Skip to content

Commit

Permalink
Merge pull request #8 from Micro-PHP/v1.6.0-release
Browse files Browse the repository at this point in the history
V1.6.0 release
  • Loading branch information
Asisyas authored Jan 21, 2023
2 parents 951b977 + bfe2fbe commit 19ec43f
Show file tree
Hide file tree
Showing 11 changed files with 155 additions and 43 deletions.
15 changes: 8 additions & 7 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,24 @@
}
],
"require": {
"micro/autowire": "^1",
"micro/kernel": "^1",
"micro/kernel-app": "^1",
"micro/kernel-boot-configuration": "^1",
"micro/kernel-boot-dependency": "^1",
"micro/kernel-boot-plugin-depended": "^1",
"micro/plugin-locator": "^1",
"micro/autowire": "^1.6",
"micro/kernel": "^1.6",
"micro/kernel-boot-configuration": "^1.6",
"micro/kernel-boot-dependency": "^1.6",
"micro/kernel-boot-plugin-depended": "^1.6",
"micro/plugin-locator": "^1.6",
"symfony/http-foundation": "^6.2"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.29",
"friendsofphp/php-cs-fixer": "^3.13",
"micro/kernel-app": "^1.6",
"phpstan/phpstan": "^1.9",
"phpunit/php-code-coverage": "^9.2",
"phpunit/phpunit": "^9.5",
"vimeo/psalm": "^5.2"
},
"minimum-stability": "dev",
"autoload": {
"psr-4": {
"Micro\\Plugin\\Http\\": "src/"
Expand Down
13 changes: 4 additions & 9 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,11 @@
<directory>tests/Unit</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">src/</directory>
<exclude>
<directory>src/Exception</directory>
<file>src/HttpCorePlugin.php</file>
</exclude>
</whitelist>
</filter>
<coverage>
<exclude>
<directory>src/Exception</directory>
<file>src/HttpCorePlugin.php</file>
</exclude>
<include>
<directory suffix=".php">src</directory>
</include>
Expand Down
6 changes: 3 additions & 3 deletions src/Business/Matcher/Route/Matchers/UriMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ class UriMatcher implements RouteMatcherInterface
*/
public function match(RouteInterface $route, Request $request): bool
{
$requestUri = $request->getRequestUri();
$pathInfo = $request->getPathInfo();
$pattern = $route->getPattern();
if (!$pattern) {
return $requestUri === $route->getUri();
return $pathInfo === $route->getUri();
}

$matched = preg_match_all($pattern, $requestUri, $matches);
$matched = preg_match_all($pattern, $pathInfo, $matches);

if (0 === $matched) {
return false;
Expand Down
16 changes: 12 additions & 4 deletions src/Business/Response/Callback/ResponseCallback.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ public function __construct(
public function __invoke(): mixed
{
$controller = $this->route->getController();
$routeName = $this->route->getName() ?? $this->route->getUri();

if (\is_callable($controller)) {
$callback = $this->autowireHelper->autowire($controller);

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

if (\is_array($controller)) {
$controller = array_filter($controller);
if (!\count($controller)) {
throw new RouteInvalidConfigurationException($this->route->getName() ?? $this->route->getUri(), ['Controller is not defined.']);
throw new RouteInvalidConfigurationException($routeName, ['Controller is not defined.']);
}

$classController = $controller[0];
$classMethod = $controller[1] ?? $this->snakeToCamel($this->route->getName() ?? '');
$classMethod = !empty($controller[1]) ? $controller[1] : $this->snakeToCamel($this->route->getName() ?? '');
}

/* @psalm-suppress RedundantConditionGivenDocblockType */
if (!\is_object($classController)) {
/** @psalm-suppress PossiblyNullArgument */
/**
* @psalm-suppress PossiblyNullArgument
*
* @phpstan-ignore-next-line
*/
$classController = $this->autowireHelper->autowire($classController)();
}

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

protected function snakeToCamel(string $str): string
{
return lcfirst(str_replace(' ', '', ucwords(str_replace('_', ' ', $str))));
return lcfirst(str_replace(' ', '', ucwords(str_replace(['_', '-'], [' ', ' '], $str))));
}
}
5 changes: 3 additions & 2 deletions src/Business/Route/RouteBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,11 @@ public function build(): RouteInterface
$pattern = null;
$parameters = null;
/** @psalm-suppress PossiblyNullArgument */
$isDynamic = preg_match_all('/\{\s*([^}\s]*)\s*\}/', $this->uri, $matches);
$isDynamic = preg_match_all('/\{\s*([^}\s]*)\s*}/', $this->uri, $matches);
if ($isDynamic) {
$parameters = $matches[1];
/** @psalm-suppress PossiblyNullArgument */
$pattern = '/'.addcslashes($this->uri, '/.').'/';
$pattern = '/'.addcslashes($this->uri, '/.').'$/';

foreach ($matches[0] as $replaced) {
$pattern = str_replace($replaced, '(.[aA-zZ0-9-_]+)', $pattern);
Expand Down Expand Up @@ -185,5 +185,6 @@ protected function clear(): void
$this->uri = null;
$this->action = null;
$this->methods = $this->methodsByDefault;
$this->name = null;
}
}
2 changes: 1 addition & 1 deletion tests/Unit/Business/Locator/RouteLocatorFactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ protected function createKernel(string $locatorAlias, bool $isLocatorNotFound):
->expects($this->once())
->method('plugins')
->with(HttpRouteLocatorPluginInterface::class)
->willReturn([$stubLocator]);
->willReturn(new \ArrayObject([$stubLocator]));

return $stubKernel;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public function testMatch(string $requestUri, string $routeUri, string|null $rou
$requestMock = $this->createMock(Request::class);
$requestMock
->expects($this->once())
->method('getRequestUri')
->method('getPathInfo')
->willReturn($requestUri);

$actual = $matcher->match(
Expand Down
5 changes: 5 additions & 0 deletions tests/Unit/Business/Response/CallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@
*/
class CallbackTest
{
public function __invoke(): Response
{
return new Response();
}

public function helloWithResponse(): Response
{
return new Response();
Expand Down
108 changes: 96 additions & 12 deletions tests/Unit/Business/Response/ResponseCallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use Micro\Component\DependencyInjection\Autowire\AutowireHelperInterface;
use Micro\Plugin\Http\Business\Response\Callback\ResponseCallback;
use Micro\Plugin\Http\Business\Route\RouteInterface;
use Micro\Plugin\Http\Exception\RouteInvalidConfigurationException;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\Response;

Expand All @@ -22,18 +23,26 @@ class ResponseCallbackTest extends TestCase
/**
* @dataProvider dataProvider
*/
public function testInvoke(mixed $callable)
{
public function testInvoke(
mixed $routeController,
string $routeName,
array $expectedAutoWireArguments,
array $autowireReturns
) {
$route = $this->createMock(RouteInterface::class);
$route
->expects($this->once())
$route->expects($this->once())
->method('getController')
->willReturn($callable);
->willReturn($routeController);

$route->expects($this->any())
->method('getName')
->willReturn($routeName);

$autowireHelper = $this->createMock(AutowireHelperInterface::class);
$autowireHelper->expects($this->any())
->method('autowire')
->willReturn(fn () => new Response());
->withConsecutive(...$expectedAutoWireArguments)
->willReturnOnConsecutiveCalls(...$autowireReturns);

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

public function dataProvider()
public function dataProvider(): array
{
$anonymousFunction = function () { return new Response(); };
$callbackTestObj = new CallbackTest();

return [
[
function () {},
'routeController' => $anonymousFunction,
'routeName' => 'does-not-matter',
'autoWireArguments' => [[$anonymousFunction]],
'autowireReturns' => [$anonymousFunction],
],
[
'routeController' => CallbackTest::class,
'routeName' => '',
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, '']]],
'autowireReturns' => [
fn () => $callbackTestObj,
[$callbackTestObj, '__invoke'],
],
],
[
'routeController' => CallbackTest::class,
'routeName' => 'hello-with-response',
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
'autowireReturns' => [
fn () => $callbackTestObj,
[$callbackTestObj, 'helloWithResponse'],
],
],
[
'routeController' => [CallbackTest::class, 'helloWithResponse'],
'routeName' => '',
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
'autowireReturns' => [
fn () => $callbackTestObj,
[$callbackTestObj, 'helloWithResponse'],
],
],
[
CallbackTest::class,
'routeController' => CallbackTest::class.'::helloWithResponse',
'routeName' => '',
'autoWireArguments' => [[CallbackTest::class], [[$callbackTestObj, 'helloWithResponse']]],
'autowireReturns' => [
fn () => $callbackTestObj,
[$callbackTestObj, 'helloWithResponse'],
],
],
[
CallbackTest::class, 'helloWithResponse',
'routeController' => [$callbackTestObj, 'helloWithResponse'],
'routeName' => 'does-not-matter',
'autoWireArguments' => [[[$callbackTestObj, 'helloWithResponse']]],
'autowireReturn' => [
[$callbackTestObj, 'helloWithResponse'],
],
],
[
CallbackTest::class.'::helloWithResponse',
'routeController' => $callbackTestObj,
'routeName' => '',
'autoWireArguments' => [[$callbackTestObj]],
'autowireReturn' => [$callbackTestObj],
],
[
new CallbackTest(), 'helloWithResponse',
'routeController' => $callbackTestObj,
'routeName' => 'hello-with-response',
'autoWireArguments' => [[$callbackTestObj]],
'autowireReturn' => [$callbackTestObj],
],
];
}

public function testInvokeWithRouteInvalidConfigurationException(): void
{
$route = $this->createMock(RouteInterface::class);
$route->expects($this->once())
->method('getController')
->willReturn([]);

$route->expects($this->any())
->method('getName')
->willReturn('route-name');

$autowireHelper = $this->createMock(AutowireHelperInterface::class);
$autowireHelper->expects($this->any())
->method('autowire')
->willReturn(fn () => new Response());

$responseCallback = new ResponseCallback(
$autowireHelper,
$route,
);

$this->expectException(RouteInvalidConfigurationException::class);
$responseCallback();
}
}
24 changes: 21 additions & 3 deletions tests/Unit/Business/Route/RouteBuilderTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,30 @@ public function testBuild(
public function dataProvider()
{
return [
['test', function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', ['POST'], null],
['test', function () {}, '/{test}-{date}.{_format}', '/\/(.[aA-zZ0-9-_]+)-(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', ['POST'], null],
[null, function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)/', null, null],
['test', function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', ['POST'], null],
['test', function () {}, '/{test}-{date}.{_format}', '/\/(.[aA-zZ0-9-_]+)-(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', ['POST'], null],
[null, function () {}, '/{test}.{_format}', '/\/(.[aA-zZ0-9-_]+)\.(.[aA-zZ0-9-_]+)$/', null, null],
['test', null, '/{test}.{_format}', null, null, RouteInvalidConfigurationException::class],
['test', function () {}, '/test', null, null, null],
['test', null, null, null, null, RouteInvalidConfigurationException::class],
];
}

public function testClear()
{
$builder = new RouteBuilder();

$routeA = $builder->setName('test')
->setController(function () {})
->setUri('/{test}.{_format}')
->setMethods(['POST'])
->build();

$routeB = $builder->setController(function () {})
->setUri('/{test}.{_format}')
->setMethods(['POST'])
->build();

$this->assertNotEquals($routeA->getName(), $routeB->getName());
}
}
2 changes: 1 addition & 1 deletion tests/Unit/HttpCorePluginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public function testPlugin(string $parameter)
throw $exception;
}

$this->assertEquals($response->getContent(), $parameter);
$this->assertEquals($parameter, $response->getContent());
}

public function dataProvider()
Expand Down

0 comments on commit 19ec43f

Please sign in to comment.