Skip to content

Commit

Permalink
feat: support backed enum and datetime
Browse files Browse the repository at this point in the history
  • Loading branch information
darkdarin committed Jul 23, 2024
1 parent 5b40ce5 commit 4b4559e
Show file tree
Hide file tree
Showing 5 changed files with 122 additions and 9 deletions.
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@
"laravel"
],
"require": {
"php": ">=7.4",
"php": ">=8.0",
"ext-json": "*",
"illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/console": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/container": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/pipeline": "^6.0|^7.0|^8.0|^9.0|^10.0",
"illuminate/support": "^8.0|^9.0|^10.0",
"illuminate/console": "^8.0|^9.0|^10.0",
"illuminate/container": "^8.0|^9.0|^10.0",
"illuminate/pipeline": "^8.0|^9.0|^10.0",
"spiral/attributes": "^2.8",
"tochka-developers/jsonrpc": "^4.0|^5.0",
"tochka-developers/jsonrpc-annotations": "^1.1"
},
"require-dev": {
"roave/security-advisories": "dev-latest",
"phpunit/phpunit": "^9.5|^10.0",
"phpunit/phpunit": "^10.0",
"mockery/mockery": "^1.0"
},
"autoload": {
Expand Down
8 changes: 6 additions & 2 deletions src/OpenRpcServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
use Tochka\OpenRpc\Handlers\OpenRpcCacheHandler;
use Tochka\OpenRpc\Handlers\OpenRpcGenerator;
use Tochka\OpenRpc\Pipes\ArrayShapePipe;
use Tochka\OpenRpc\Pipes\BackedEnumPipe;
use Tochka\OpenRpc\Pipes\ClassPropertyFromPhpDocPipe;
use Tochka\OpenRpc\Pipes\EnumPipe;
use Tochka\OpenRpc\Pipes\BenSampoEnumPipe;
use Tochka\OpenRpc\Pipes\DateTimePipe;
use Tochka\OpenRpc\Pipes\ExpectedValuesPipe;
use Tochka\OpenRpc\Pipes\ModelPipe;
use Tochka\OpenRpc\Pipes\ValueExamplePipe;
Expand Down Expand Up @@ -51,7 +53,9 @@ function () {
$instance->addPipe(new ExpectedValuesPipe());
$instance->addPipe(new ValueExamplePipe());
$instance->addPipe(new ArrayShapePipe());
$instance->addPipe(new EnumPipe());
$instance->addPipe(new DateTimePipe());
$instance->addPipe(new BackedEnumPipe());
$instance->addPipe(new BenSampoEnumPipe());
$instance->addPipe(new ModelPipe());
$instance->addPipe(new ClassPropertyFromPhpDocPipe());

Expand Down
78 changes: 78 additions & 0 deletions src/Pipes/BackedEnumPipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<?php

namespace Tochka\OpenRpc\Pipes;

use Tochka\JsonRpc\Facades\JsonRpcDocBlockFactory;
use Tochka\JsonRpc\Route\Parameters\ParameterTypeEnum;
use Tochka\OpenRpc\Contracts\SchemaHandlerPipeInterface;
use Tochka\OpenRpc\DTO\Schema;
use Tochka\OpenRpc\Support\ExpectedSchemaPipeObject;
use Tochka\OpenRpc\Support\StrSupport;

class BackedEnumPipe implements SchemaHandlerPipeInterface
{
public function handle(ExpectedSchemaPipeObject $expected, callable $next): ExpectedSchemaPipeObject
{
/** @var ExpectedSchemaPipeObject $result */
$result = $next($expected);

if (
$result->parameter->className !== null
&& $result->parameter->type->is(ParameterTypeEnum::TYPE_OBJECT)
&& is_subclass_of($result->parameter->className, '\BackedEnum')
) {
$this->setSchemaEnumProperty($result->schema->getSchema(), $result->parameter->className);
}

return $result;
}

/**
* @param Schema $schema
* @param class-string<\BackedEnum> $className
*/
private function setSchemaEnumProperty(Schema $schema, string $className): void
{
$schema->enum = array_map(fn($enum) => $enum->value, $className::cases());

$classDocBlock = JsonRpcDocBlockFactory::makeForClass($className);
if ($classDocBlock !== null) {
$schema->title = $classDocBlock->getSummary();
$schema->description = StrSupport::resolveRef($classDocBlock->getDescription());

$reflector = $classDocBlock->getReflector();
if ($reflector instanceof \ReflectionClass) {
$schema->oneOf = $this->getConstSchemasForValues($reflector);
}
}

if (is_int($className::cases()[0]->value)) {
$schema->type = ParameterTypeEnum::TYPE_INTEGER()->toJsonType();
} elseif (is_string($className::cases()[0]->value)) {
$schema->type = ParameterTypeEnum::TYPE_STRING()->toJsonType();
} else {
$schema->type = ParameterTypeEnum::TYPE_MIXED()->toJsonType();
}
}

private function getConstSchemasForValues(\ReflectionClass $reflector): array
{
$schemas = [];

$constants = $reflector->getReflectionConstants();
foreach ($constants as $constant) {
$docBlock = JsonRpcDocBlockFactory::make($constant);

$schema = new Schema();
$schema->const = $constant->getValue();

if ($docBlock !== null) {
$schema->description = $docBlock->getSummary();
}

$schemas[] = $schema;
}

return $schemas;
}
}
2 changes: 1 addition & 1 deletion src/Pipes/EnumPipe.php → src/Pipes/BenSampoEnumPipe.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Tochka\OpenRpc\Support\ExpectedSchemaPipeObject;
use Tochka\OpenRpc\Support\StrSupport;

class EnumPipe implements SchemaHandlerPipeInterface
class BenSampoEnumPipe implements SchemaHandlerPipeInterface
{
public function handle(ExpectedSchemaPipeObject $expected, callable $next): ExpectedSchemaPipeObject
{
Expand Down
31 changes: 31 additions & 0 deletions src/Pipes/DateTimePipe.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Tochka\OpenRpc\Pipes;

use Tochka\JsonRpc\Route\Parameters\ParameterTypeEnum;
use Tochka\OpenRpc\Contracts\SchemaHandlerPipeInterface;
use Tochka\OpenRpc\Support\ExpectedSchemaPipeObject;

class DateTimePipe implements SchemaHandlerPipeInterface
{
public function handle(ExpectedSchemaPipeObject $expected, callable $next): ExpectedSchemaPipeObject
{
/** @var ExpectedSchemaPipeObject $result */
$result = $next($expected);

if (!is_subclass_of($result->parameter->className, \DateTime::class)) {
return $result;
}

$schema = $result->schema->getSchema();

$schema->type = ParameterTypeEnum::TYPE_STRING()->toJsonType();
$schema->required = [];
$schema->properties = [];
$schema->format = 'datetime';
$schema->title = 'DateTime';
$schema->description = null;

return $result;
}
}

0 comments on commit 4b4559e

Please sign in to comment.