Skip to content

Commit

Permalink
Make as many unit tests as possible pass
Browse files Browse the repository at this point in the history
  • Loading branch information
WyriHaximus committed Nov 29, 2023
1 parent a39ed4d commit bbfcb6b
Show file tree
Hide file tree
Showing 154 changed files with 7,944 additions and 1,504 deletions.
7 changes: 4 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"jawira/case-converter": "^3.5",
"kwn/number-to-words": "^2.6",
"league/openapi-psr7-validator": "^0.21",
"league/uri": "^6.8 || ^7.3",
"nikic/php-parser": "^4.15",
"nunomaduro/termwind": "^1.15",
"ondram/ci-detector": "^4.1",
Expand Down Expand Up @@ -55,10 +56,10 @@
],
"config": {
"allow-plugins": {
"wyrihaximus/composer-update-bin-autoload-path": true,
"infection/extension-installer": true,
"dealerdirect/phpcodesniffer-composer-installer": true,
"ergebnis/composer-normalize": true
"ergebnis/composer-normalize": true,
"infection/extension-installer": true,
"wyrihaximus/composer-update-bin-autoload-path": true
},
"platform": {
"php": "8.2.13"
Expand Down
646 changes: 360 additions & 286 deletions composer.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions example/templates/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"devizzent/cebe-php-openapi": "^1",
"eventsauce/object-hydrator": "^1.1",
"league/openapi-psr7-validator": "^0.21",
"league/uri": "^7.3 || ^6.8",
"psr/http-message": "^1.0",
"react/http": "^1.8",
"react/async": "^4.0",
Expand Down
97 changes: 97 additions & 0 deletions src/Gatherer/CompositSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

declare(strict_types=1);

namespace ApiClients\Tools\OpenApiClientGenerator\Gatherer;

use ApiClients\Tools\OpenApiClientGenerator\ClassString;
use ApiClients\Tools\OpenApiClientGenerator\Configuration\Namespace_;
use ApiClients\Tools\OpenApiClientGenerator\Registry\CompositSchema as CompositSchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Contract as ContractRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Schema as SchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Representation\Schema;
use ApiClients\Tools\OpenApiClientGenerator\Utils;
use cebe\openapi\spec\Schema as baseSchema;

use function array_key_exists;
use function in_array;
use function is_array;
use function property_exists;

final class CompositSchema
{
public static function gather(
Namespace_ $baseNamespace,
string $className,
baseSchema $schema,
SchemaRegistry $schemaRegistry,
ContractRegistry $contractRegistry,
CompositSchemaRegistry $compositSchemaRegistry,
): Schema {
$className = Utils::className($className);
$isArray = $schema->type === 'array';
$properties = [];
$example = [];

if ($isArray) {
$schema = $schema->items;
}

foreach ($schema->properties as $propertyName => $property) {
$gatheredProperty = Property::gather(
$baseNamespace,
$className,
(string) $propertyName,
in_array(
(string) $propertyName,
$schema->required ?? [],
false,
),
$property,
$schemaRegistry,
$contractRegistry,
$compositSchemaRegistry,
);
$properties[] = $gatheredProperty;

$example[$gatheredProperty->sourceName] = $gatheredProperty->example->raw;

foreach (['examples', 'example'] as $examplePropertyName) {
if (array_key_exists($gatheredProperty->sourceName, $example)) {
break;
}

if (! property_exists($schema, $examplePropertyName) || ! is_array($schema->$examplePropertyName) || ! array_key_exists($gatheredProperty->sourceName, $schema->$examplePropertyName)) {
continue;
}

$example[$gatheredProperty->sourceName] = $schema->$examplePropertyName[$gatheredProperty->sourceName];
}

foreach ($property->enum ?? [] as $value) {
$example[$gatheredProperty->sourceName] = $value;
break;
}

if ($example[$gatheredProperty->sourceName] !== null || $schema->required) {
continue;
}

unset($example[$gatheredProperty->sourceName]);
}

return new Schema(
ClassString::factory($baseNamespace, 'Schema\\' . $className),
ClassString::factory($baseNamespace, 'Contract\\' . $className),
ClassString::factory($baseNamespace, 'Error\\' . $className),
ClassString::factory($baseNamespace, 'ErrorSchemas\\' . $className),
$schema->title ?? '',
$schema->description ?? '',
$example,
$properties,
$schema,
$isArray,
($schema->type === null ? ['object'] : (is_array($schema->type) ? $schema->type : [$schema->type])),
);
}
}
31 changes: 30 additions & 1 deletion src/Gatherer/ExampleData.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,24 @@
use ReverseRegex\Lexer;
use ReverseRegex\Parser;

use function explode;
use function gettype;
use function is_array;
use function is_string;
use function Safe\date;
use function Safe\json_encode;
use function strlen;
use function strpos;

final class ExampleData
{
public static function gather(mixed $exampleData, PropertyType $type, string $propertyName): Representation\ExampleData
{
if ($type->type === 'array') {
if ($exampleData instanceof Representation\ExampleData) {
return $exampleData;
}

if ($type->type === 'array' || $type->type === 'union') {
if ($type->payload instanceof Schema) {
$exampleData = ArrayMerger::doMerge(
$type->payload->example,
Expand Down Expand Up @@ -90,6 +96,12 @@ public static function determiteType(mixed $exampleData): Representation\Example
/** @phpstan-ignore-next-line */
public static function scalarData(int $seed, string $type, string|null $format, string|null $pattern = null): Representation\ExampleData
{
if (strpos($type, '|') !== false) {
[$firstType] = explode('|', $type);

return self::scalarData($seed, $firstType, $format, $pattern);
}

if ($type === 'int' || $type === '?int') {
return new Representation\ExampleData($seed, new Node\Scalar\LNumber($seed));
}
Expand Down Expand Up @@ -149,6 +161,23 @@ public static function scalarData(int $seed, string $type, string|null $format,
return new Representation\ExampleData('generated', new Node\Scalar\String_('generated'));
}

if ($type === 'array' || $type === '?array') {
$string = self::scalarData($seed, 'string', $format, $pattern);

return new Representation\ExampleData(
[
$string->raw,
],
new Node\Expr\Array_(
[
new Node\Expr\ArrayItem(
$string->node,
),
],
),
);
}

return new Representation\ExampleData(
null,
new Node\Expr\ConstFetch(
Expand Down
106 changes: 106 additions & 0 deletions src/Gatherer/IntersectionSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);

namespace ApiClients\Tools\OpenApiClientGenerator\Gatherer;

use ApiClients\Tools\OpenApiClientGenerator\ClassString;
use ApiClients\Tools\OpenApiClientGenerator\Configuration\Namespace_;
use ApiClients\Tools\OpenApiClientGenerator\Registry\CompositSchema as CompositSchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Contract as ContractRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Schema as SchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Representation\Contract;
use ApiClients\Tools\OpenApiClientGenerator\Representation\Schema;
use ApiClients\Tools\OpenApiClientGenerator\Utils;
use cebe\openapi\spec\Schema as baseSchema;

use function array_key_exists;
use function in_array;
use function is_array;
use function property_exists;

final class IntersectionSchema
{
public static function gather(
Namespace_ $baseNamespace,
string $className,
baseSchema $baseProperty,
SchemaRegistry $schemaRegistry,
ContractRegistry $contractRegistry,
CompositSchemaRegistry $compositSchemaRegistry,
): Schema {
$className = Utils::className($className);
$contracts = [];
$properties = [];
$example = [];

foreach ($baseProperty->allOf as $schema) {
$gatheredProperties = [];
foreach ($schema->properties as $propertyName => $property) {
$gatheredProperty = $gatheredProperties[(string) $propertyName] = Property::gather(
$baseNamespace,
$className,
(string) $propertyName,
in_array(
(string) $propertyName,
$schema->required ?? [],
false,
),
$property,
$schemaRegistry,
$contractRegistry,
$compositSchemaRegistry,
);

$example[$gatheredProperty->sourceName] = $gatheredProperty->example->raw;

foreach (['examples', 'example'] as $examplePropertyName) {
if (array_key_exists($gatheredProperty->sourceName, $example)) {
break;
}

if (! property_exists($schema, $examplePropertyName) || ! is_array($schema->$examplePropertyName) || ! array_key_exists($gatheredProperty->sourceName, $schema->$examplePropertyName)) {
continue;
}

$example[$gatheredProperty->sourceName] = $schema->$examplePropertyName[$gatheredProperty->sourceName];
}

foreach ($property->enum ?? [] as $value) {
$example[$gatheredProperty->sourceName] = $value;
break;
}

if ($example[$gatheredProperty->sourceName] !== null || $property->required || $baseProperty->required) {
continue;
}

unset($example[$gatheredProperty->sourceName]);
}

$contracts[] = new Contract(
ClassString::factory(
$baseNamespace,
$contractRegistry->get($schema, 'Contract\\' . $className . '\\' . $schema->title),
),
$gatheredProperties,
);

$properties = [...$properties, ...$gatheredProperties];
}

return new Schema(
ClassString::factory($baseNamespace, 'Schema\\' . $className),
$contracts,
ClassString::factory($baseNamespace, 'Error\\' . $className),
ClassString::factory($baseNamespace, 'ErrorSchemas\\' . $className),
$baseProperty->title ?? '',
$baseProperty->description ?? '',
$example,
$properties,
$baseProperty,
false,
($baseProperty->type === null ? ['object'] : (is_array($baseProperty->type) ? $baseProperty->type : [$baseProperty->type])),
);
}
}
20 changes: 18 additions & 2 deletions src/Gatherer/Operation.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

use ApiClients\Tools\OpenApiClientGenerator\ClassString;
use ApiClients\Tools\OpenApiClientGenerator\Configuration\Namespace_;
use ApiClients\Tools\OpenApiClientGenerator\Registry\CompositSchema as CompositSchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Contract as ContractRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\Schema as SchemaRegistry;
use ApiClients\Tools\OpenApiClientGenerator\Registry\ThrowableSchema;
use ApiClients\Tools\OpenApiClientGenerator\Representation\Header;
Expand Down Expand Up @@ -45,11 +47,21 @@ public static function gather(
openAPIOperation $operation,
ThrowableSchema $throwableSchemaRegistry,
SchemaRegistry $schemaRegistry,
ContractRegistry $contractRegistry,
CompositSchemaRegistry $compositSchemaRegistry,
): \ApiClients\Tools\OpenApiClientGenerator\Representation\Operation {
$returnType = [];
$parameters = [];
$empties = [];
foreach ($operation->parameters as $parameter) {
$types = is_array($parameter->schema->type) ? $parameter->schema->type : [$parameter->schema->type];
if (count($parameter->schema->oneOf ?? []) > 0) {
$types = [];
foreach ($parameter->schema->oneOf as $oneOfSchema) {
$types[] = $oneOfSchema->type;
}
}

$parameterType = str_replace([
'integer',
'any',
Expand All @@ -58,7 +70,7 @@ public static function gather(
'int',
'string|object',
'bool',
], implode('|', is_array($parameter->schema->type) ? $parameter->schema->type : [$parameter->schema->type]));
], implode('|', $types));

$parameters[] = new Parameter(
(new Convert($parameter->name))->toCamel(),
Expand All @@ -82,7 +94,7 @@ public static function gather(
);
$requestBody[] = new OperationRequestBody(
$contentType,
Schema::gather($baseNamespace, $requestBodyClassname, $requestBodyDetails->schema, $schemaRegistry),
Schema::gather($baseNamespace, $requestBodyClassname, $requestBodyDetails->schema, $schemaRegistry, $contractRegistry, $compositSchemaRegistry),
);
}
}
Expand Down Expand Up @@ -115,6 +127,8 @@ public static function gather(
$contentTypeMediaType->schema,
true,
$schemaRegistry,
$contractRegistry,
$compositSchemaRegistry,
),
);
if ($isError) {
Expand All @@ -139,6 +153,8 @@ public static function gather(
),
$headerSpec->schema,
$schemaRegistry,
$contractRegistry,
$compositSchemaRegistry,
), ExampleData::determiteType($headerSpec->example));
}

Expand Down
Loading

0 comments on commit bbfcb6b

Please sign in to comment.