Skip to content

Commit 1cbe153

Browse files
authored
Merge pull request #196 from php-api-clients/introduce-routers-object-for-centralize-router-look-up
Introduce routers object for centralize router look up
2 parents 89c90ce + 75f572d commit 1cbe153

File tree

13 files changed

+341
-184
lines changed

13 files changed

+341
-184
lines changed

src/Generator/Client.php

Lines changed: 91 additions & 129 deletions
Large diffs are not rendered by default.

src/Generator/Client/Routers.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
use Jawira\CaseConverter\Convert;
1111
use PhpParser\Node;
1212

13+
use function lcfirst;
1314
use function rtrim;
15+
use function str_replace;
1416

1517
final class Routers
1618
{
@@ -59,9 +61,18 @@ public function createClassName(
5961
string|null $group,
6062
string $name,
6163
): Router {
64+
$className = rtrim('Router\\' . (new Convert($method))->toPascal() . ($group === null ? '' : '\\' . (new Convert($group))->toPascal()), '\\');
65+
6266
return new Router(
63-
rtrim('Router\\' . (new Convert($method))->toPascal() . ($group === null ? '' : '\\' . (new Convert($group))->toPascal()), '\\'),
67+
$className,
6468
(new Convert($name))->toCamel(),
69+
str_replace(
70+
'\\',
71+
'🔀',
72+
lcfirst(
73+
$className,
74+
),
75+
),
6576
);
6677
}
6778
}

src/Generator/Client/Routers/Router.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
public function __construct(
1010
public string $class,
1111
public string $method,
12+
public string $loopUpMethod,
1213
) {
1314
}
1415
}

src/Generator/Routers.php

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace ApiClients\Tools\OpenApiClientGenerator\Generator;
6+
7+
use ApiClients\Contracts\HTTP\Headers\AuthenticationInterface;
8+
use ApiClients\Tools\OpenApiClientGenerator\Configuration;
9+
use ApiClients\Tools\OpenApiClientGenerator\File;
10+
use ApiClients\Tools\OpenApiClientGenerator\Generator\Client\Routers as ClientRouters;
11+
use ApiClients\Tools\OpenApiClientGenerator\PrivatePromotedPropertyAsParam;
12+
use PhpParser\BuilderFactory;
13+
use PhpParser\Node;
14+
use PhpParser\Node\Arg;
15+
use React\Http\Browser;
16+
17+
use function trim;
18+
19+
final class Routers
20+
{
21+
/** @return iterable<File> */
22+
public static function generate(Configuration $configuration, string $pathPrefix, ClientRouters $routers): iterable
23+
{
24+
$factory = new BuilderFactory();
25+
$stmt = $factory->namespace(trim($configuration->namespace->source, '\\'));
26+
27+
$class = $factory->class('Routers')->makeFinal()->addStmt(
28+
$factory->method('__construct')->makePublic()->addParam(
29+
(new PrivatePromotedPropertyAsParam('authentication'))->setType('\\' . AuthenticationInterface::class)->makeReadonly(),
30+
)->addParam(
31+
(new PrivatePromotedPropertyAsParam('browser'))->setType('\\' . Browser::class)->makeReadonly(),
32+
)->addParam(
33+
(new PrivatePromotedPropertyAsParam('requestSchemaValidator'))->setType('\League\OpenAPIValidation\Schema\SchemaValidator')->makeReadonly(),
34+
)->addParam(
35+
(new PrivatePromotedPropertyAsParam('responseSchemaValidator'))->setType('\League\OpenAPIValidation\Schema\SchemaValidator')->makeReadonly(),
36+
)->addParam(
37+
(new PrivatePromotedPropertyAsParam('hydrators'))->setType('Hydrators')->makeReadonly(),
38+
),
39+
);
40+
41+
foreach ($routers->get() as $group) {
42+
$router = $routers->createClassName($group->method, $group->group, '');
43+
$class->addStmts([
44+
$factory->property($router->loopUpMethod)->setType('?' . $router->class)->setDefault(null)->makePrivate(),
45+
$factory->method($router->loopUpMethod)->setReturnType($router->class)->makePublic()->addStmts([
46+
new Node\Stmt\If_(
47+
new Node\Expr\BinaryOp\Identical(
48+
new Node\Expr\Instanceof_(
49+
new Node\Expr\PropertyFetch(
50+
new Node\Expr\Variable('this'),
51+
$router->loopUpMethod,
52+
),
53+
new Node\Name($router->class),
54+
),
55+
new Node\Expr\ConstFetch(new Node\Name('false')),
56+
),
57+
[
58+
'stmts' => [
59+
new Node\Stmt\Expression(
60+
new Node\Expr\Assign(
61+
new Node\Expr\PropertyFetch(
62+
new Node\Expr\Variable('this'),
63+
$router->loopUpMethod,
64+
),
65+
new Node\Expr\New_(
66+
new Node\Name($router->class),
67+
[
68+
new Arg(
69+
new Node\Expr\PropertyFetch(
70+
new Node\Expr\Variable('this'),
71+
'browser',
72+
),
73+
false,
74+
false,
75+
[],
76+
new Node\Identifier('browser'),
77+
),
78+
new Arg(
79+
new Node\Expr\PropertyFetch(
80+
new Node\Expr\Variable('this'),
81+
'authentication',
82+
),
83+
false,
84+
false,
85+
[],
86+
new Node\Identifier('authentication'),
87+
),
88+
new Arg(
89+
new Node\Expr\PropertyFetch(
90+
new Node\Expr\Variable('this'),
91+
'requestSchemaValidator',
92+
),
93+
false,
94+
false,
95+
[],
96+
new Node\Identifier('requestSchemaValidator'),
97+
),
98+
new Arg(
99+
new Node\Expr\PropertyFetch(
100+
new Node\Expr\Variable('this'),
101+
'responseSchemaValidator',
102+
),
103+
false,
104+
false,
105+
[],
106+
new Node\Identifier('responseSchemaValidator'),
107+
),
108+
new Arg(
109+
new Node\Expr\PropertyFetch(
110+
new Node\Expr\Variable('this'),
111+
'hydrators',
112+
),
113+
false,
114+
false,
115+
[],
116+
new Node\Identifier('hydrators'),
117+
),
118+
],
119+
),
120+
),
121+
),
122+
],
123+
],
124+
),
125+
new Node\Stmt\Return_(
126+
new Node\Expr\PropertyFetch(
127+
new Node\Expr\Variable('this'),
128+
$router->loopUpMethod,
129+
),
130+
),
131+
]),
132+
]);
133+
}
134+
135+
yield new File($pathPrefix, 'Routers', $stmt->addStmt($class)->getNode());
136+
}
137+
}

src/Output/Error.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public static function display(Throwable $throwable): void
2020
render('<div>
2121
<div class="px-1 bg-red-600">ERROR</div>
2222
<em class="ml-1">
23-
' . $throwable->getMessage() . '
23+
' . $throwable . '
2424
</em>
2525
</div>');
2626

tests/app/etc/openapi-client-generator.state

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@
204204
},
205205
{
206206
"name": ".\/tests\/app\/src\/\/Client.php",
207-
"hash": "719d8221d11509ec31f017f2bd54cb1e"
207+
"hash": "6ff122e2242b2a6e4485e102494cb16e"
208208
},
209209
{
210210
"name": ".\/tests\/app\/src\/\/Router\/Get\/Pets.php",
@@ -228,23 +228,23 @@
228228
},
229229
{
230230
"name": ".\/tests\/app\/src\/\/Router\/Get\/Two.php",
231-
"hash": "a0e0ed35a37774016b138af026b36f77"
231+
"hash": "b3dfb54492236d6acce0d855f5a9722c"
232232
},
233233
{
234234
"name": ".\/tests\/app\/src\/\/Router\/Get\/Three.php",
235-
"hash": "fe90c28538f6f8e8e7844ffc1cee7d0c"
235+
"hash": "010a712431902ce0cd62c76b442f3b2f"
236236
},
237237
{
238238
"name": ".\/tests\/app\/src\/\/Router\/List\/Two.php",
239-
"hash": "acfddb57c7bfe66131602af16078e64e"
239+
"hash": "8c536f506e86e29020d73148d614efc2"
240240
},
241241
{
242242
"name": ".\/tests\/app\/src\/\/Router\/List\/Three.php",
243-
"hash": "25ba6590befb6bee1dbf71b48ddbb81b"
243+
"hash": "ed2f78d6ad9c8fde60c41578f5c3e85f"
244244
},
245245
{
246246
"name": ".\/tests\/app\/src\/\/Router\/Post\/Two.php",
247-
"hash": "609aaf14d32b8bc5bb9cef46fe7e3a93"
247+
"hash": "50181ba1cfdb8b707f8a7bb47b0811ea"
248248
},
249249
{
250250
"name": ".\/tests\/app\/src\/\/OperationsInterface.php",
@@ -285,6 +285,10 @@
285285
{
286286
"name": ".\/tests\/app\/src\/\/Router\/Get.php",
287287
"hash": "0c8b86bc66e7540692ee4266e1c2ea95"
288+
},
289+
{
290+
"name": ".\/tests\/app\/src\/\/Routers.php",
291+
"hash": "981e3ed9c1d96ba38e608555aeb4681d"
288292
}
289293
]
290294
},

tests/app/src/Client.php

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ final class Client implements ClientInterface
2222
private array $router = array();
2323
private readonly OperationsInterface $operations;
2424
private readonly Hydrators $hydrators;
25+
private readonly Routers $routers;
2526
public function __construct(\ApiClients\Contracts\HTTP\Headers\AuthenticationInterface $authentication, \React\Http\Browser $browser)
2627
{
2728
$this->authentication = $authentication;
@@ -30,6 +31,7 @@ public function __construct(\ApiClients\Contracts\HTTP\Headers\AuthenticationInt
3031
$this->responseSchemaValidator = new \League\OpenAPIValidation\Schema\SchemaValidator(\League\OpenAPIValidation\Schema\SchemaValidator::VALIDATE_AS_RESPONSE);
3132
$this->hydrators = new Hydrators();
3233
$this->operations = new Operations(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
34+
$this->routers = new Routers(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
3335
}
3436
// phpcs:disable
3537
/**
@@ -44,31 +46,31 @@ public function call(string $call, array $params = array()) : iterable|\ApiClien
4446
if ($method === 'GET') {
4547
if ($pathChunksCount === 2) {
4648
if (\array_key_exists(Router\Get\Two::class, $this->router) == false) {
47-
$this->router[Router\Get\Two::class] = new Router\Get\Two(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
49+
$this->router[Router\Get\Two::class] = new Router\Get\Two(routers: $this->routers);
4850
}
4951
return $this->router[Router\Get\Two::class]->call($call, $params, $pathChunks);
5052
} elseif ($pathChunksCount === 3) {
5153
if (\array_key_exists(Router\Get\Three::class, $this->router) == false) {
52-
$this->router[Router\Get\Three::class] = new Router\Get\Three(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
54+
$this->router[Router\Get\Three::class] = new Router\Get\Three(routers: $this->routers);
5355
}
5456
return $this->router[Router\Get\Three::class]->call($call, $params, $pathChunks);
5557
}
5658
} elseif ($method === 'LIST') {
5759
if ($pathChunksCount === 2) {
5860
if (\array_key_exists(Router\List\Two::class, $this->router) == false) {
59-
$this->router[Router\List\Two::class] = new Router\List\Two(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
61+
$this->router[Router\List\Two::class] = new Router\List\Two(routers: $this->routers);
6062
}
6163
return $this->router[Router\List\Two::class]->call($call, $params, $pathChunks);
6264
} elseif ($pathChunksCount === 3) {
6365
if (\array_key_exists(Router\List\Three::class, $this->router) == false) {
64-
$this->router[Router\List\Three::class] = new Router\List\Three(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
66+
$this->router[Router\List\Three::class] = new Router\List\Three(routers: $this->routers);
6567
}
6668
return $this->router[Router\List\Three::class]->call($call, $params, $pathChunks);
6769
}
6870
} elseif ($method === 'POST') {
6971
if ($pathChunksCount === 2) {
7072
if (\array_key_exists(Router\Post\Two::class, $this->router) == false) {
71-
$this->router[Router\Post\Two::class] = new Router\Post\Two(browser: $this->browser, authentication: $this->authentication, requestSchemaValidator: $this->requestSchemaValidator, responseSchemaValidator: $this->responseSchemaValidator, hydrators: $this->hydrators);
73+
$this->router[Router\Post\Two::class] = new Router\Post\Two(routers: $this->routers);
7274
}
7375
return $this->router[Router\Post\Two::class]->call($call, $params, $pathChunks);
7476
}

tests/app/src/Router/Get/Three.php

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
use ApiClients\Contracts;
1616
final class Three
1717
{
18-
private array $router = array();
19-
public function __construct(private \League\OpenAPIValidation\Schema\SchemaValidator $requestSchemaValidator, private \League\OpenAPIValidation\Schema\SchemaValidator $responseSchemaValidator, private \ApiClients\Client\PetStore\Hydrators $hydrators, private \React\Http\Browser $browser, private \ApiClients\Contracts\HTTP\Headers\AuthenticationInterface $authentication)
18+
public function __construct(private \ApiClients\Client\PetStore\Routers $routers)
2019
{
2120
}
2221
/**
@@ -28,24 +27,15 @@ public function call(string $call, array $params, array $pathChunks) : iterable|
2827
if ($pathChunks[1] == 'pets') {
2928
if ($pathChunks[2] == 'gatos') {
3029
if ($call == 'GET /pets/gatos') {
31-
if (\array_key_exists(Router\Get\PetsList::class, $this->router) == false) {
32-
$this->router[Router\Get\PetsList::class] = new Router\Get\PetsList($this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrators, $this->browser, $this->authentication);
33-
}
34-
return $this->router[Router\Get\PetsList::class]->Gatos($params);
30+
return $this->routers->router🔀Get🔀PetsList()->gatos($params);
3531
}
3632
} elseif ($pathChunks[2] == 'names') {
3733
if ($call == 'GET /pets/names') {
38-
if (\array_key_exists(Router\Get\Pets::class, $this->router) == false) {
39-
$this->router[Router\Get\Pets::class] = new Router\Get\Pets($this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrators, $this->browser, $this->authentication);
40-
}
41-
return $this->router[Router\Get\Pets::class]->Names($params);
34+
return $this->routers->router🔀Get🔀Pets()->names($params);
4235
}
4336
} elseif ($pathChunks[2] == '{petId}') {
4437
if ($call == 'GET /pets/{petId}') {
45-
if (\array_key_exists(Router\Get::class, $this->router) == false) {
46-
$this->router[Router\Get::class] = new Router\Get($this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrators, $this->browser, $this->authentication);
47-
}
48-
return $this->router[Router\Get::class]->ShowPetById($params);
38+
return $this->routers->router🔀Get()->showPetById($params);
4939
}
5040
}
5141
}

tests/app/src/Router/Get/Two.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
use ApiClients\Contracts;
1616
final class Two
1717
{
18-
private array $router = array();
19-
public function __construct(private \League\OpenAPIValidation\Schema\SchemaValidator $requestSchemaValidator, private \League\OpenAPIValidation\Schema\SchemaValidator $responseSchemaValidator, private \ApiClients\Client\PetStore\Hydrators $hydrators, private \React\Http\Browser $browser, private \ApiClients\Contracts\HTTP\Headers\AuthenticationInterface $authentication)
18+
public function __construct(private \ApiClients\Client\PetStore\Routers $routers)
2019
{
2120
}
2221
/**
@@ -27,10 +26,7 @@ public function call(string $call, array $params, array $pathChunks) : iterable
2726
if ($pathChunks[0] == '') {
2827
if ($pathChunks[1] == 'pets') {
2928
if ($call == 'GET /pets') {
30-
if (\array_key_exists(Router\Get\Pets::class, $this->router) == false) {
31-
$this->router[Router\Get\Pets::class] = new Router\Get\Pets($this->requestSchemaValidator, $this->responseSchemaValidator, $this->hydrators, $this->browser, $this->authentication);
32-
}
33-
return $this->router[Router\Get\Pets::class]->List($params);
29+
return $this->routers->router🔀Get🔀Pets()->list($params);
3430
}
3531
}
3632
}

0 commit comments

Comments
 (0)