Skip to content

Commit e74a421

Browse files
committed
v1.0 prerelease
1 parent 815f564 commit e74a421

38 files changed

+636
-115
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
},
3535
"autoload-dev": {
3636
"psr-4": {
37-
"Micro\\Plugin\\Http\\Tests\\": "tests/"
37+
"Micro\\Plugin\\Http\\Test\\": "tests/"
3838
}
3939
},
4040
"config": {

src/Business/Executor/RouteExecutor.php

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515

1616
use Micro\Component\DependencyInjection\ContainerRegistryInterface;
1717
use Micro\Plugin\Http\Business\Matcher\UrlMatcherInterface;
18-
use Micro\Plugin\Http\Business\Response\ResponseCallbackFactoryInterface;
18+
use Micro\Plugin\Http\Business\Response\Callback\ResponseCallbackFactoryInterface;
19+
use Micro\Plugin\Http\Business\Response\Transformer\ResponseTransformerFactoryInterface;
20+
use Micro\Plugin\Http\Exception\HttpException;
1921
use Micro\Plugin\Http\Exception\HttpInternalServerException;
20-
use Micro\Plugin\Http\Exception\ResponseInvalidException;
2122
use Symfony\Component\HttpFoundation\Request;
2223
use Symfony\Component\HttpFoundation\Response;
2324

@@ -29,7 +30,8 @@
2930
public function __construct(
3031
private UrlMatcherInterface $urlMatcher,
3132
private ContainerRegistryInterface $containerRegistry,
32-
private ResponseCallbackFactoryInterface $responseCallbackFactory
33+
private ResponseCallbackFactoryInterface $responseCallbackFactory,
34+
private ResponseTransformerFactoryInterface $responseTransformerFactory
3335
) {
3436
}
3537

@@ -40,12 +42,15 @@ public function execute(Request $request, bool $flush = true): Response
4042
{
4143
$route = $this->urlMatcher->match($request);
4244
$this->containerRegistry->register(Request::class, fn (): Request => $request);
43-
4445
$callback = $this->responseCallbackFactory->create($route);
46+
4547
try {
4648
$response = $callback();
47-
} catch (ResponseInvalidException $exception) {
48-
throw new HttpInternalServerException($request, $exception);
49+
$response = $this->generateResponse($request, $response);
50+
} catch (HttpException $exception) {
51+
throw $exception;
52+
} catch (\Throwable $exception) {
53+
$response = $this->generateResponse($request, $exception, false);
4954
}
5055

5156
if ($flush) {
@@ -54,4 +59,36 @@ public function execute(Request $request, bool $flush = true): Response
5459

5560
return $response;
5661
}
62+
63+
protected function generateResponse(Request $request, mixed $responseData, bool $tryIfThrowNoHttpException = true): Response
64+
{
65+
if ($responseData instanceof Response) {
66+
return $responseData;
67+
}
68+
69+
$response = new Response();
70+
try {
71+
$transformed = $this->responseTransformerFactory
72+
->create()
73+
->transform(
74+
$request,
75+
$response,
76+
$responseData
77+
);
78+
} catch (HttpException $exception) {
79+
throw $exception;
80+
} catch (\Throwable $exception) {
81+
if ($tryIfThrowNoHttpException) {
82+
return $this->generateResponse($request, $exception, false);
83+
}
84+
85+
throw new HttpInternalServerException('Internal Server Error.', $exception);
86+
}
87+
88+
if (!$transformed) {
89+
throw new HttpInternalServerException();
90+
}
91+
92+
return $response;
93+
}
5794
}

src/Business/Executor/RouteExecutorFactory.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515

1616
use Micro\Component\DependencyInjection\ContainerRegistryInterface;
1717
use Micro\Plugin\Http\Business\Matcher\UrlMatcherFactoryInterface;
18-
use Micro\Plugin\Http\Business\Response\ResponseCallbackFactoryInterface;
18+
use Micro\Plugin\Http\Business\Response\Callback\ResponseCallbackFactoryInterface;
19+
use Micro\Plugin\Http\Business\Response\Transformer\ResponseTransformerFactoryInterface;
1920

2021
/**
2122
* @author Stanislau Komar <[email protected]>
@@ -25,7 +26,8 @@
2526
public function __construct(
2627
private UrlMatcherFactoryInterface $urlMatcherFactory,
2728
private ContainerRegistryInterface $containerRegistry,
28-
private ResponseCallbackFactoryInterface $responseCallbackFactory
29+
private ResponseCallbackFactoryInterface $responseCallbackFactory,
30+
private ResponseTransformerFactoryInterface $responseTransformerFactory
2931
) {
3032
}
3133

@@ -37,7 +39,8 @@ public function create(): RouteExecutorInterface
3739
return new RouteExecutor(
3840
$this->urlMatcherFactory->create(),
3941
$this->containerRegistry,
40-
$this->responseCallbackFactory
42+
$this->responseCallbackFactory,
43+
$this->responseTransformerFactory
4144
);
4245
}
4346
}

src/Business/Matcher/UrlMatcher.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,6 @@ public function match(Request $request): RouteInterface
4343
return $route;
4444
}
4545

46-
throw new HttpNotFoundException($request);
46+
throw new HttpNotFoundException();
4747
}
4848
}

src/Business/Response/ResponseCallback.php renamed to src/Business/Response/Callback/ResponseCallback.php

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@
1111
* file that was distributed with this source code.
1212
*/
1313

14-
namespace Micro\Plugin\Http\Business\Response;
14+
namespace Micro\Plugin\Http\Business\Response\Callback;
1515

1616
use Micro\Component\DependencyInjection\Autowire\AutowireHelperInterface;
1717
use Micro\Plugin\Http\Business\Route\RouteInterface;
18-
use Micro\Plugin\Http\Exception\ResponseInvalidException;
1918
use Micro\Plugin\Http\Exception\RouteInvalidConfigurationException;
20-
use Symfony\Component\HttpFoundation\Response;
2119

2220
/**
2321
* @author Stanislau Komar <[email protected]>
@@ -33,9 +31,15 @@ public function __construct(
3331
/**
3432
* {@inheritDoc}
3533
*/
36-
public function __invoke(): Response
34+
public function __invoke(): mixed
3735
{
3836
$controller = $this->route->getController();
37+
if (\is_callable($controller)) {
38+
$callback = $this->autowireHelper->autowire($controller);
39+
40+
return $callback();
41+
}
42+
3943
$classController = $controller;
4044
$classMethod = $this->route->getName();
4145

@@ -59,13 +63,7 @@ public function __invoke(): Response
5963

6064
$controller = [$classController, $classMethod];
6165

62-
$response = \call_user_func($this->autowireHelper->autowire($controller));
63-
64-
if ($response instanceof Response) {
65-
return $response;
66-
}
67-
68-
throw new ResponseInvalidException($response);
66+
return \call_user_func($this->autowireHelper->autowire($controller));
6967
}
7068

7169
protected function snakeToCamel(string $str): string

src/Business/Response/ResponseCallbackFactory.php renamed to src/Business/Response/Callback/ResponseCallbackFactory.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* file that was distributed with this source code.
1212
*/
1313

14-
namespace Micro\Plugin\Http\Business\Response;
14+
namespace Micro\Plugin\Http\Business\Response\Callback;
1515

1616
use Micro\Component\DependencyInjection\Autowire\AutowireHelperFactoryInterface;
1717
use Micro\Plugin\Http\Business\Route\RouteInterface;
@@ -26,14 +26,11 @@ public function __construct(
2626
) {
2727
}
2828

29-
/**
30-
* {@inheritDoc}
31-
*/
3229
public function create(RouteInterface $route): ResponseCallbackInterface
3330
{
3431
return new ResponseCallback(
3532
$this->autowireHelperFactory->create(),
36-
$route
33+
$route,
3734
);
3835
}
3936
}

src/Business/Response/ResponseCallbackFactoryInterface.php renamed to src/Business/Response/Callback/ResponseCallbackFactoryInterface.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* file that was distributed with this source code.
1212
*/
1313

14-
namespace Micro\Plugin\Http\Business\Response;
14+
namespace Micro\Plugin\Http\Business\Response\Callback;
1515

1616
use Micro\Plugin\Http\Business\Route\RouteInterface;
1717

src/Business/Response/ResponseCallbackInterface.php renamed to src/Business/Response/Callback/ResponseCallbackInterface.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,10 @@
1111
* file that was distributed with this source code.
1212
*/
1313

14-
namespace Micro\Plugin\Http\Business\Response;
14+
namespace Micro\Plugin\Http\Business\Response\Callback;
1515

1616
use Micro\Plugin\Http\Exception\HttpException;
1717
use Micro\Plugin\Http\Exception\ResponseInvalidException;
18-
use Symfony\Component\HttpFoundation\Response;
1918

2019
/**
2120
* @author Stanislau Komar <[email protected]>
@@ -26,5 +25,5 @@ interface ResponseCallbackInterface
2625
* @throws ResponseInvalidException
2726
* @throws HttpException
2827
*/
29-
public function __invoke(): Response;
28+
public function __invoke(): mixed;
3029
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Micro framework package.
7+
*
8+
* (c) Stanislau Komar <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Micro\Plugin\Http\Business\Response\Transformer;
15+
16+
use Symfony\Component\HttpFoundation\Request;
17+
use Symfony\Component\HttpFoundation\Response;
18+
19+
/**
20+
* @author Stanislau Komar <[email protected]>
21+
*/
22+
readonly class ResponseTransformer implements ResponseTransformerInterface
23+
{
24+
/**
25+
* @param iterable<ResponseTransformerInterface> $responseTransformersCollection
26+
*/
27+
public function __construct(
28+
private iterable $responseTransformersCollection
29+
) {
30+
}
31+
32+
/**
33+
* {@inheritDoc}
34+
*/
35+
public function transform(Request $request, Response $response, mixed &$responseData): bool
36+
{
37+
$transformed = false;
38+
39+
foreach ($this->responseTransformersCollection as $responseTransformer) {
40+
$isTransformed = $responseTransformer->transform($request, $response, $responseData);
41+
if (false === $isTransformed) {
42+
continue;
43+
}
44+
45+
$transformed = true;
46+
}
47+
48+
return $transformed;
49+
}
50+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* This file is part of the Micro framework package.
7+
*
8+
* (c) Stanislau Komar <[email protected]>
9+
*
10+
* For the full copyright and license information, please view the LICENSE
11+
* file that was distributed with this source code.
12+
*/
13+
14+
namespace Micro\Plugin\Http\Business\Response\Transformer;
15+
16+
use Micro\Framework\Kernel\KernelInterface;
17+
use Micro\Plugin\Http\Plugin\HttpResponseTransformerPlugin;
18+
19+
/**
20+
* @author Stanislau Komar <[email protected]>
21+
*/
22+
readonly class ResponseTransformerFactory implements ResponseTransformerFactoryInterface
23+
{
24+
public function __construct(
25+
private KernelInterface $kernel
26+
) {
27+
}
28+
29+
public function create(): ResponseTransformerInterface
30+
{
31+
$transformers = [];
32+
$iterator = $this->kernel->plugins(HttpResponseTransformerPlugin::class);
33+
/** @var HttpResponseTransformerPlugin $plugin */
34+
foreach ($iterator as $plugin) {
35+
$transformers[$plugin->weight()] = $plugin->createTransformer();
36+
}
37+
38+
krsort($transformers);
39+
40+
return new ResponseTransformer(array_values($transformers));
41+
}
42+
}

0 commit comments

Comments
 (0)