Skip to content

Commit 42eef82

Browse files
authored
Merge branch 'master' into improved-string-length
2 parents ab88be5 + 85f5f42 commit 42eef82

21 files changed

+458
-8
lines changed

CHANGELOG.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,18 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7-
## [7.0.0] - 2021-07-27
7+
## [7.0.0] - 2021-08-27
88
### Fixed
99
- Using `grapheme_strlen` to properly count string lengths.
1010

11+
## [6.1.0] - 2021-08-27
12+
### Added
13+
- Readded enums as consts only
14+
15+
## [6.0.2] - 2021-08-12
16+
### Fixed
17+
- The array of serializers in BodySerializer depends on both requests and responses content type
18+
1119
## [6.0.1] - 2021-07-27
1220
### Fixed
1321
- Fix preg_match pattern by adding a slash (/) as a delimiter.

example/gen/src/Request/FindPetsByStatusRequest.php

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
class FindPetsByStatusRequest implements RequestInterface
1414
{
15+
public const STATUS_AVAILABLE = 'available';
16+
17+
public const STATUS_PENDING = 'pending';
18+
19+
public const STATUS_SOLD = 'sold';
20+
1521
private ?string $status = null;
1622

1723
private string $contentType = '';

example/gen/src/Schema/Order.php

+6
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@
1313

1414
class Order implements SerializableInterface, JsonSerializable
1515
{
16+
public const STATUS_PLACED = 'placed';
17+
18+
public const STATUS_APPROVED = 'approved';
19+
20+
public const STATUS_DELIVERED = 'delivered';
21+
1622
private ?int $id = null;
1723

1824
private ?int $petId = null;

example/gen/src/Schema/Pet.php

+6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@
1212

1313
class Pet implements SerializableInterface, JsonSerializable
1414
{
15+
public const STATUS_AVAILABLE = 'available';
16+
17+
public const STATUS_PENDING = 'pending';
18+
19+
public const STATUS_SOLD = 'sold';
20+
1521
private ?int $id = null;
1622

1723
private string $name;

example/test-example.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@
1515
use OpenApi\PetStoreClient\SwaggerPetstoreOpenAPI3ClientFactory;
1616

1717
// https://petstore3.swagger.io/api/v3/openapi.json
18-
$client = new Client(['base_uri' => 'https://petstore.swagger.io/v2/pet']);
18+
$client = new Client(['base_uri' => 'https://petstore.swagger.io/v2/']);
1919
$factory = new SwaggerPetstoreOpenAPI3ClientFactory();
2020
$client = $factory->create($client);
2121

2222
$request = new FindPetsByStatusRequest();
23-
$request->setStatus('sold');
23+
$request->setStatus('pending');
2424
$result = $client->findPetsByStatus($request);
2525
if ($result === null || $result->count() === 0) {
2626
sprintf('findPetsByStatus failed, result: %s', json_encode($result, JSON_THROW_ON_ERROR)) || exit(1);

src/Entity/Field.php

+13
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class Field
2323
private bool $nullable;
2424
private ?Field $arrayItem = null;
2525
private array $objectProperties = [];
26+
private array $enumValues = [];
2627
private string $format = '';
2728
/** @phpstan-ignore-next-line cannot use strict type before PHP8 with "mixed" pseudo type */
2829
private $default;
@@ -74,6 +75,18 @@ public function setObjectProperties(array $objectProperties): self
7475
return $this;
7576
}
7677

78+
public function getEnumValues(): ?array
79+
{
80+
return $this->enumValues;
81+
}
82+
83+
public function setEnumValues(array $enumValues): self
84+
{
85+
$this->enumValues = $enumValues;
86+
87+
return $this;
88+
}
89+
7790
public function getFormat(): ?string
7891
{
7992
return $this->format;

src/Entity/Response.php

+29-1
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,38 @@
22

33
namespace DoclerLabs\ApiClientGenerator\Entity;
44

5+
use DoclerLabs\ApiClientGenerator\Input\InvalidSpecificationException;
6+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\FormUrlencodedContentTypeSerializer;
7+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\JsonContentTypeSerializer;
8+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\VdnApiJsonContentTypeSerializer;
9+
use DoclerLabs\ApiClientGenerator\Output\Copy\Serializer\ContentType\XmlContentTypeSerializer;
10+
511
class Response
612
{
13+
private const ALLOWED_CONTENT_TYPES = [
14+
JsonContentTypeSerializer::MIME_TYPE,
15+
FormUrlencodedContentTypeSerializer::MIME_TYPE,
16+
XmlContentTypeSerializer::MIME_TYPE,
17+
VdnApiJsonContentTypeSerializer::MIME_TYPE,
18+
];
19+
720
private int $statusCode;
821
private ?Field $body;
22+
private array $bodyContentTypes;
923

10-
public function __construct(int $statusCode, Field $body = null)
24+
public function __construct(int $statusCode, Field $body = null, array $bodyContentTypes = [])
1125
{
1226
$this->statusCode = $statusCode;
1327
$this->body = $body;
28+
29+
$unsupportedContentTypes = array_diff($bodyContentTypes, static::ALLOWED_CONTENT_TYPES);
30+
if (!empty($unsupportedContentTypes)) {
31+
throw new InvalidSpecificationException(
32+
sprintf('Response content-type %s is not currently supported.', json_encode($unsupportedContentTypes))
33+
);
34+
}
35+
36+
$this->bodyContentTypes = $bodyContentTypes;
1437
}
1538

1639
public function getStatusCode(): int
@@ -22,4 +45,9 @@ public function getBody(): ?Field
2245
{
2346
return $this->body;
2447
}
48+
49+
public function getBodyContentTypes(): array
50+
{
51+
return $this->bodyContentTypes;
52+
}
2553
}

src/Generator/MutatorAccessorClassGeneratorAbstract.php

+18
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
use DoclerLabs\ApiClientGenerator\Entity\Constraint\ConstraintInterface;
1111
use DoclerLabs\ApiClientGenerator\Entity\Field;
1212
use DoclerLabs\ApiClientGenerator\Input\Specification;
13+
use DoclerLabs\ApiClientGenerator\Naming\SchemaNaming;
1314
use DoclerLabs\ApiClientGenerator\Output\Php\PhpFileCollection;
1415
use PhpParser\Node\Stmt\ClassMethod;
1516
use PhpParser\Node\Stmt\Property;
@@ -98,6 +99,23 @@ protected function getGetMethodName(Field $field): string
9899
return sprintf('get%s', ucfirst($field->getPhpVariableName()));
99100
}
100101

102+
protected function generateEnumStatements(Field $field): array
103+
{
104+
$statements = [];
105+
$enumValues = $field->getEnumValues();
106+
if (!empty($enumValues)) {
107+
foreach ($enumValues as $enumValue) {
108+
$constName = SchemaNaming::getEnumConstName($field, $enumValue);
109+
$statements[] = $this->builder->constant(
110+
$constName,
111+
$this->builder->val($enumValue)
112+
);
113+
}
114+
}
115+
116+
return $statements;
117+
}
118+
101119
protected function generateConstraints(Field $root): array
102120
{
103121
$stmts = [];

src/Generator/RequestGenerator.php

+15
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ protected function generateRequest(PhpFileCollection $fileRegistry, Operation $o
3636
$classBuilder = $this->builder
3737
->class($className)
3838
->implement('RequestInterface')
39+
->addStmts($this->generateEnums($request))
3940
->addStmts($this->generateProperties($request))
4041
->addStmt($this->generateConstructor($request))
4142
->addStmt($this->generateGetContentType())
@@ -47,6 +48,20 @@ protected function generateRequest(PhpFileCollection $fileRegistry, Operation $o
4748
$this->registerFile($fileRegistry, $classBuilder, self::SUBDIRECTORY, self::NAMESPACE_SUBPATH);
4849
}
4950

51+
protected function generateEnums(Request $request): array
52+
{
53+
$statements = [];
54+
foreach ($request->getFields() as $fields) {
55+
foreach ($fields as $field) {
56+
foreach ($this->generateEnumStatements($field) as $statement) {
57+
$statements[] = $statement;
58+
}
59+
}
60+
}
61+
62+
return $statements;
63+
}
64+
5065
protected function generateProperties(Request $request): array
5166
{
5267
$statements = [];

src/Generator/SchemaGenerator.php

+13
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ protected function generateSchema(Field $field, PhpFileCollection $fileRegistry)
3636
$classBuilder = $this->builder
3737
->class($className)
3838
->implement('SerializableInterface', 'JsonSerializable')
39+
->addStmts($this->generateEnumConsts($field))
3940
->addStmts($this->generateProperties($field))
4041
->addStmt($this->generateConstructor($field))
4142
->addStmts($this->generateSetMethods($field))
@@ -46,6 +47,18 @@ protected function generateSchema(Field $field, PhpFileCollection $fileRegistry)
4647
$this->registerFile($fileRegistry, $classBuilder, self::SUBDIRECTORY, self::NAMESPACE_SUBPATH);
4748
}
4849

50+
protected function generateEnumConsts(Field $root): array
51+
{
52+
$statements = [];
53+
foreach ($root->getObjectProperties() as $propertyField) {
54+
foreach ($this->generateEnumStatements($propertyField) as $statement) {
55+
$statements[] = $statement;
56+
}
57+
}
58+
59+
return $statements;
60+
}
61+
4962
protected function generateProperties(Field $root): array
5063
{
5164
$statements = [];

src/Input/Factory/FieldFactory.php

+5
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ public function create(
118118
$field->setArrayItem($arrayItem);
119119
} elseif (!empty($objectProperties)) {
120120
$field->setObjectProperties($objectProperties);
121+
} elseif (isset($schema->enum)) {
122+
if (!FieldType::isSpecificationTypeString($type)) {
123+
throw new InvalidSpecificationException('Only string enum fields are currently supported');
124+
}
125+
$field->setEnumValues($schema->enum);
121126
}
122127

123128
if (isset($schema->format)) {

src/Input/Factory/ResponseFactory.php

+6-4
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,14 @@ public function createSuccessful(string $operationName, array $openApiResponses)
3434
return new Response((int)$code, null);
3535
}
3636

37-
$schema = null;
38-
foreach ($response->content as $content) {
37+
$contentTypes = [];
38+
$schema = null;
39+
foreach ($response->content as $contentType => $content) {
3940
if ($schema !== null && !Parity::isEqualTo($content->schema, $schema)) {
4041
throw new InvalidSpecificationException('Multiple schemas per response is not currently supported.');
4142
}
42-
$schema = $content->schema;
43+
$schema = $content->schema;
44+
$contentTypes[] = $contentType;
4345
}
4446

4547
$schemaName = SchemaNaming::getClassName($schema, ucfirst($operationName) . 'ResponseBody');
@@ -52,7 +54,7 @@ public function createSuccessful(string $operationName, array $openApiResponses)
5254
$schemaName
5355
);
5456

55-
return new Response((int)$code, $body);
57+
return new Response((int)$code, $body, $contentTypes);
5658
}
5759
}
5860

src/Input/Specification.php

+3
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,9 @@ public function getAllContentTypes(): array
9191
foreach ($operation->getRequest()->getBodyContentTypes() as $contentType) {
9292
$allContentTypes[$contentType] = true;
9393
}
94+
foreach ($operation->getSuccessfulResponse()->getBodyContentTypes() as $contentType) {
95+
$allContentTypes[$contentType] = true;
96+
}
9497
}
9598

9699
return array_keys(array_filter($allContentTypes));

src/Naming/SchemaNaming.php

+9
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,13 @@ public static function getClassName(SpecObjectInterface $reference, string $fall
3535

3636
return CaseCaster::toPascal($referencePath[0]);
3737
}
38+
39+
public static function getEnumConstName(Field $field, string $enum): string
40+
{
41+
return sprintf(
42+
'%s_%s',
43+
CaseCaster::toMacro($field->getName()),
44+
CaseCaster::toMacro($enum)
45+
);
46+
}
3847
}

test/suite/functional/Generator/Request/PatchResourceRequest.php

+4
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
class PatchResourceRequest implements RequestInterface
1515
{
16+
public const ACCEPT_APPLICATION_JSON = 'application/json';
17+
18+
public const ACCEPT_APPLICATION_XML = 'application/xml';
19+
1620
private string $accept;
1721

1822
private PatchResourceRequestBody $patchResourceRequestBody;

test/suite/functional/Generator/Request/PutResourceByIdRequest.php

+12
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,18 @@
1616

1717
class PutResourceByIdRequest implements RequestInterface
1818
{
19+
public const ENUM_PARAMETER_ONE_VALUE = 'one value';
20+
21+
public const ENUM_PARAMETER_ANOTHER_VALUE = 'another value';
22+
23+
public const ENUM_PARAMETER_THIRD_VALUE = 'third value';
24+
25+
public const MANDATORY_ENUM_PARAMETER_ONE_VALUE = 'one value';
26+
27+
public const MANDATORY_ENUM_PARAMETER_ANOTHER_VALUE = 'another value';
28+
29+
public const MANDATORY_ENUM_PARAMETER_THIRD_VALUE = 'third value';
30+
1931
private int $resourceId;
2032

2133
private ?int $integerParameter = null;

test/suite/functional/Generator/Schema/ItemPhp70.php

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
class Item implements SerializableInterface, JsonSerializable
1616
{
17+
const MANDATORY_ENUM_ONE_OPTION = 'one option';
18+
19+
const MANDATORY_ENUM_ANOTHER_OPTION = 'another option';
20+
21+
const OPTIONAL_ENUM_ONE_OPTION = 'one option';
22+
23+
const OPTIONAL_ENUM_ANOTHER_OPTION = 'another option';
24+
1725
/** @var int */
1826
private $mandatoryInteger;
1927

test/suite/functional/Generator/Schema/ItemPhp72.php

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
class Item implements SerializableInterface, JsonSerializable
1616
{
17+
public const MANDATORY_ENUM_ONE_OPTION = 'one option';
18+
19+
public const MANDATORY_ENUM_ANOTHER_OPTION = 'another option';
20+
21+
public const OPTIONAL_ENUM_ONE_OPTION = 'one option';
22+
23+
public const OPTIONAL_ENUM_ANOTHER_OPTION = 'another option';
24+
1725
/** @var int */
1826
private $mandatoryInteger;
1927

test/suite/functional/Generator/Schema/ItemPhp74.php

+8
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,14 @@
1414

1515
class Item implements SerializableInterface, JsonSerializable
1616
{
17+
public const MANDATORY_ENUM_ONE_OPTION = 'one option';
18+
19+
public const MANDATORY_ENUM_ANOTHER_OPTION = 'another option';
20+
21+
public const OPTIONAL_ENUM_ONE_OPTION = 'one option';
22+
23+
public const OPTIONAL_ENUM_ANOTHER_OPTION = 'another option';
24+
1725
private int $mandatoryInteger;
1826

1927
private string $mandatoryString;

0 commit comments

Comments
 (0)