Skip to content

Commit 10e6f58

Browse files
authored
Merge pull request #95 from dunglas/fix_collection
Fix bad typehint when using Doctrine collections
2 parents 178bea6 + 36401a3 commit 10e6f58

8 files changed

+58
-45
lines changed

composer.json

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,21 +24,19 @@
2424
"friendsofphp/php-cs-fixer": "^2.4",
2525
"league/html-to-markdown": "^4.0",
2626
"psr/log": "^1.0",
27+
"symfony/config": "^3.3 || ^4.0",
2728
"symfony/console": "^2.7 || ^3.0 || ^4.0",
2829
"symfony/yaml": "^2.7 || ^3.0 || ^4.0",
29-
"symfony/config": "^3.3 || ^4.0",
3030
"twig/twig": "^1.12 || ^2.0"
3131
},
3232
"require-dev": {
33+
"api-platform/core": "^2.0",
3334
"doctrine/orm": "^2.2",
35+
"myclabs/php-enum": "^1.0",
36+
"symfony/doctrine-bridge": "^2.7 || ^3.0 || ^4.0",
3437
"symfony/filesystem": "^2.7 || ^3.0 || ^4.0",
38+
"symfony/serializer": "^2.7 || ^3.0 || ^4.0",
3539
"symfony/validator": "^2.7 || ^3.0 || ^4.0"
3640
},
37-
"suggest": {
38-
"doctrine/collections": "For Doctrine collections",
39-
"doctrine/orm": "For Doctrine annotations",
40-
"myclabs/php-enum": "For enumerations",
41-
"symfony/validator": "For constraint annotations"
42-
},
4341
"bin": ["bin/schema"]
4442
}

src/AnnotationGenerator/AbstractAnnotationGenerator.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ protected function toPhpType(array $field, bool $adderOrRemover = false): string
184184

185185
if ($field['isArray'] && !$adderOrRemover) {
186186
if ($this->config['doctrine']['useCollection']) {
187-
return sprintf('ArrayCollection<%s>', $range);
187+
return sprintf('Collection<%s>', $range);
188188
}
189189

190190
return sprintf('%s[]', $range);

src/AnnotationGenerator/ApiPlatformCoreAnnotationGenerator.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace ApiPlatform\SchemaGenerator\AnnotationGenerator;
1515

16+
use ApiPlatform\Core\Annotation\ApiProperty;
17+
use ApiPlatform\Core\Annotation\ApiResource;
1618
use ApiPlatform\SchemaGenerator\TypesGenerator;
1719

1820
/**
@@ -52,6 +54,6 @@ public function generateUses(string $className): array
5254
$subClassOf = $resource->get('rdfs:subClassOf');
5355
$typeIsEnum = $subClassOf && $subClassOf->getUri() === TypesGenerator::SCHEMA_ORG_ENUMERATION;
5456

55-
return $typeIsEnum ? [] : ['ApiPlatform\Core\Annotation\ApiResource', 'ApiPlatform\Core\Annotation\ApiProperty'];
57+
return $typeIsEnum ? [] : [ApiResource::class, ApiProperty::class];
5658
}
5759
}

src/AnnotationGenerator/ConstraintAnnotationGenerator.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace ApiPlatform\SchemaGenerator\AnnotationGenerator;
1515

16+
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
17+
1618
/**
1719
* Constraint annotation generator.
1820
*
@@ -90,7 +92,7 @@ public function generateUses(string $className): array
9092

9193
$uses = [];
9294
$uses[] = 'Symfony\Component\Validator\Constraints as Assert';
93-
$uses[] = 'Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity';
95+
$uses[] = UniqueEntity::class;
9496

9597
foreach ($this->classes[$className]['fields'] as $field) {
9698
if ($field['isEnum']) {

src/AnnotationGenerator/SerializerGroupsAnnotationGenerator.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace ApiPlatform\SchemaGenerator\AnnotationGenerator;
1515

16+
use Symfony\Component\Serializer\Annotation\Groups;
17+
1618
/**
1719
* Symfony Serializer Groups annotation generator.
1820
*
@@ -43,6 +45,6 @@ public function generateFieldAnnotations(string $className, string $fieldName):
4345
*/
4446
public function generateUses(string $className): array
4547
{
46-
return ['Symfony\Component\Serializer\Annotation\Groups'];
48+
return [Groups::class];
4749
}
4850
}

src/TypesGenerator.php

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
namespace ApiPlatform\SchemaGenerator;
1515

1616
use ApiPlatform\SchemaGenerator\AnnotationGenerator\AnnotationGeneratorInterface;
17+
use Doctrine\Common\Collections\ArrayCollection;
18+
use Doctrine\Common\Collections\Collection;
19+
use MyCLabs\Enum\Enum;
1720
use PhpCsFixer\Cache\NullCacheManager;
1821
use PhpCsFixer\Differ\NullDiffer;
1922
use PhpCsFixer\Error\ErrorsManager;
@@ -37,27 +40,6 @@ class TypesGenerator
3740
*/
3841
public const SCHEMA_ORG_ENUMERATION = 'http://schema.org/Enumeration';
3942

40-
/**
41-
* @var string
42-
*
43-
* @see https://github.com/myclabs/php-enum Used enum implementation
44-
*/
45-
private const ENUM_USE = 'MyCLabs\Enum\Enum';
46-
47-
/**
48-
* @var string
49-
*
50-
* @see https://github.com/doctrine/collections
51-
*/
52-
private const DOCTRINE_COLLECTION_USE = 'Doctrine\Common\Collections\ArrayCollection';
53-
54-
/**
55-
* @var string
56-
*
57-
* @see https://github.com/myclabs/php-enum Used enum implementation
58-
*/
59-
private const ENUM_EXTENDS = 'Enum';
60-
6143
/**
6244
* @var string
6345
*/
@@ -177,8 +159,8 @@ public function generate(array $config): void
177159
$class['isEnum'] = $this->isEnum($type);
178160
if ($class['isEnum']) {
179161
$class['namespace'] = $typeConfig['namespace'] ?? $config['namespaces']['enum'];
180-
$class['parent'] = self::ENUM_EXTENDS;
181-
$class['uses'][] = self::ENUM_USE;
162+
$class['parent'] = 'Enum';
163+
$class['uses'][] = Enum::class;
182164

183165
// Constants
184166
foreach ($this->graphs as $graph) {
@@ -263,9 +245,9 @@ public function generate(array $config): void
263245

264246
foreach ($class['fields'] as &$field) {
265247
$field['isEnum'] = isset($classes[$field['range']]) && $classes[$field['range']]['isEnum'];
266-
$field['typeHint'] = $this->fieldToTypeHint($field, $classes) ?? false;
248+
$field['typeHint'] = $this->fieldToTypeHint($config, $field, $classes) ?? false;
267249

268-
if ('array' === $field['typeHint']) {
250+
if ($field['isArray']) {
269251
$field['adderRemoverTypeHint'] = $this->fieldToAdderRemoverTypeHint($field, $classes) ?? false;
270252
}
271253
}
@@ -513,10 +495,10 @@ private function isDatatype(string $type): bool
513495
return in_array($type, ['Boolean', 'DataType', 'Date', 'DateTime', 'Float', 'Integer', 'Number', 'Text', 'Time', 'URL'], true);
514496
}
515497

516-
private function fieldToTypeHint(array $field, array $classes): ?string
498+
private function fieldToTypeHint(array $config, array $field, array $classes): ?string
517499
{
518500
if ($field['isArray']) {
519-
return 'array';
501+
return $config['doctrine']['useCollection'] ? 'Collection' : 'array';
520502
}
521503

522504
return $this->fieldToAdderRemoverTypeHint($field, $classes);
@@ -649,11 +631,13 @@ private function generateField(array $config, array $class, \EasyRdf_Resource $t
649631
'columnPrefix' => $columnPrefix,
650632
'isId' => false,
651633
];
634+
652635
if ($isArray) {
653636
$class['hasConstructor'] = true;
654637

655-
if (isset($config['doctrine']['useCollection']) && $config['doctrine']['useCollection'] && !in_array(self::DOCTRINE_COLLECTION_USE, $class['uses'], true)) {
656-
$class['uses'][] = self::DOCTRINE_COLLECTION_USE;
638+
if ($config['doctrine']['useCollection'] && !in_array(ArrayCollection::class, $class['uses'], true)) {
639+
$class['uses'][] = ArrayCollection::class;
640+
$class['uses'][] = Collection::class;
657641
}
658642
}
659643
}

templates/class.php.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ use {{ use }};
118118
* {{ annotation }}
119119
{% endfor %}
120120
*/
121-
public function get{{ field.name|ucfirst }}(){% if field.typeHint %}: {% if field.isNullable %}?{% endif %}{{ field.typeHint }}{% endif %}
121+
public function get{{ field.name|ucfirst }}(){% if field.typeHint %}: {% if field.isNullable and not field.isArray %}?{% endif %}{{ field.typeHint }}{% endif %}
122122
{
123123
return $this->{{ field.name }};
124124
}

tests/Command/GenerateTypesCommandTest.php

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,6 @@ public function testCommand($output, $config)
4747
public function getArguments()
4848
{
4949
return [
50-
[__DIR__.'/../../build/address-book/', __DIR__.'/../config/address-book.yaml'],
5150
[__DIR__.'/../../build/blog/', __DIR__.'/../config/blog.yaml'],
5251
[__DIR__.'/../../build/ecommerce/', __DIR__.'/../config/ecommerce.yaml'],
5352
[__DIR__.'/../../build/vgo/', __DIR__.'/../config/vgo.yaml'],
@@ -56,14 +55,39 @@ public function getArguments()
5655
];
5756
}
5857

58+
public function testDoctrineCollection()
59+
{
60+
$outputDir = __DIR__.'/../../build/address-book';
61+
$config = __DIR__.'/../config/address-book.yaml';
62+
63+
$this->fs->mkdir($outputDir);
64+
65+
$commandTester = new CommandTester(new GenerateTypesCommand());
66+
$this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config]));
67+
68+
$person = file_get_contents($outputDir.'/AddressBook/Entity/Person.php');
69+
70+
$this->assertContains('use Doctrine\Common\Collections\ArrayCollection;', $person);
71+
$this->assertContains('use Doctrine\Common\Collections\Collection;', $person);
72+
73+
$this->assertContains(<<<'PHP'
74+
public function getFriends(): Collection
75+
{
76+
return $this->friends;
77+
}
78+
PHP
79+
, $person);
80+
}
81+
5982
public function testFluentMutators()
6083
{
6184
$outputDir = __DIR__.'/../../build/fluent-mutators';
6285
$config = __DIR__.'/../config/fluent-mutators.yaml';
6386
$this->fs->mkdir($outputDir);
6487
$commandTester = new CommandTester(new GenerateTypesCommand());
6588
$this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config]));
66-
$organization = file_get_contents($outputDir.'/AppBundle/Entity/Person.php');
89+
$person = file_get_contents($outputDir.'/AppBundle/Entity/Person.php');
90+
6791
$this->assertContains(<<<'PHP'
6892
public function setUrl(?string $url): self
6993
{
@@ -72,7 +96,8 @@ public function setUrl(?string $url): self
7296
return $this;
7397
}
7498
PHP
75-
, $organization);
99+
, $person);
100+
76101
$this->assertContains(<<<'PHP'
77102
public function addFriends(Person $friends): self
78103
{
@@ -88,7 +113,7 @@ public function removeFriends(Person $friends): self
88113
return $this;
89114
}
90115
PHP
91-
, $organization);
116+
, $person);
92117
}
93118

94119
public function testDoNotGenerateAccessorMethods()

0 commit comments

Comments
 (0)