Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port discriminator feature from 4.x branch to master #91

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
53 changes: 35 additions & 18 deletions src/JsonSchema/Generator/Model/GetterSetterGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,29 @@ protected function createGetter(Property $property, string $namespace, bool $req
);
}

protected function createSetter(Property $property, string $namespace, bool $required): Stmt\ClassMethod
protected function createSetter(Property $property, string $namespace, bool $required, bool $fluent = true): Stmt\ClassMethod
{
$setType = $property->getType()->getTypeHint($namespace);

if ($setType && !$required) {
$setType = '?' . $setType;
}

$stmts = [
// $this->property = $property;
new Stmt\Expression(new Expr\Assign(
new Expr\PropertyFetch(
new Expr\Variable('this'),
$this->getNaming()->getPropertyName($property->getPhpName())
), new Expr\Variable($this->getNaming()->getPropertyName($property->getPhpName()))
)),
];

if ($fluent) {
// return $this;
$stmts[] = new Stmt\Return_(new Expr\Variable('this'));
}

return new Stmt\ClassMethod(
// setProperty
$this->getNaming()->getPrefixedMethodName('set', $property->getPhpName()),
Expand All @@ -65,20 +80,10 @@ protected function createSetter(Property $property, string $namespace, bool $req
'params' => [
new Param(new Expr\Variable($this->getNaming()->getPropertyName($property->getPhpName())), null, $setType),
],
'stmts' => [
// $this->property = $property;
new Stmt\Expression(new Expr\Assign(
new Expr\PropertyFetch(
new Expr\Variable('this'),
$this->getNaming()->getPropertyName($property->getPhpName())
), new Expr\Variable($this->getNaming()->getPropertyName($property->getPhpName()))
)),
// return $this;
new Stmt\Return_(new Expr\Variable('this')),
],
'returnType' => 'self',
'stmts' => $stmts,
'returnType' => $fluent ? 'self' : null,
], [
'comments' => [$this->createSetterDoc($property, $namespace, $required)],
'comments' => [$this->createSetterDoc($property, $namespace, $required, $fluent)],
]
);
}
Expand All @@ -95,18 +100,30 @@ protected function createGetterDoc(Property $property, string $namespace, bool $
, $property->getDescription(), $this->getDocType($property, $namespace, $required)));
}

protected function createSetterDoc(Property $property, string $namespace, bool $required): Doc
protected function createSetterDoc(Property $property, string $namespace, bool $required, bool $fluent): Doc
{
return new Doc(sprintf(<<<EOD
$description = sprintf(<<<EOD
/**
* %s
*
* @param %s %s

EOD
, $property->getDescription(), $this->getDocType($property, $namespace, $required), '$' . $property->getPhpName());

if ($fluent) {
$description .= <<<EOD
*
* @return self

EOD;
}

$description .= <<<EOD
*/
EOD
, $property->getDescription(), $this->getDocType($property, $namespace, $required), '$' . $property->getPhpName()));
EOD;

return new Doc($description);
}

private function getDocType(Property $property, string $namespace, bool $required): string
Expand Down
31 changes: 23 additions & 8 deletions src/JsonSchema/Generator/ModelGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
use Jane\JsonSchema\Generator\Model\ClassGenerator;
use Jane\JsonSchema\Generator\Model\GetterSetterGenerator;
use Jane\JsonSchema\Generator\Model\PropertyGenerator;
use Jane\JsonSchema\Guesser\Guess\ClassGuess;
use Jane\JsonSchema\Guesser\Guess\Property;
use Jane\JsonSchema\Schema;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;
Expand Down Expand Up @@ -53,20 +55,33 @@ public function generate(Schema $schema, string $className, Context $context)
foreach ($class->getProperties() as $property) {
$required = !$property->isNullable() && $context->isStrict();
$properties[] = $this->createProperty($property, $schema->getNamespace() . '\\Model');
$methods[] = $this->createGetter($property, $schema->getNamespace() . '\\Model', $required);
$methods[] = $this->createSetter($property, $schema->getNamespace() . '\\Model', $required);
$methods = array_merge($methods, $this->doCreateClassMethods($class, $property, $schema->getNamespace() . '\\Model', $required));
}

$model = $this->createModel(
$class->getName(),
$properties,
$methods,
\count($class->getExtensionsType()) > 0
);
$model = $this->doCreateModel($class, $properties, $methods);

$namespace = new Stmt\Namespace_(new Name($schema->getNamespace() . '\\Model'), [$model]);

$schema->addFile(new File($schema->getDirectory() . '/Model/' . $class->getName() . '.php', $namespace, self::FILE_TYPE_MODEL));
}
}

protected function doCreateClassMethods(ClassGuess $classGuess, Property $property, string $namespace, bool $required)
{
$methods = [];
$methods[] = $this->createGetter($property, $namespace, $required);
$methods[] = $this->createSetter($property, $namespace, $required);

return $methods;
}

protected function doCreateModel(ClassGuess $class, $properties, $methods): Stmt\Class_
{
return $this->createModel(
$class->getName(),
$properties,
$methods,
\count($class->getExtensionsType()) > 0
);
}
}
29 changes: 18 additions & 11 deletions src/JsonSchema/Generator/Normalizer/DenormalizerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,7 @@ protected function createDenormalizeMethod(string $modelFqdn, Context $context,
];
}

array_unshift($statements, new Stmt\If_(
new Expr\BooleanNot(new Expr\FuncCall(new Name('is_object'), [new Arg(new Expr\Variable('data'))])),
[
'stmts' => [
$context->isStrict() ?
new Stmt\Throw_(new Expr\New_(new Name('InvalidArgumentException')))
:
new Stmt\Return_(new Expr\ConstFetch(new Name('null'))),
],
]
));
array_unshift($statements, ...$this->denormalizeMethodStatements($classGuess, $context));

$unset = \count($classGuess->getExtensionsType()) > 0;

Expand Down Expand Up @@ -159,4 +149,21 @@ protected function createDenormalizeMethod(string $modelFqdn, Context $context,
'stmts' => $statements,
]);
}

protected function denormalizeMethodStatements(ClassGuess $classGuess, Context $context): array
{
return [
new Stmt\If_(
new Expr\BooleanNot(new Expr\FuncCall(new Name('is_object'), [new Arg(new Expr\Variable('data'))])),
[
'stmts' => [
$context->isStrict() ?
new Stmt\Throw_(new Expr\New_(new Name('InvalidArgumentException')))
:
new Stmt\Return_(new Expr\ConstFetch(new Name('null'))),
],
]
),
];
}
}
11 changes: 8 additions & 3 deletions src/JsonSchema/Generator/Normalizer/NormalizerGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ protected function createNormalizeMethod($modelFqdn, Context $context, ClassGues
{
$context->refreshScope();
$dataVariable = new Expr\Variable('data');
$statements = [
new Stmt\Expression(new Expr\Assign($dataVariable, new Expr\New_(new Name('\\stdClass')))),
];
$statements = $this->normalizeMethodStatements($dataVariable, $classGuess, $context);

/** @var Property $property */
foreach ($classGuess->getProperties() as $property) {
Expand Down Expand Up @@ -140,4 +138,11 @@ protected function createNormalizeMethod($modelFqdn, Context $context, ClassGues
'stmts' => $statements,
]);
}

protected function normalizeMethodStatements(Expr\Variable $dataVariable, ClassGuess $classGuess, Context $context): array
{
return [
new Stmt\Expression(new Expr\Assign($dataVariable, new Expr\New_(new Name('\\stdClass')))),
];
}
}
2 changes: 1 addition & 1 deletion src/JsonSchema/Guesser/Guess/ClassGuess.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class ClassGuess
/**
* @var Property[]
*/
private $properties;
private $properties = [];

private $reference;

Expand Down
9 changes: 7 additions & 2 deletions src/JsonSchema/Guesser/JsonSchema/AllOfGuesser.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AllOfGuesser implements GuesserInterface, TypeGuesserInterface, ChainGuess
use ChainGuesserAwareTrait;
use GuesserResolverTrait;

private $naming;
protected $naming;

public function __construct(SerializerInterface $serializer, Naming $naming)
{
Expand Down Expand Up @@ -69,7 +69,7 @@ public function guessClass($object, $name, $reference, Registry $registry)
}
}

$registry->getSchema($reference)->addClass($reference, new ClassGuess($object, $reference, $this->naming->getClassName($name), $extensions));
$registry->getSchema($reference)->addClass($reference, $this->createClassGuess($object, $reference, $name, $extensions));
}

foreach ($object->getAllOf() as $allOfIndex => $allOf) {
Expand Down Expand Up @@ -168,4 +168,9 @@ protected function getSchemaClass()
{
return JsonSchema::class;
}

protected function createClassGuess($object, $reference, $name, $extensions): ClassGuess
{
return new ClassGuess($object, $reference, $this->naming->getClassName($name), $extensions);
}
}
7 changes: 6 additions & 1 deletion src/JsonSchema/Guesser/JsonSchema/ObjectGuesser.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public function guessClass($object, $name, $reference, Registry $registry)
}
}

$registry->getSchema($reference)->addClass($reference, new ClassGuess($object, $reference, $this->naming->getClassName($name), $extensions));
$registry->getSchema($reference)->addClass($reference, $this->createClassGuess($object, $reference, $name, $extensions));
}

foreach ($object->getProperties() as $key => $property) {
Expand Down Expand Up @@ -150,4 +150,9 @@ protected function getSchemaClass()
{
return JsonSchema::class;
}

protected function createClassGuess($object, $reference, $name, $extensions): ClassGuess
{
return new ClassGuess($object, $reference, $this->naming->getClassName($name), $extensions);
}
}
44 changes: 44 additions & 0 deletions src/OpenApi/Generator/Model/ClassGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Jane\OpenApi\Generator\Model;

use Jane\JsonSchema\Generator\Model\ClassGenerator as BaseClassGenerator;
use PhpParser\Node;
use PhpParser\Node\Name;
use PhpParser\Node\Stmt;

trait ClassGenerator
{
use BaseClassGenerator {
createModel as baseCreateModel;
}

/**
* Return a model class.
*
* @param string $name
* @param Node[] $properties
* @param Node[] $methods
* @param bool $hasExtensions
* @param string $extends
*
* @return Stmt\Class_
*/
protected function createModel(string $name, $properties, $methods, bool $hasExtensions = false, $extends = null): Stmt\Class_
{
$classExtends = null;
if (null !== $extends) {
$classExtends = new Name($extends);
} elseif ($hasExtensions) {
$classExtends = new Name('\ArrayObject');
}

return new Stmt\Class_(
new Name($this->getNaming()->getClassName($name)),
[
'stmts' => array_merge($properties, $methods),
'extends' => $classExtends,
]
);
}
}
44 changes: 44 additions & 0 deletions src/OpenApi/Generator/ModelGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

namespace Jane\OpenApi\Generator;

use Jane\JsonSchema\Generator\ModelGenerator as BaseModelGenerator;
use Jane\JsonSchema\Guesser\Guess\ClassGuess as BaseClassGuess;
use Jane\JsonSchema\Guesser\Guess\Property;
use Jane\OpenApi\Generator\Model\ClassGenerator;
use Jane\OpenApi\Guesser\Guess\ClassGuess;
use Jane\OpenApi\Guesser\Guess\MultipleClass;
use PhpParser\Node\Stmt;

class ModelGenerator extends BaseModelGenerator
{
use ClassGenerator;

protected function doCreateClassMethods(BaseClassGuess $classGuess, Property $property, string $namespace, bool $required)
{
$methods = [];
$methods[] = $this->createGetter($property, $namespace, $required);
$methods[] = $this->createSetter($property, $namespace, $required, $classGuess instanceof MultipleClass ? false : true);

return $methods;
}

protected function doCreateModel(BaseClassGuess $class, $properties, $methods): Stmt\Class_
{
$extends = null;
if ($class instanceof ClassGuess &&
$class->getMultipleClass() instanceof MultipleClass) {
$extends = $this->getNaming()->getClassName($class->getMultipleClass()->getName());
}

$classModel = $this->createModel(
$class->getName(),
$properties,
$methods,
\count($class->getExtensionsType()) > 0,
$extends
);

return $classModel;
}
}