Skip to content

Commit fbcd9c7

Browse files
committed
UrlGenerator implemented, Phpunit: implements test
1 parent 0359cf1 commit fbcd9c7

11 files changed

+282
-5
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
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\Generator;
15+
16+
use Micro\Plugin\Http\Business\Route\RouteCollectionInterface;
17+
18+
/**
19+
* @author Stanislau Komar <[email protected]>
20+
*/
21+
readonly class UrlGenerator implements UrlGeneratorInterface
22+
{
23+
public function __construct(private RouteCollectionInterface $routeCollection)
24+
{
25+
}
26+
27+
/**
28+
* {@inheritDoc}
29+
*/
30+
public function generateUrlByRouteName(string $routeName, array|null $parameters = []): string
31+
{
32+
$route = $this->routeCollection->getRouteByName($routeName);
33+
$uri = $route->getUri();
34+
$routeParameters = $route->getParameters() ?? [];
35+
$parameters = $parameters ?? [];
36+
$parametersKeys = array_keys($parameters);
37+
38+
sort($routeParameters);
39+
sort($parametersKeys);
40+
41+
if ($routeParameters !== $parametersKeys) {
42+
throw new \RuntimeException('Route parameters mismatch. Parameters available: '.json_encode($routeParameters));
43+
}
44+
45+
foreach ($parameters as $key => $value) {
46+
$uri = str_replace(sprintf('{%s}', $key), $value, $uri);
47+
}
48+
49+
return $uri;
50+
}
51+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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\Generator;
15+
16+
use Micro\Plugin\Http\Business\Route\RouteCollectionFactoryInterface;
17+
18+
/**
19+
* @author Stanislau Komar <[email protected]>
20+
*/
21+
readonly class UrlGeneratorFactory implements UrlGeneratorFactoryInterface
22+
{
23+
public function __construct(
24+
private RouteCollectionFactoryInterface $routeCollectionFactory
25+
) {
26+
}
27+
28+
/**
29+
* {@inheritDoc}
30+
*/
31+
public function create(): UrlGeneratorInterface
32+
{
33+
return new UrlGenerator($this->routeCollectionFactory->create());
34+
}
35+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\Generator;
15+
16+
/**
17+
* @author Stanislau Komar <[email protected]>
18+
*/
19+
interface UrlGeneratorFactoryInterface
20+
{
21+
public function create(): UrlGeneratorInterface;
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
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\Generator;
15+
16+
use Micro\Plugin\Http\Exception\RouteNotFoundException;
17+
18+
/**
19+
* @author Stanislau Komar <[email protected]>
20+
*/
21+
interface UrlGeneratorInterface
22+
{
23+
/**
24+
* @param array<string, mixed>|null $parameters
25+
*
26+
* @throws RouteNotFoundException
27+
* @throws \RuntimeException
28+
*/
29+
public function generateUrlByRouteName(string $routeName, array|null $parameters = []): string;
30+
}

src/Business/Route/RouteCollectionFactory.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,32 @@
1818
/**
1919
* @author Stanislau Komar <[email protected]>
2020
*/
21-
readonly class RouteCollectionFactory implements RouteCollectionFactoryInterface
21+
class RouteCollectionFactory implements RouteCollectionFactoryInterface
2222
{
23+
private RouteCollectionInterface|null $routeCollection;
24+
2325
public function __construct(
24-
private RouteLocatorFactoryInterface $routeLocatorFactory
26+
private readonly RouteLocatorFactoryInterface $routeLocatorFactory
2527
) {
28+
$this->routeCollection = null;
2629
}
2730

2831
/**
2932
* {@inheritDoc}
3033
*/
3134
public function create(): RouteCollectionInterface
3235
{
36+
if ($this->routeCollection) {
37+
return $this->routeCollection;
38+
}
39+
3340
$collection = new RouteCollection();
3441

3542
$locator = $this->routeLocatorFactory->create();
3643
foreach ($locator->locate() as $route) {
3744
$collection->addRoute($route);
3845
}
3946

40-
return $collection;
47+
return $this->routeCollection = $collection;
4148
}
4249
}

src/Facade/HttpFacade.php

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace Micro\Plugin\Http\Facade;
1515

1616
use Micro\Plugin\Http\Business\Executor\RouteExecutorFactoryInterface;
17+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorFactoryInterface;
1718
use Micro\Plugin\Http\Business\Matcher\UrlMatcherFactoryInterface;
1819
use Micro\Plugin\Http\Business\Route\RouteBuilderFactoryInterface;
1920
use Micro\Plugin\Http\Business\Route\RouteBuilderInterface;
@@ -31,7 +32,8 @@ public function __construct(
3132
private UrlMatcherFactoryInterface $urlMatcherFactory,
3233
private RouteCollectionFactoryInterface $routeCollectionFactory,
3334
private RouteExecutorFactoryInterface $routeExecutorFactory,
34-
private RouteBuilderFactoryInterface $routeBuilderFactory
35+
private RouteBuilderFactoryInterface $routeBuilderFactory,
36+
private UrlGeneratorFactoryInterface $urlGeneratorFactory
3537
) {
3638
}
3739

@@ -72,4 +74,14 @@ public function execute(Request $request, bool $flush = true): Response
7274
->create()
7375
->execute($request, $flush);
7476
}
77+
78+
/**
79+
* {@inheritDoc}
80+
*/
81+
public function generateUrlByRouteName(string $routeName, array|null $parameters = []): string
82+
{
83+
return $this->urlGeneratorFactory
84+
->create()
85+
->generateUrlByRouteName($routeName, $parameters);
86+
}
7587
}

src/Facade/HttpFacadeInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@
1414
namespace Micro\Plugin\Http\Facade;
1515

1616
use Micro\Plugin\Http\Business\Executor\RouteExecutorInterface;
17+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorInterface;
1718
use Micro\Plugin\Http\Business\Matcher\UrlMatcherInterface;
1819
use Micro\Plugin\Http\Business\Route\RouteBuilderInterface;
1920

2021
/**
2122
* @author Stanislau Komar <[email protected]>
2223
*/
23-
interface HttpFacadeInterface extends UrlMatcherInterface, RouteExecutorInterface
24+
interface HttpFacadeInterface extends UrlMatcherInterface, RouteExecutorInterface, UrlGeneratorInterface
2425
{
2526
/**
2627
* @return string[]

src/HttpCorePlugin.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
use Micro\Framework\Kernel\Plugin\PluginConfigurationTrait;
2323
use Micro\Plugin\Http\Business\Executor\RouteExecutorFactory;
2424
use Micro\Plugin\Http\Business\Executor\RouteExecutorFactoryInterface;
25+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorFactory;
26+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorFactoryInterface;
2527
use Micro\Plugin\Http\Business\Locator\RouteLocatorFactory;
2628
use Micro\Plugin\Http\Business\Locator\RouteLocatorFactoryInterface;
2729
use Micro\Plugin\Http\Business\Matcher\Route\RouteMatcherFactory;
@@ -82,9 +84,15 @@ protected function createFacade(): HttpFacadeInterface
8284
$routeCollectionFactory,
8385
$this->createRouteExecutorFactory($urlMatcherFactory),
8486
$this->createRouteBuilderFactory(),
87+
$this->createUrlGeneratorFactory($routeCollectionFactory)
8588
);
8689
}
8790

91+
protected function createUrlGeneratorFactory(RouteCollectionFactoryInterface $routeCollectionFactory): UrlGeneratorFactoryInterface
92+
{
93+
return new UrlGeneratorFactory($routeCollectionFactory);
94+
}
95+
8896
protected function createRouteBuilderFactory(): RouteBuilderFactoryInterface
8997
{
9098
return new RouteBuilderFactory();
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Micro framework package.
5+
*
6+
* (c) Stanislau Komar <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Unit\Business\Generator;
13+
14+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorFactory;
15+
use Micro\Plugin\Http\Business\Generator\UrlGeneratorInterface;
16+
use Micro\Plugin\Http\Business\Route\RouteCollectionFactoryInterface;
17+
use PHPUnit\Framework\TestCase;
18+
19+
class UrlGeneratorFactoryTest extends TestCase
20+
{
21+
public function testCreate()
22+
{
23+
$urlGeneratorFactory = new UrlGeneratorFactory(
24+
$this->createMock(RouteCollectionFactoryInterface::class),
25+
);
26+
27+
$this->assertInstanceOf(UrlGeneratorInterface::class, $urlGeneratorFactory->create());
28+
}
29+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Micro framework package.
5+
*
6+
* (c) Stanislau Komar <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Unit\Business\Generator;
13+
14+
use Micro\Plugin\Http\Business\Generator\UrlGenerator;
15+
use Micro\Plugin\Http\Business\Route\RouteCollectionInterface;
16+
use Micro\Plugin\Http\Business\Route\RouteInterface;
17+
use PHPUnit\Framework\TestCase;
18+
19+
class UrlGeneratorTest extends TestCase
20+
{
21+
/**
22+
* @dataProvider dataProvider
23+
*/
24+
public function testGenerateUrlByRouteName(
25+
string $routeUri,
26+
array $routeParameters,
27+
array|null $parameters,
28+
string $exceptedRoute,
29+
string|null $exceptionExcepted
30+
) {
31+
$route = $this->createMock(RouteInterface::class);
32+
$route
33+
->expects($this->once())
34+
->method('getUri')
35+
->willReturn($routeUri);
36+
37+
$route
38+
->expects($this->once())
39+
->method('getParameters')
40+
->willReturn($routeParameters);
41+
42+
$collection = $this->createMock(RouteCollectionInterface::class);
43+
$collection
44+
->expects($this->once())
45+
->method('getRouteByName')
46+
->with('test_route')
47+
->willReturn($route);
48+
49+
$generator = new UrlGenerator($collection);
50+
51+
if ($exceptionExcepted) {
52+
$this->expectException($exceptionExcepted);
53+
}
54+
55+
$generated = $generator->generateUrlByRouteName('test_route', $parameters);
56+
57+
$this->assertEquals($exceptedRoute, $generated);
58+
}
59+
60+
public function dataProvider()
61+
{
62+
return [
63+
['/test', [], [], '/test', null],
64+
['/{parameter}', ['parameter'], ['parameter' => 'dynamic'], '/dynamic', null],
65+
['/{parameter}', ['parameter'], ['parameter' => 'dynamic', 'invalid_parameter' => 'test'], '', \RuntimeException::class],
66+
['/{parameter}', ['parameter'], [], '', \RuntimeException::class],
67+
];
68+
}
69+
}

0 commit comments

Comments
 (0)