Skip to content

Commit 970feea

Browse files
committed
Implement Middleware Aliases
commit da31230 Author: Joe Lambert <[email protected]> Date: Fri Jul 19 12:05:34 2019 +0100 Switch to production version of `rareloop/router` commit b85b4ab Author: Joe Lambert <[email protected]> Date: Wed Apr 10 20:56:02 2019 +0100 Add Facade to access bound `MiddlewareAliasStore` commit db1e0ac Author: Joe Lambert <[email protected]> Date: Wed Apr 10 20:51:44 2019 +0100 Refactor new interface names commit 64e3426 Author: Joe Lambert <[email protected]> Date: Tue Apr 9 21:47:39 2019 +0100 Enable middleware aliases on WordPress Controllers commit 3fe8fc6 Author: Joe Lambert <[email protected]> Date: Tue Apr 9 21:14:39 2019 +0100 Create & use MiddlewareResolver in the Router commit b8e930e Author: Joe Lambert <[email protected]> Date: Tue Apr 9 20:55:09 2019 +0100 Implement MiddlewareAliasStore
1 parent 095bca8 commit 970feea

12 files changed

+449
-7
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"require": {
66
"php": ">=7.1.0",
77
"php-di/php-di": "^6.0.0",
8-
"rareloop/router": "^4.2.0",
8+
"rareloop/router": "^4.3.0",
99
"psr/container": "^1.0",
1010
"psr/http-message": "^1.0",
1111
"psr/http-server-middleware": "^1.0",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Contracts;
4+
5+
interface MiddlewareAliases
6+
{
7+
public function set(string $name, $middleware);
8+
public function get(string $name);
9+
public function has(string $name) : bool;
10+
}

src/Facades/MiddlewareAliases.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Facades;
4+
5+
use Blast\Facades\AbstractFacade;
6+
7+
class MiddlewareAliases extends AbstractFacade
8+
{
9+
protected static function accessor()
10+
{
11+
return 'middleware-alias-store';
12+
}
13+
}

src/Http/MiddlewareAliasStore.php

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Http;
4+
5+
use Closure;
6+
use Psr\Container\ContainerInterface;
7+
use Rareloop\Lumberjack\Contracts\MiddlewareAliases;
8+
9+
class MiddlewareAliasStore implements MiddlewareAliases
10+
{
11+
protected $aliases = [];
12+
13+
public function set(string $name, $middleware)
14+
{
15+
$this->aliases[$name] = $middleware;
16+
}
17+
18+
public function get(string $name)
19+
{
20+
list($name, $params) = $this->parseName($name);
21+
22+
$middleware = $this->aliases[$name];
23+
24+
if ($middleware instanceof Closure) {
25+
$middleware = $middleware(...$params);
26+
}
27+
28+
if (is_string($middleware) && class_exists($middleware)) {
29+
$middleware = new $middleware(...$params);
30+
}
31+
32+
return $middleware;
33+
}
34+
35+
protected function parseName($name) : array
36+
{
37+
list($name, $params) = array_pad(explode(':', $name), 2, '');
38+
39+
$params = explode(',', $params);
40+
41+
return [$name, $params];
42+
}
43+
44+
public function has(string $name) : bool
45+
{
46+
list($name, $params) = $this->parseName($name);
47+
48+
return isset($this->aliases[$name]);
49+
}
50+
}

src/Http/MiddlewareResolver.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Http;
4+
5+
use Psr\Container\ContainerInterface;
6+
use Rareloop\Lumberjack\Contracts\MiddlewareAliases;
7+
use Rareloop\Router\MiddlewareResolver as MiddlewareResolverInterface;
8+
9+
class MiddlewareResolver implements MiddlewareResolverInterface
10+
{
11+
protected $app;
12+
protected $store;
13+
14+
public function __construct(ContainerInterface $app, MiddlewareAliases $store)
15+
{
16+
$this->app = $app;
17+
$this->store = $store;
18+
}
19+
20+
public function resolve($name)
21+
{
22+
if (!is_string($name)) {
23+
return $name;
24+
}
25+
26+
if ($this->store->has($name)) {
27+
return $this->store->get($name);
28+
}
29+
30+
return $this->app->get($name);
31+
}
32+
}

src/Providers/RouterServiceProvider.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,32 @@
33
namespace Rareloop\Lumberjack\Providers;
44

55
use Psr\Http\Message\RequestInterface;
6-
use Rareloop\Lumberjack\Http\ServerRequest;
6+
use Rareloop\Lumberjack\Contracts\MiddlewareAliases;
7+
use Rareloop\Lumberjack\Http\MiddlewareAliasStore;
8+
use Rareloop\Lumberjack\Http\MiddlewareResolver;
79
use Rareloop\Lumberjack\Http\Router;
10+
use Rareloop\Lumberjack\Http\ServerRequest;
11+
use Rareloop\Router\MiddlewareResolver as MiddlewareResolverInterface;
812
use Zend\Diactoros\ServerRequestFactory;
913

1014
class RouterServiceProvider extends ServiceProvider
1115
{
1216
public function register()
1317
{
14-
$router = new Router($this->app);
18+
$store = new MiddlewareAliasStore;
19+
$resolver = new MiddlewareResolver($this->app, $store);
20+
21+
$router = new Router($this->app, $resolver);
1522
$router->setBasePath($this->getBasePathFromWPConfig());
1623

1724
$this->app->bind('router', $router);
1825
$this->app->bind(Router::class, $router);
26+
27+
$this->app->bind('middleware-alias-store', $store);
28+
$this->app->bind(MiddlewareAliases::class, $store);
29+
30+
$this->app->bind('middleware-resolver', $resolver);
31+
$this->app->bind(MiddlewareResolverInterface::class, $resolver);
1932
}
2033

2134
public function boot()

src/Providers/WordPressControllersServiceProvider.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function handleRequest(RequestInterface $request, $controllerName, $metho
7979
return $cm->excludedForMethod($methodName);
8080
})->map(function ($cm) {
8181
return $cm->middleware();
82-
});
82+
})->all();
8383
}
8484

8585
$middlewares[] = function ($request) use ($controller, $methodName) {
@@ -88,7 +88,20 @@ public function handleRequest(RequestInterface $request, $controllerName, $metho
8888
return ResponseFactory::create($output, $request);
8989
};
9090

91-
$dispatcher = new Dispatcher($middlewares);
91+
$dispatcher = $this->createDispatcher($middlewares);
9292
return $dispatcher->dispatch($request);
9393
}
94+
95+
private function createDispatcher(array $middlewares) : Dispatcher
96+
{
97+
$resolver = null;
98+
99+
if ($this->app->has('middleware-resolver')) {
100+
$resolver = function ($name) {
101+
return $this->app->get('middleware-resolver')->resolve($name);
102+
};
103+
}
104+
105+
return new Dispatcher($middlewares, $resolver);
106+
}
94107
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Test\Facades;
4+
5+
use Blast\Facades\FacadeFactory;
6+
use PHPUnit\Framework\TestCase;
7+
use Rareloop\Lumberjack\Application;
8+
use Rareloop\Lumberjack\Facades\MiddlewareAliases;
9+
use Rareloop\Lumberjack\Http\MiddlewareAliasStore;
10+
11+
class MiddlewareAliasesTest extends TestCase
12+
{
13+
/** @test */
14+
public function test_facade()
15+
{
16+
$app = new Application();
17+
FacadeFactory::setContainer($app);
18+
19+
$store = new MiddlewareAliasStore();
20+
$app->bind('middleware-alias-store', $store);
21+
22+
$this->assertInstanceOf(MiddlewareAliasStore::class, MiddlewareAliases::__instance());
23+
$this->assertSame($store, MiddlewareAliases::__instance());
24+
}
25+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Test\Http;
4+
5+
use Mockery;
6+
use PHPUnit\Framework\TestCase;
7+
use Psr\Http\Server\MiddlewareInterface;
8+
use Rareloop\Lumberjack\Application;
9+
use Rareloop\Lumberjack\Http\MiddlewareAliasStore;
10+
11+
class MiddlewareAliasStoreTest extends TestCase
12+
{
13+
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
14+
15+
/** @test */
16+
public function can_register_an_alias_for_a_middleware_object()
17+
{
18+
$store = new MiddlewareAliasStore;
19+
$middleware = Mockery::mock(MiddlewareInterface::class);
20+
21+
$store->set('middlewarekey', $middleware);
22+
23+
$this->assertSame($middleware, $store->get('middlewarekey'));
24+
}
25+
26+
/** @test */
27+
public function can_register_an_alias_for_a_middleware_closure_factory()
28+
{
29+
$store = new MiddlewareAliasStore;
30+
$middleware = Mockery::mock(MiddlewareInterface::class);
31+
32+
$store->set('middlewarekey', function () use ($middleware) {
33+
return $middleware;
34+
});
35+
36+
$this->assertSame($middleware, $store->get('middlewarekey'));
37+
}
38+
39+
/** @test */
40+
public function can_register_an_alias_for_a_classname()
41+
{
42+
$store = new MiddlewareAliasStore();
43+
44+
$store->set('middlewarekey', MASTestClass::class);
45+
46+
$this->assertInstanceOf(MASTestClass::class, $store->get('middlewarekey'));
47+
}
48+
49+
/** @test */
50+
public function can_register_an_alias_with_params_for_a_middleware_closure_factory()
51+
{
52+
$store = new MiddlewareAliasStore;
53+
$middleware = Mockery::mock(MiddlewareInterface::class);
54+
55+
$store->set('middlewarekey', function ($param1, $param2) use ($middleware) {
56+
$this->assertSame('123', $param1);
57+
$this->assertSame('abc', $param2);
58+
return $middleware;
59+
});
60+
61+
$this->assertSame($middleware, $store->get('middlewarekey:123,abc'));
62+
}
63+
64+
/** @test */
65+
public function can_register_an_alias_with_params_for_a_classname()
66+
{
67+
$store = new MiddlewareAliasStore;
68+
69+
$store->set('middlewarekey', MASTestClassWithConstructorParams::class);
70+
$middleware = $store->get('middlewarekey:123,abc');
71+
72+
$this->assertInstanceOf(MASTestClassWithConstructorParams::class, $middleware);
73+
$this->assertSame('123', $middleware->param1);
74+
$this->assertSame('abc', $middleware->param2);
75+
}
76+
77+
/** @test */
78+
public function can_check_if_alias_exists()
79+
{
80+
$store = new MiddlewareAliasStore;
81+
$middleware = Mockery::mock(MiddlewareInterface::class);
82+
83+
$this->assertFalse($store->has('middlewarekey'));
84+
85+
$store->set('middlewarekey', $middleware);
86+
87+
$this->assertTrue($store->has('middlewarekey'));
88+
}
89+
90+
/** @test */
91+
public function can_check_if_alias_exists_when_string_contains_params()
92+
{
93+
$store = new MiddlewareAliasStore;
94+
$middleware = Mockery::mock(MiddlewareInterface::class);
95+
96+
$this->assertFalse($store->has('middlewarekey'));
97+
98+
$store->set('middlewarekey', $middleware);
99+
100+
$this->assertTrue($store->has('middlewarekey:param1,param2'));
101+
}
102+
}
103+
104+
class MASTestClass
105+
{
106+
107+
}
108+
109+
class MASTestClassWithConstructorParams
110+
{
111+
public $param1;
112+
public $param2;
113+
114+
public function __construct($param1, $param2)
115+
{
116+
$this->param1 = $param1;
117+
$this->param2 = $param2;
118+
}
119+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Rareloop\Lumberjack\Test\Http;
4+
5+
use Mockery;
6+
use PHPUnit\Framework\TestCase;
7+
use Rareloop\Lumberjack\Application;
8+
use Rareloop\Lumberjack\Contracts\MiddlewareAliases;
9+
use Rareloop\Lumberjack\Http\MiddlewareAliasStore;
10+
use Rareloop\Lumberjack\Http\MiddlewareResolver;
11+
12+
class MiddlewareResolverTest extends TestCase
13+
{
14+
use \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
15+
16+
/** @test */
17+
public function can_resolve_a_key_from_the_container()
18+
{
19+
$app = new Application;
20+
$resolver = new MiddlewareResolver($app, new MiddlewareAliasStore);
21+
22+
$datetime = new \DateTime;
23+
$app->bind('datetime', $datetime);
24+
25+
$this->assertSame($datetime, $resolver->resolve('datetime'));
26+
}
27+
28+
/** @test */
29+
public function can_resolve_an_object_from_a_classname_from_the_container()
30+
{
31+
$app = new Application;
32+
$resolver = new MiddlewareResolver($app, new MiddlewareAliasStore);
33+
34+
$this->assertInstanceOf(MRTestClass::class, $resolver->resolve(MRTestClass::class));
35+
}
36+
37+
/** @test */
38+
public function can_resolve_a_middleware_alias()
39+
{
40+
$app = new Application;
41+
$store = Mockery::mock(MiddlewareAliases::class);
42+
$store->shouldReceive('has')->with('middlewarekey')->once()->andReturn(true);
43+
$store->shouldReceive('get')->with('middlewarekey')->once()->andReturn(new MRTestClass);
44+
$resolver = new MiddlewareResolver($app, $store);
45+
46+
$this->assertInstanceOf(MRTestClass::class, $resolver->resolve('middlewarekey'));
47+
}
48+
49+
/** @test */
50+
public function non_string_values_are_returned_as_is()
51+
{
52+
$app = new Application;
53+
$resolver = new MiddlewareResolver($app, new MiddlewareAliasStore);
54+
55+
$datetime = new \DateTime;
56+
57+
$this->assertSame($datetime, $resolver->resolve($datetime));
58+
}
59+
}
60+
61+
class MRTestClass
62+
{
63+
64+
}

0 commit comments

Comments
 (0)