Skip to content

Commit 2b86f68

Browse files
committed
Stack compatible now. Can acts like middleware and apply middlewares as filter
1 parent 2d2fc4b commit 2b86f68

File tree

6 files changed

+163
-13
lines changed

6 files changed

+163
-13
lines changed

lib/Exception/ExceptionInterface.php

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace wmlib\controller\Exception;
3+
4+
class NotFoundException extends \Exception
5+
{
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace wmlib\controller\Exception;
3+
4+
class RouteNotFoundException extends NotFoundException
5+
{
6+
}

lib/Filter/Middleware.php

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,92 @@
11
<?php
22
namespace wmlib\controller\Filter;
33

4+
use Symfony\Component\HttpKernel\HttpKernelInterface;
45
use wmlib\controller\Filter;
56

7+
use wmlib\controller\Request;
68
use wmlib\controller\Response;
79
use wmlib\controller\Route;
810

11+
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
12+
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
13+
use wmlib\controller\Stream\String;
14+
915
/**
1016
* Middlewares support.
1117
* Filter can reuse any Symfony HttpKernelInterface middleware
1218
*
1319
*/
1420
class Middleware extends Filter
1521
{
16-
public function __construct(HttpKernelInterface $middleware){
22+
/**
23+
* @var HttpKernelInterface
24+
*/
25+
private $middleware;
26+
27+
private $exclusive;
28+
29+
/**
30+
* @param HttpKernelInterface $middleware
31+
* @param bool $exclusive True is filter should use middleware response in ex way and pass all next's filters and route
32+
*/
33+
public function __construct(HttpKernelInterface $middleware, $exclusive = true)
34+
{
35+
$this->middleware = $middleware;
36+
$this->exclusive = $exclusive;
37+
}
38+
39+
/**
40+
* Pre filter method
41+
*
42+
* For process the rest of filter chain this code should be call inside:
43+
* <code>
44+
* $filterChain->doPreFilter ();
45+
* </code>
46+
*
47+
* @param Request $request
48+
* @param Response $response
49+
* @param Chain $filterChain
50+
* @return Response|null
51+
*/
52+
public function doPreFilter(Request $request, Response $response, Chain $filterChain)
53+
{
54+
$symphony_response = $this->middleware->handle($this->decorateRequest($request), HttpKernelInterface::MASTER_REQUEST, false);
55+
56+
$response = $this->mergeResponse($response, $symphony_response);
57+
58+
if ($this->exclusive) {
59+
return $response;
60+
}
61+
return $filterChain->doPreFilter($request, $response);
62+
}
63+
64+
/**
65+
* Decorate lib request to symfony request
66+
*
67+
* @param Request $request
68+
* @return SymfonyRequest
69+
*/
70+
private function decorateRequest(Request $request)
71+
{
72+
$symfony_request = new SymfonyRequest($request->getQueryParams(), $request->getBodyParams(), $request->getAttributes(), $request->getCookies());
73+
74+
return $symfony_request;
75+
}
1776

77+
/**
78+
* Merge symfony response to lib response
79+
*
80+
* @param Response $response
81+
* @param SymfonyResponse $symfonyResponse
82+
* @return Response
83+
*/
84+
private function mergeResponse(Response $response, SymfonyResponse $symfonyResponse)
85+
{
86+
foreach($symfonyResponse->headers as $header => $line) {
87+
$response = $response->withHeader($header, $line);
88+
}
89+
$response = $response->withBody(new String($symfonyResponse->getContent()));
90+
return $response;
1891
}
1992
}

lib/Middleware.php

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
namespace wmlib\controller;
3+
4+
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
5+
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
6+
use Symfony\Component\HttpKernel\HttpKernelInterface;
7+
use wmlib\controller\Exception\RouteNotFoundException;
8+
9+
10+
/**
11+
* This StackPHP middleware creates a middleware from a root router.
12+
* If no request is found, control is passed to the next middleware.
13+
*
14+
*/
15+
class Middleware implements HttpKernelInterface
16+
{
17+
/**
18+
* @var HttpKernelInterface
19+
*/
20+
private $next;
21+
22+
/**
23+
* @var Router
24+
*/
25+
private $router;
26+
27+
/**
28+
*
29+
* @param HttpKernelInterface $next The next application the request will be forwarded to if not handled by this
30+
* @param Router $router Router to handle
31+
*/
32+
public function __construct(HttpKernelInterface $next, Router $router) {
33+
$this->next = $next;
34+
$this->router = $router;
35+
}
36+
37+
38+
/**
39+
* Handles a Request to convert it to a Response.
40+
*
41+
* When $catch is true, the implementation must catch all exceptions
42+
* and do its best to convert them to a Response instance.
43+
*
44+
* @param SymfonyRequest $symfonyRequest A Request instance
45+
* @param int $type The type of the request
46+
* (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
47+
* @param bool $catch Whether to catch exceptions or not
48+
*
49+
* @return SymfonyResponse A Response instance
50+
*
51+
* @throws \Exception When an Exception occurs during processing
52+
*
53+
* @api
54+
*/
55+
public function handle(SymfonyRequest $symfonyRequest, $type = self::MASTER_REQUEST, $catch = true)
56+
{
57+
// create lib request from Symfony request
58+
$request = new Request(new Url($symfonyRequest->getBaseUrl()), new Url($symfonyRequest->getRequestUri()), $symfonyRequest->getMethod());
59+
$response = new Response($request);
60+
try {
61+
$response = $this->router->dispatch($request, $response);
62+
63+
return new SymfonyResponse($response->getBody()->getContents(), $response->getStatusCode(), $response->getHeaders());
64+
65+
} catch (RouteNotFoundException $e) {
66+
return $this->next->handle($symfonyRequest, $type, $catch);
67+
} catch (\Exception $e) {
68+
if ($catch) {
69+
// handle exception to response
70+
} else throw $e;
71+
}
72+
}
73+
}

lib/Router.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
namespace wmlib\controller;
33

44

5+
use wmlib\controller\Exception\RouteNotFoundException;
6+
57
class Router extends Route
68
{
79
const URI_DELIMITER = '/';
@@ -476,7 +478,7 @@ public function url($uri)
476478
* @param Request $request
477479
* @param Response $response
478480
* @return Response
479-
* @throws \Exception
481+
* @throws RouteNotFoundException
480482
*/
481483
protected function dispatchHome(Request $request, Response $response)
482484
{
@@ -491,7 +493,7 @@ protected function dispatchHome(Request $request, Response $response)
491493
}
492494
}
493495

494-
throw new \Exception(sprintf('No matched route found for %s app[%s], "%s" existed', $look_for, get_class($this),
496+
throw new RouteNotFoundException(sprintf('No matched route found for %s app[%s], "%s" existed', $look_for, get_class($this),
495497
implode(', ', $patterns)));
496498

497499
return $response;

0 commit comments

Comments
 (0)