Skip to content

Commit 19ec43f

Browse files
authored
Merge pull request #8 from Micro-PHP/v1.6.0-release
V1.6.0 release
2 parents 951b977 + bfe2fbe commit 19ec43f

File tree

11 files changed

+155
-43
lines changed

11 files changed

+155
-43
lines changed

composer.json

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@
1010
}
1111
],
1212
"require": {
13-
"micro/autowire": "^1",
14-
"micro/kernel": "^1",
15-
"micro/kernel-app": "^1",
16-
"micro/kernel-boot-configuration": "^1",
17-
"micro/kernel-boot-dependency": "^1",
18-
"micro/kernel-boot-plugin-depended": "^1",
19-
"micro/plugin-locator": "^1",
13+
"micro/autowire": "^1.6",
14+
"micro/kernel": "^1.6",
15+
"micro/kernel-boot-configuration": "^1.6",
16+
"micro/kernel-boot-dependency": "^1.6",
17+
"micro/kernel-boot-plugin-depended": "^1.6",
18+
"micro/plugin-locator": "^1.6",
2019
"symfony/http-foundation": "^6.2"
2120
},
2221
"require-dev": {
2322
"ergebnis/composer-normalize": "^2.29",
2423
"friendsofphp/php-cs-fixer": "^3.13",
24+
"micro/kernel-app": "^1.6",
2525
"phpstan/phpstan": "^1.9",
2626
"phpunit/php-code-coverage": "^9.2",
2727
"phpunit/phpunit": "^9.5",
2828
"vimeo/psalm": "^5.2"
2929
},
30+
"minimum-stability": "dev",
3031
"autoload": {
3132
"psr-4": {
3233
"Micro\\Plugin\\Http\\": "src/"

phpunit.xml.dist

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,11 @@
1616
<directory>tests/Unit</directory>
1717
</testsuite>
1818
</testsuites>
19-
<filter>
20-
<whitelist>
21-
<directory suffix=".php">src/</directory>
22-
<exclude>
23-
<directory>src/Exception</directory>
24-
<file>src/HttpCorePlugin.php</file>
25-
</exclude>
26-
</whitelist>
27-
</filter>
2819
<coverage>
20+
<exclude>
21+
<directory>src/Exception</directory>
22+
<file>src/HttpCorePlugin.php</file>
23+
</exclude>
2924
<include>
3025
<directory suffix=".php">src</directory>
3126
</include>

src/Business/Matcher/Route/Matchers/UriMatcher.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,13 @@ class UriMatcher implements RouteMatcherInterface
2727
*/
2828
public function match(RouteInterface $route, Request $request): bool
2929
{
30-
$requestUri = $request->getRequestUri();
30+
$pathInfo = $request->getPathInfo();
3131
$pattern = $route->getPattern();
3232
if (!$pattern) {
33-
return $requestUri === $route->getUri();
33+
return $pathInfo === $route->getUri();
3434
}
3535

36-
$matched = preg_match_all($pattern, $requestUri, $matches);
36+
$matched = preg_match_all($pattern, $pathInfo, $matches);
3737

3838
if (0 === $matched) {
3939
return false;

src/Business/Response/Callback/ResponseCallback.php

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public function __construct(
3434
public function __invoke(): mixed
3535
{
3636
$controller = $this->route->getController();
37+
$routeName = $this->route->getName() ?? $this->route->getUri();
38+
3739
if (\is_callable($controller)) {
3840
$callback = $this->autowireHelper->autowire($controller);
3941

@@ -48,16 +50,22 @@ public function __invoke(): mixed
4850
}
4951

5052
if (\is_array($controller)) {
53+
$controller = array_filter($controller);
5154
if (!\count($controller)) {
52-
throw new RouteInvalidConfigurationException($this->route->getName() ?? $this->route->getUri(), ['Controller is not defined.']);
55+
throw new RouteInvalidConfigurationException($routeName, ['Controller is not defined.']);
5356
}
57+
5458
$classController = $controller[0];
55-
$classMethod = $controller[1] ?? $this->snakeToCamel($this->route->getName() ?? '');
59+
$classMethod = !empty($controller[1]) ? $controller[1] : $this->snakeToCamel($this->route->getName() ?? '');
5660
}
5761

5862
/* @psalm-suppress RedundantConditionGivenDocblockType */
5963
if (!\is_object($classController)) {
60-
/** @psalm-suppress PossiblyNullArgument */
64+
/**
65+
* @psalm-suppress PossiblyNullArgument
66+
*
67+
* @phpstan-ignore-next-line
68+
*/
6169
$classController = $this->autowireHelper->autowire($classController)();
6270
}
6371

@@ -68,6 +76,6 @@ public function __invoke(): mixed
6876

6977
protected function snakeToCamel(string $str): string
7078
{
71-
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $str))));
79+
return lcfirst(str_replace(' ', '', ucwords(str_replace(['_', '-'], [' ', ' '], $str))));
7280
}
7381
}

src/Business/Route/RouteBuilder.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,11 +152,11 @@ public function build(): RouteInterface
152152
$pattern = null;
153153
$parameters = null;
154154
/** @psalm-suppress PossiblyNullArgument */
155-
$isDynamic = preg_match_all('/\{\s*([^}\s]*)\s*\}/', $this->uri, $matches);
155+
$isDynamic = preg_match_all('/\{\s*([^}\s]*)\s*}/', $this->uri, $matches);
156156
if ($isDynamic) {
157157
$parameters = $matches[1];
158158
/** @psalm-suppress PossiblyNullArgument */
159-
$pattern = '/'.addcslashes($this->uri, '/.').'/';
159+
$pattern = '/'.addcslashes($this->uri, '/.').'$/';
160160

161161
foreach ($matches[0] as $replaced) {
162162
$pattern = str_replace($replaced, '(.[aA-zZ0-9-_]+)', $pattern);
@@ -185,5 +185,6 @@ protected function clear(): void
185185
$this->uri = null;
186186
$this->action = null;
187187
$this->methods = $this->methodsByDefault;
188+
$this->name = null;
188189
}
189190
}

tests/Unit/Business/Locator/RouteLocatorFactoryTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ protected function createKernel(string $locatorAlias, bool $isLocatorNotFound):
7575
->expects($this->once())
7676
->method('plugins')
7777
->with(HttpRouteLocatorPluginInterface::class)
78-
->willReturn([$stubLocator]);
78+
->willReturn(new \ArrayObject([$stubLocator]));
7979

8080
return $stubKernel;
8181
}

tests/Unit/Business/Matcher/Route/Matchers/UriMatcherTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public function testMatch(string $requestUri, string $routeUri, string|null $rou
4747
$requestMock = $this->createMock(Request::class);
4848
$requestMock
4949
->expects($this->once())
50-
->method('getRequestUri')
50+
->method('getPathInfo')
5151
->willReturn($requestUri);
5252

5353
$actual = $matcher->match(

tests/Unit/Business/Response/CallbackTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@
2020
*/
2121
class CallbackTest
2222
{
23+
public function __invoke(): Response
24+
{
25+
return new Response();
26+
}
27+
2328
public function helloWithResponse(): Response
2429
{
2530
return new Response();

tests/Unit/Business/Response/ResponseCallbackTest.php

Lines changed: 96 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Micro\Component\DependencyInjection\Autowire\AutowireHelperInterface;
1515
use Micro\Plugin\Http\Business\Response\Callback\ResponseCallback;
1616
use Micro\Plugin\Http\Business\Route\RouteInterface;
17+
use Micro\Plugin\Http\Exception\RouteInvalidConfigurationException;
1718
use PHPUnit\Framework\TestCase;
1819
use Symfony\Component\HttpFoundation\Response;
1920

@@ -22,18 +23,26 @@ class ResponseCallbackTest extends TestCase
2223
/**
2324
* @dataProvider dataProvider
2425
*/
25-
public function testInvoke(mixed $callable)
26-
{
26+
public function testInvoke(
27+
mixed $routeController,
28+
string $routeName,
29+
array $expectedAutoWireArguments,
30+
array $autowireReturns
31+
) {
2732
$route = $this->createMock(RouteInterface::class);
28-
$route
29-
->expects($this->once())
33+
$route->expects($this->once())
3034
->method('getController')
31-
->willReturn($callable);
35+
->willReturn($routeController);
36+
37+
$route->expects($this->any())
38+
->method('getName')
39+
->willReturn($routeName);
3240

3341
$autowireHelper = $this->createMock(AutowireHelperInterface::class);
3442
$autowireHelper->expects($this->any())
3543
->method('autowire')
36-
->willReturn(fn () => new Response());
44+
->withConsecutive(...$expectedAutoWireArguments)
45+
->willReturnOnConsecutiveCalls(...$autowireReturns);
3746

3847
$responseCallback = new ResponseCallback(
3948
$autowireHelper,
@@ -43,24 +52,99 @@ public function testInvoke(mixed $callable)
4352
$this->assertInstanceOf(Response::class, $responseCallback());
4453
}
4554

46-
public function dataProvider()
55+
public function dataProvider(): array
4756
{
57+
$anonymousFunction = function () { return new Response(); };
58+
$callbackTestObj = new CallbackTest();
59+
4860
return [
4961
[
50-
function () {},
62+
'routeController' => $anonymousFunction,
63+
'routeName' => 'does-not-matter',
64+
'autoWireArguments' => [[$anonymousFunction]],
65+
'autowireReturns' => [$anonymousFunction],
66+
],
67+
[
68+
'routeController' => CallbackTest::class,
69+
'routeName' => '',
70+
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, '']]],
71+
'autowireReturns' => [
72+
fn () => $callbackTestObj,
73+
[$callbackTestObj, '__invoke'],
74+
],
75+
],
76+
[
77+
'routeController' => CallbackTest::class,
78+
'routeName' => 'hello-with-response',
79+
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
80+
'autowireReturns' => [
81+
fn () => $callbackTestObj,
82+
[$callbackTestObj, 'helloWithResponse'],
83+
],
84+
],
85+
[
86+
'routeController' => [CallbackTest::class, 'helloWithResponse'],
87+
'routeName' => '',
88+
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
89+
'autowireReturns' => [
90+
fn () => $callbackTestObj,
91+
[$callbackTestObj, 'helloWithResponse'],
92+
],
5193
],
5294
[
53-
CallbackTest::class,
95+
'routeController' => CallbackTest::class.'::helloWithResponse',
96+
'routeName' => '',
97+
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
98+
'autowireReturns' => [
99+
fn () => $callbackTestObj,
100+
[$callbackTestObj, 'helloWithResponse'],
101+
],
54102
],
55103
[
56-
CallbackTest::class, 'helloWithResponse',
104+
'routeController' => [$callbackTestObj, 'helloWithResponse'],
105+
'routeName' => 'does-not-matter',
106+
'autoWireArguments' => [[[$callbackTestObj, 'helloWithResponse']]],
107+
'autowireReturn' => [
108+
[$callbackTestObj, 'helloWithResponse'],
109+
],
57110
],
58111
[
59-
CallbackTest::class.'::helloWithResponse',
112+
'routeController' => $callbackTestObj,
113+
'routeName' => '',
114+
'autoWireArguments' => [[$callbackTestObj]],
115+
'autowireReturn' => [$callbackTestObj],
60116
],
61117
[
62-
new CallbackTest(), 'helloWithResponse',
118+
'routeController' => $callbackTestObj,
119+
'routeName' => 'hello-with-response',
120+
'autoWireArguments' => [[$callbackTestObj]],
121+
'autowireReturn' => [$callbackTestObj],
63122
],
64123
];
65124
}
125+
126+
public function testInvokeWithRouteInvalidConfigurationException(): void
127+
{
128+
$route = $this->createMock(RouteInterface::class);
129+
$route->expects($this->once())
130+
->method('getController')
131+
->willReturn([]);
132+
133+
$route->expects($this->any())
134+
->method('getName')
135+
->willReturn('route-name');
136+
137+
$autowireHelper = $this->createMock(AutowireHelperInterface::class);
138+
$autowireHelper->expects($this->any())
139+
->method('autowire')
140+
->willReturn(fn () => new Response());
141+
142+
$responseCallback = new ResponseCallback(
143+
$autowireHelper,
144+
$route,
145+
);
146+
147+
$this->expectException(RouteInvalidConfigurationException::class);
148+
$responseCallback();
149+
}
66150
}

tests/Unit/Business/Route/RouteBuilderTest.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,30 @@ public function testBuild(
7474
public function dataProvider()
7575
{
7676
return [
77-
['test', function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', ['POST'], null],
78-
['test', function () {}, '/{test}-{date}.{_format}', '/\/(.[aA-zZ0-9-_]+)-(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', ['POST'], null],
79-
[null, function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', null, null],
77+
['test', function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', ['POST'], null],
78+
['test', function () {}, '/{test}-{date}.{_format}', '/\/(.[aA-zZ0-9-_]+)-(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', ['POST'], null],
79+
[null, function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', null, null],
8080
['test', null, '/{test}.{_format}', null, null, RouteInvalidConfigurationException::class],
8181
['test', function () {}, '/test', null, null, null],
8282
['test', null, null, null, null, RouteInvalidConfigurationException::class],
8383
];
8484
}
85+
86+
public function testClear()
87+
{
88+
$builder = new RouteBuilder();
89+
90+
$routeA = $builder->setName('test')
91+
->setController(function () {})
92+
->setUri('/{test}.{_format}')
93+
->setMethods(['POST'])
94+
->build();
95+
96+
$routeB = $builder->setController(function () {})
97+
->setUri('/{test}.{_format}')
98+
->setMethods(['POST'])
99+
->build();
100+
101+
$this->assertNotEquals($routeA->getName(), $routeB->getName());
102+
}
85103
}

0 commit comments

Comments
 (0)