diff --git a/composer.json b/composer.json index 49fbdd92..3f90baee 100644 --- a/composer.json +++ b/composer.json @@ -24,21 +24,19 @@ "friendsofphp/php-cs-fixer": "^2.4", "league/html-to-markdown": "^4.0", "psr/log": "^1.0", + "symfony/config": "^3.3 || ^4.0", "symfony/console": "^2.7 || ^3.0 || ^4.0", "symfony/yaml": "^2.7 || ^3.0 || ^4.0", - "symfony/config": "^3.3 || ^4.0", "twig/twig": "^1.12 || ^2.0" }, "require-dev": { + "api-platform/core": "^2.0", "doctrine/orm": "^2.2", + "myclabs/php-enum": "^1.0", + "symfony/doctrine-bridge": "^2.7 || ^3.0 || ^4.0", "symfony/filesystem": "^2.7 || ^3.0 || ^4.0", + "symfony/serializer": "^2.7 || ^3.0 || ^4.0", "symfony/validator": "^2.7 || ^3.0 || ^4.0" }, - "suggest": { - "doctrine/collections": "For Doctrine collections", - "doctrine/orm": "For Doctrine annotations", - "myclabs/php-enum": "For enumerations", - "symfony/validator": "For constraint annotations" - }, "bin": ["bin/schema"] } diff --git a/src/AnnotationGenerator/AbstractAnnotationGenerator.php b/src/AnnotationGenerator/AbstractAnnotationGenerator.php index 78277a93..d133201e 100644 --- a/src/AnnotationGenerator/AbstractAnnotationGenerator.php +++ b/src/AnnotationGenerator/AbstractAnnotationGenerator.php @@ -184,7 +184,7 @@ protected function toPhpType(array $field, bool $adderOrRemover = false): string if ($field['isArray'] && !$adderOrRemover) { if ($this->config['doctrine']['useCollection']) { - return sprintf('ArrayCollection<%s>', $range); + return sprintf('Collection<%s>', $range); } return sprintf('%s[]', $range); diff --git a/src/AnnotationGenerator/ApiPlatformCoreAnnotationGenerator.php b/src/AnnotationGenerator/ApiPlatformCoreAnnotationGenerator.php index 2a55dc10..16532dc8 100644 --- a/src/AnnotationGenerator/ApiPlatformCoreAnnotationGenerator.php +++ b/src/AnnotationGenerator/ApiPlatformCoreAnnotationGenerator.php @@ -13,6 +13,8 @@ namespace ApiPlatform\SchemaGenerator\AnnotationGenerator; +use ApiPlatform\Core\Annotation\ApiProperty; +use ApiPlatform\Core\Annotation\ApiResource; use ApiPlatform\SchemaGenerator\TypesGenerator; /** @@ -52,6 +54,6 @@ public function generateUses(string $className): array $subClassOf = $resource->get('rdfs:subClassOf'); $typeIsEnum = $subClassOf && $subClassOf->getUri() === TypesGenerator::SCHEMA_ORG_ENUMERATION; - return $typeIsEnum ? [] : ['ApiPlatform\Core\Annotation\ApiResource', 'ApiPlatform\Core\Annotation\ApiProperty']; + return $typeIsEnum ? [] : [ApiResource::class, ApiProperty::class]; } } diff --git a/src/AnnotationGenerator/ConstraintAnnotationGenerator.php b/src/AnnotationGenerator/ConstraintAnnotationGenerator.php index d229ec8f..37ef449b 100644 --- a/src/AnnotationGenerator/ConstraintAnnotationGenerator.php +++ b/src/AnnotationGenerator/ConstraintAnnotationGenerator.php @@ -13,6 +13,8 @@ namespace ApiPlatform\SchemaGenerator\AnnotationGenerator; +use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; + /** * Constraint annotation generator. * @@ -90,7 +92,7 @@ public function generateUses(string $className): array $uses = []; $uses[] = 'Symfony\Component\Validator\Constraints as Assert'; - $uses[] = 'Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity'; + $uses[] = UniqueEntity::class; foreach ($this->classes[$className]['fields'] as $field) { if ($field['isEnum']) { diff --git a/src/AnnotationGenerator/SerializerGroupsAnnotationGenerator.php b/src/AnnotationGenerator/SerializerGroupsAnnotationGenerator.php index f6f627c7..5d2e5f15 100644 --- a/src/AnnotationGenerator/SerializerGroupsAnnotationGenerator.php +++ b/src/AnnotationGenerator/SerializerGroupsAnnotationGenerator.php @@ -13,6 +13,8 @@ namespace ApiPlatform\SchemaGenerator\AnnotationGenerator; +use Symfony\Component\Serializer\Annotation\Groups; + /** * Symfony Serializer Groups annotation generator. * @@ -43,6 +45,6 @@ public function generateFieldAnnotations(string $className, string $fieldName): */ public function generateUses(string $className): array { - return ['Symfony\Component\Serializer\Annotation\Groups']; + return [Groups::class]; } } diff --git a/src/TypesGenerator.php b/src/TypesGenerator.php index 6f5ff3b8..f0c29711 100644 --- a/src/TypesGenerator.php +++ b/src/TypesGenerator.php @@ -14,6 +14,9 @@ namespace ApiPlatform\SchemaGenerator; use ApiPlatform\SchemaGenerator\AnnotationGenerator\AnnotationGeneratorInterface; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; +use MyCLabs\Enum\Enum; use PhpCsFixer\Cache\NullCacheManager; use PhpCsFixer\Differ\NullDiffer; use PhpCsFixer\Error\ErrorsManager; @@ -37,27 +40,6 @@ class TypesGenerator */ public const SCHEMA_ORG_ENUMERATION = 'http://schema.org/Enumeration'; - /** - * @var string - * - * @see https://github.com/myclabs/php-enum Used enum implementation - */ - private const ENUM_USE = 'MyCLabs\Enum\Enum'; - - /** - * @var string - * - * @see https://github.com/doctrine/collections - */ - private const DOCTRINE_COLLECTION_USE = 'Doctrine\Common\Collections\ArrayCollection'; - - /** - * @var string - * - * @see https://github.com/myclabs/php-enum Used enum implementation - */ - private const ENUM_EXTENDS = 'Enum'; - /** * @var string */ @@ -177,8 +159,8 @@ public function generate(array $config): void $class['isEnum'] = $this->isEnum($type); if ($class['isEnum']) { $class['namespace'] = $typeConfig['namespace'] ?? $config['namespaces']['enum']; - $class['parent'] = self::ENUM_EXTENDS; - $class['uses'][] = self::ENUM_USE; + $class['parent'] = 'Enum'; + $class['uses'][] = Enum::class; // Constants foreach ($this->graphs as $graph) { @@ -263,9 +245,9 @@ public function generate(array $config): void foreach ($class['fields'] as &$field) { $field['isEnum'] = isset($classes[$field['range']]) && $classes[$field['range']]['isEnum']; - $field['typeHint'] = $this->fieldToTypeHint($field, $classes) ?? false; + $field['typeHint'] = $this->fieldToTypeHint($config, $field, $classes) ?? false; - if ('array' === $field['typeHint']) { + if ($field['isArray']) { $field['adderRemoverTypeHint'] = $this->fieldToAdderRemoverTypeHint($field, $classes) ?? false; } } @@ -513,10 +495,10 @@ private function isDatatype(string $type): bool return in_array($type, ['Boolean', 'DataType', 'Date', 'DateTime', 'Float', 'Integer', 'Number', 'Text', 'Time', 'URL'], true); } - private function fieldToTypeHint(array $field, array $classes): ?string + private function fieldToTypeHint(array $config, array $field, array $classes): ?string { if ($field['isArray']) { - return 'array'; + return $config['doctrine']['useCollection'] ? 'Collection' : 'array'; } return $this->fieldToAdderRemoverTypeHint($field, $classes); @@ -649,11 +631,13 @@ private function generateField(array $config, array $class, \EasyRdf_Resource $t 'columnPrefix' => $columnPrefix, 'isId' => false, ]; + if ($isArray) { $class['hasConstructor'] = true; - if (isset($config['doctrine']['useCollection']) && $config['doctrine']['useCollection'] && !in_array(self::DOCTRINE_COLLECTION_USE, $class['uses'], true)) { - $class['uses'][] = self::DOCTRINE_COLLECTION_USE; + if ($config['doctrine']['useCollection'] && !in_array(ArrayCollection::class, $class['uses'], true)) { + $class['uses'][] = ArrayCollection::class; + $class['uses'][] = Collection::class; } } } diff --git a/templates/class.php.twig b/templates/class.php.twig index ff4705a5..dc51b22b 100644 --- a/templates/class.php.twig +++ b/templates/class.php.twig @@ -118,7 +118,7 @@ use {{ use }}; * {{ annotation }} {% endfor %} */ - public function get{{ field.name|ucfirst }}(){% if field.typeHint %}: {% if field.isNullable %}?{% endif %}{{ field.typeHint }}{% endif %} + public function get{{ field.name|ucfirst }}(){% if field.typeHint %}: {% if field.isNullable and not field.isArray %}?{% endif %}{{ field.typeHint }}{% endif %} { return $this->{{ field.name }}; } diff --git a/tests/Command/GenerateTypesCommandTest.php b/tests/Command/GenerateTypesCommandTest.php index f802b41f..94a8bba8 100644 --- a/tests/Command/GenerateTypesCommandTest.php +++ b/tests/Command/GenerateTypesCommandTest.php @@ -47,7 +47,6 @@ public function testCommand($output, $config) public function getArguments() { return [ - [__DIR__.'/../../build/address-book/', __DIR__.'/../config/address-book.yaml'], [__DIR__.'/../../build/blog/', __DIR__.'/../config/blog.yaml'], [__DIR__.'/../../build/ecommerce/', __DIR__.'/../config/ecommerce.yaml'], [__DIR__.'/../../build/vgo/', __DIR__.'/../config/vgo.yaml'], @@ -56,6 +55,30 @@ public function getArguments() ]; } + public function testDoctrineCollection() + { + $outputDir = __DIR__.'/../../build/address-book'; + $config = __DIR__.'/../config/address-book.yaml'; + + $this->fs->mkdir($outputDir); + + $commandTester = new CommandTester(new GenerateTypesCommand()); + $this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config])); + + $person = file_get_contents($outputDir.'/AddressBook/Entity/Person.php'); + + $this->assertContains('use Doctrine\Common\Collections\ArrayCollection;', $person); + $this->assertContains('use Doctrine\Common\Collections\Collection;', $person); + + $this->assertContains(<<<'PHP' + public function getFriends(): Collection + { + return $this->friends; + } +PHP + , $person); + } + public function testFluentMutators() { $outputDir = __DIR__.'/../../build/fluent-mutators'; @@ -63,7 +86,8 @@ public function testFluentMutators() $this->fs->mkdir($outputDir); $commandTester = new CommandTester(new GenerateTypesCommand()); $this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config])); - $organization = file_get_contents($outputDir.'/AppBundle/Entity/Person.php'); + $person = file_get_contents($outputDir.'/AppBundle/Entity/Person.php'); + $this->assertContains(<<<'PHP' public function setUrl(?string $url): self { @@ -72,7 +96,8 @@ public function setUrl(?string $url): self return $this; } PHP - , $organization); + , $person); + $this->assertContains(<<<'PHP' public function addFriends(Person $friends): self { @@ -88,7 +113,7 @@ public function removeFriends(Person $friends): self return $this; } PHP - , $organization); + , $person); } public function testDoNotGenerateAccessorMethods()