Skip to content

Commit c9e262a

Browse files
authored
Merge pull request #78 from php-api-clients/add-client-interface
Add ClientInterface
2 parents fd50d1d + 13c2ff3 commit c9e262a

File tree

3 files changed

+104
-1
lines changed

3 files changed

+104
-1
lines changed

src/Generator.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use ApiClients\Tools\OpenApiClientGenerator\Generator\Authentication;
66
use ApiClients\Tools\OpenApiClientGenerator\Generator\Client;
7+
use ApiClients\Tools\OpenApiClientGenerator\Generator\ClientInterface;
78
use ApiClients\Tools\OpenApiClientGenerator\Generator\Clients;
89
use ApiClients\Tools\OpenApiClientGenerator\Generator\Operation;
910
use ApiClients\Tools\OpenApiClientGenerator\Generator\Path;
@@ -146,6 +147,11 @@ private function all(string $namespace, string $rootPath): iterable
146147
);
147148

148149
}
150+
yield from ClientInterface::generate(
151+
$namespace,
152+
$clients,
153+
$schemaRegistry,
154+
);
149155
yield from Client::generate(
150156
$namespace,
151157
$clients,

src/Generator/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static function generate(string $namespace, array $clients, SchemaRegistr
3434
$factory = new BuilderFactory();
3535
$stmt = $factory->namespace(rtrim($namespace, '\\'));
3636

37-
$class = $factory->class('Client')->makeFinal()->addStmt(
37+
$class = $factory->class('Client')->implement(new Node\Name('ClientInterface'))->makeFinal()->addStmt(
3838
$factory->property('authentication')->setType('\\' . AuthenticationInterface::class)->makeReadonly()->makePrivate()
3939
)->addStmt(
4040
$factory->property('browser')->setType('\\' . Browser::class)->makeReadonly()->makePrivate()

src/Generator/ClientInterface.php

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
<?php
2+
3+
namespace ApiClients\Tools\OpenApiClientGenerator\Generator;
4+
5+
use ApiClients\Contracts\HTTP\Headers\AuthenticationInterface;
6+
use ApiClients\Tools\OpenApiClientGenerator\File;
7+
use ApiClients\Tools\OpenApiClientGenerator\SchemaRegistry;
8+
use cebe\openapi\spec\Operation as OpenAPiOperation;
9+
use cebe\openapi\spec\PathItem;
10+
use Jawira\CaseConverter\Convert;
11+
use League\OpenAPIValidation\Schema\Exception\SchemaMismatch;
12+
use PhpParser\Builder\Param;
13+
use PhpParser\BuilderFactory;
14+
use PhpParser\Comment\Doc;
15+
use PhpParser\Node;
16+
use PhpParser\Node\Arg;
17+
use PhpParser\Node\Stmt\Class_;
18+
use Psr\Http\Message\RequestInterface;
19+
use Psr\Http\Message\ResponseInterface;
20+
use Psr\Http\Message\ServerRequestInterface;
21+
use React\Http\Browser;
22+
use React\Promise\PromiseInterface;
23+
use RingCentral\Psr7\Request;
24+
use Rx\Observable;
25+
26+
final class ClientInterface
27+
{
28+
/**
29+
* @return iterable<Node>
30+
* @throws \Jawira\CaseConverter\CaseConverterException
31+
*/
32+
public static function generate(string $namespace, array $clients, SchemaRegistry $schemaRegistry): iterable
33+
{
34+
$factory = new BuilderFactory();
35+
$stmt = $factory->namespace(rtrim($namespace, '\\'));
36+
37+
$class = $factory->interface('ClientInterface');
38+
$operationCalls = [];
39+
$callReturnTypes = [];
40+
41+
foreach ($clients as $operationGroup => $operations) {
42+
$cn = str_replace('/', '\\', '\\' . $namespace . 'Operation/' . $operationGroup);
43+
$casedOperationgroup = lcfirst($operationGroup);
44+
foreach ($operations as $operationOperation => $operationDetails) {
45+
$returnType = [];
46+
foreach ($operationDetails['operation']->responses as $code => $spec) {
47+
$contentTypeCases = [];
48+
foreach ($spec->content as $contentType => $contentTypeSchema) {
49+
$fallbackName = 'Operation\\' . $operationGroup . '\\Response\\' . (new Convert(str_replace('/', '\\', $contentType) . '\\H' . $code ))->toPascal();
50+
$object = '\\' . $namespace . 'Schema\\' . $schemaRegistry->get($contentTypeSchema->schema, $fallbackName);
51+
$callReturnTypes[] = ($contentTypeSchema->schema->type === 'array' ? '\\' . Observable::class . '<' : '') . $object . ($contentTypeSchema->schema->type === 'array' ? '>' : '');
52+
$contentTypeCases[] = $returnType[] = $contentTypeSchema->schema->type === 'array' ? '\\' . Observable::class : $object;
53+
}
54+
if (count($contentTypeCases) === 0) {
55+
$returnType[] = $callReturnTypes[] = 'int';
56+
}
57+
}
58+
$operationCalls[] = [
59+
'operationGroupMethod' => $casedOperationgroup,
60+
'operationMethod' => lcfirst($operationOperation),
61+
'className' => str_replace('/', '\\', '\\' . $namespace . 'Operation\\' . $operationDetails['class']),
62+
'params' => iterator_to_array((function (array $operationDetails): iterable {
63+
foreach ($operationDetails['operation']->parameters as $parameter) {
64+
yield $parameter->name;
65+
}
66+
})($operationDetails)),
67+
'returnType' => $returnType,
68+
];
69+
}
70+
$class->addStmt(
71+
$factory->method($casedOperationgroup)->setReturnType($cn)->makePublic()
72+
);
73+
}
74+
75+
$class->addStmt(
76+
$factory->method('call')->makePublic()->setReturnType(
77+
new Node\Name('\\' . PromiseInterface::class)
78+
)->setDocComment(
79+
new Doc(implode(PHP_EOL, [
80+
'/**',
81+
' * @return \\' . PromiseInterface::class . '<' . implode('|', array_unique($callReturnTypes)) . '>',
82+
' */',
83+
]))
84+
)->addParam((new Param('call'))->setType('string'))->addParam((new Param('params'))->setType('array')->setDefault([]))
85+
);
86+
87+
$class->addStmt(
88+
$factory->method('hydrateObject')->makePublic()->setReturnType('object')->addParam(
89+
(new Param('className'))->setType('string')
90+
)->addParam(
91+
(new Param('data'))->setType('array')
92+
)
93+
);
94+
95+
yield new File($namespace . '\\' . 'ClientInterface', $stmt->addStmt($class)->getNode());
96+
}
97+
}

0 commit comments

Comments
 (0)