Skip to content

Commit

Permalink
Added dateTimeClass specification parameter (#182)
Browse files Browse the repository at this point in the history
  • Loading branch information
msalakhov committed Oct 23, 2023
1 parent 1aec01f commit ba74594
Show file tree
Hide file tree
Showing 9 changed files with 72 additions and 16 deletions.
1 change: 1 addition & 0 deletions src/DependencyInjection/Configuration.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->isRequired()
->cannotBeEmpty()
->end()
->scalarNode('date_time_class')->end()
->end()
->end()
->end();
Expand Down
3 changes: 2 additions & 1 deletion src/DependencyInjection/OpenApiServerExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ public function load(array $configs, ContainerBuilder $container): void
* path: string,
* type?: string,
* name_space: string,
* media_type: string
* media_type: string,
* date_time_class?: string,
* }
* } $config
*/
Expand Down
7 changes: 6 additions & 1 deletion src/Serializer/ArrayDtoSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,13 @@ private function convert(bool $deserialize, array $source, ObjectSchema $params)
/** @psalm-suppress MissingClosureParamType */
$converter = fn ($v) => $this->convert($deserialize, $v, $objectType->getSchema());
} else {
$outputClass = null;
if ($typeId !== null && $this->resolver->isDateTime($typeId)) {
$outputClass = $property->getOutputType();
}

/** @psalm-suppress MissingClosureParamType */
$converter = fn ($v) => $this->resolver->convert($deserialize, $typeId ?? 0, $v);
$converter = fn ($v) => $this->resolver->convert($deserialize, $typeId ?? 0, $v, $outputClass);
}

if ($property->isArray()) {
Expand Down
13 changes: 13 additions & 0 deletions src/Specification/Definitions/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ final class Property
private ObjectSchema|ObjectReference|null $objectTypeDefinition = null;
private ?string $description = null;
private ?string $pattern = null;
private ?object $outputType = null;

public function __construct(string $name)
{
Expand Down Expand Up @@ -147,4 +148,16 @@ public function setNullable(bool $nullable): self

return $this;
}

public function getOutputType(): ?object
{
return $this->outputType;
}

public function setOutputType(?object $outputType): self
{
$this->outputType = $outputType;

return $this;
}
}
17 changes: 12 additions & 5 deletions src/Specification/Definitions/SpecificationConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ final class SpecificationConfig
private ?string $type;
private string $nameSpace;
private string $mediaType;
private ?string $dateTimeClass;

public function __construct(string $path, ?string $type, string $nameSpace, string $mediaType)
public function __construct(string $path, ?string $type, string $nameSpace, string $mediaType, ?string $dateTimeClass = null)
{
$this->path = $path;
$this->type = $type;
$this->nameSpace = $nameSpace;
$this->mediaType = $mediaType;
$this->path = $path;
$this->type = $type;
$this->nameSpace = $nameSpace;
$this->mediaType = $mediaType;
$this->dateTimeClass = $dateTimeClass;
}

public function getPath(): string
Expand All @@ -38,4 +40,9 @@ public function getMediaType(): string
{
return $this->mediaType;
}

public function getDateTimeClass(): ?string
{
return $this->dateTimeClass;
}
}
5 changes: 3 additions & 2 deletions src/Specification/SpecificationLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,16 @@ public function __construct(SpecificationParser $parser, FileLocatorInterface $l
}

/**
* @param array{path:string,type:string|null,name_space:string,media_type:string} $spec
* @param array{path:string,type:string|null,name_space:string,media_type:string,date_time_class:string|null} $spec
*/
public function registerSpec(string $name, array $spec): void
{
$this->specs[$name] = new SpecificationConfig(
$spec['path'],
$spec['type'] ?? null,
$spec['name_space'],
$spec['media_type']
$spec['media_type'],
$spec['date_time_class'] ?? null
);
}

Expand Down
14 changes: 12 additions & 2 deletions src/Specification/SpecificationParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use cebe\openapi\spec\Responses;
use cebe\openapi\spec\Schema;
use cebe\openapi\spec\Type;
use DateTimeInterface;
use OnMoon\OpenApiServerBundle\Exception\CannotParseOpenApi;
use OnMoon\OpenApiServerBundle\Specification\Definitions\ComponentArray;
use OnMoon\OpenApiServerBundle\Specification\Definitions\ObjectReference;
Expand Down Expand Up @@ -44,12 +45,12 @@ class SpecificationParser
private ScalarTypesResolver $typeResolver;
/** @var string[] */
private array $skipHttpCodes;
private ?DateTimeInterface $dateTimeClass = null;

/** @param array<array-key, string|int> $skipHttpCodes */
public function __construct(ScalarTypesResolver $typeResolver, array $skipHttpCodes)
{
$this->typeResolver = $typeResolver;

$this->typeResolver = $typeResolver;
$this->skipHttpCodes = array_map(static fn ($code) => (string) $code, $skipHttpCodes);
}

Expand All @@ -58,6 +59,11 @@ public function parseOpenApi(string $specificationName, SpecificationConfig $spe
$componentSchemas = new ComponentArray();

$operationDefinitions = [];

if ($specificationConfig->getDateTimeClass() !== null) {
$this->dateTimeClass = new ($specificationConfig->getDateTimeClass())();
}

/**
* @var string $url
*/
Expand Down Expand Up @@ -385,6 +391,10 @@ private function getProperty(
if (Type::isScalar($itemProperty->type)) {
$scalarTypeId = $this->typeResolver->findScalarType($itemProperty->type, $itemProperty->format);
$propertyDefinition->setScalarTypeId($scalarTypeId);

if ($this->typeResolver->isDateTime($scalarTypeId) && $this->dateTimeClass !== null) {
$propertyDefinition->setOutputType($this->dateTimeClass);
}
} elseif ($itemProperty->type === Type::OBJECT) {
$objectType = $this->getObjectSchema(
$itemProperty,
Expand Down
7 changes: 6 additions & 1 deletion src/Types/ScalarTypesResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use cebe\openapi\spec\Type;

use function dd;
use function is_string;
use function Safe\settype;

Expand Down Expand Up @@ -71,7 +72,7 @@ public function __construct()
*
* @return mixed
*/
public function convert(bool $deserialize, int $id, $value)
public function convert(bool $deserialize, int $id, $value, ?object $outputClass = null)
{
if ($value === null) {
return null;
Expand All @@ -80,6 +81,10 @@ public function convert(bool $deserialize, int $id, $value)
$format = $this->scalarTypes[$id];

if ($deserialize && isset($format['deserializer'])) {
if ($outputClass !== null) {
return TypeSerializer::{$format['deserializer']}($value, $outputClass);
}

return TypeSerializer::{$format['deserializer']}($value);
}

Expand Down
21 changes: 17 additions & 4 deletions src/Types/TypeSerializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,37 @@
namespace OnMoon\OpenApiServerBundle\Types;

use DateTime;
use DateTimeInterface;

use function base64_encode;
use function Safe\base64_decode;

class TypeSerializer
{
public static function deserializeDate(string $date): DateTime
private const DESERIALIZATION_DATE_FORMAT = 'Y-m-d';
private const SERIALIZATION_DATE_FORMAT = 'c';


public static function deserializeDate(string $date, ?DateTimeInterface $dateTimeClass = null): DateTimeInterface
{
return \Safe\DateTime::createFromFormat('Y-m-d', $date);
if ($dateTimeClass !== null) {
return $dateTimeClass::createFromFormat(self::DESERIALIZATION_DATE_FORMAT, $date);
}

return \Safe\DateTime::createFromFormat(self::DESERIALIZATION_DATE_FORMAT, $date);
}

public static function serializeDate(DateTime $date): string
{
return $date->format('Y-m-d');
return $date->format(self::SERIALIZATION_DATE_FORMAT);
}

public static function deserializeDateTime(string $date): DateTime
public static function deserializeDateTime(string $date, ?DateTimeInterface $dateTimeClass = null): DateTimeInterface
{
if ($dateTimeClass !== null) {
return new $dateTimeClass($date);
}

return new \Safe\DateTime($date);
}

Expand Down

0 comments on commit ba74594

Please sign in to comment.