From 7469bdb3e12aa963a110885ecd7a889a82f604ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 6 Sep 2017 14:14:58 +0200 Subject: [PATCH] Add a readable and a writable config option --- CHANGELOG.md | 1 + src/TypesGenerator.php | 44 ++++++++++++---------- src/TypesGeneratorConfiguration.php | 6 ++- templates/class.php.twig | 4 ++ tests/Command/DumpConfigurationTest.php | 8 +++- tests/Command/GenerateTypesCommandTest.php | 33 ++++++++++++---- tests/TypesGeneratorTest.php | 27 +++++++++++-- tests/config/readable-writable.yaml | 9 +++++ 8 files changed, 99 insertions(+), 33 deletions(-) create mode 100644 tests/config/readable-writable.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 60351e11..b128f85d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Generated classes include scalar typehints and return type * Nullable typehints are generated instead of a default `null` value +* Add new `readable` and `writable` options to fields to skip getter or mutator generation. * A fluent interface isn't generated anymore by default unless you set the `fluentMutatorMethods` config flag to `true` * Useless PHPDoc (`@param` and `@return` annotations when a typehint exist and mutator description) isn't generated anymore * `DateTimeInterface` is used instead of `DateTime` when possible diff --git a/src/TypesGenerator.php b/src/TypesGenerator.php index f0c29711..a1a951bb 100644 --- a/src/TypesGenerator.php +++ b/src/TypesGenerator.php @@ -295,24 +295,28 @@ public function generate(array $config): void // Generate ID if ($config['generateId']) { foreach ($classes as &$class) { - if (!$class['hasChild'] && !$class['isEnum'] && !$class['embeddable']) { - $class['fields'] = [ - 'id' => [ - 'name' => 'id', - 'resource' => null, - 'range' => 'Integer', - 'cardinality' => CardinalitiesExtractor::CARDINALITY_1_1, - 'ormColumn' => null, - 'isArray' => false, - 'isNullable' => false, - 'isUnique' => false, - 'isCustom' => true, - 'isEnum' => false, - 'isId' => true, - 'typeHint' => 'int', - ], - ] + $class['fields']; + if ($class['hasChild'] || $class['isEnum'] || $class['embeddable']) { + continue; } + + $class['fields'] = [ + 'id' => [ + 'name' => 'id', + 'resource' => null, + 'range' => 'Integer', + 'cardinality' => CardinalitiesExtractor::CARDINALITY_1_1, + 'ormColumn' => null, + 'isArray' => false, + 'isReadable' => true, + 'isWritable' => false, + 'isNullable' => false, + 'isUnique' => false, + 'isCustom' => true, + 'isEnum' => false, + 'isId' => true, + 'typeHint' => 'int', + ], + ] + $class['fields']; } } @@ -593,8 +597,6 @@ private function generateField(array $config, array $class, \EasyRdf_Resource $t $cardinality = $property ? $this->cardinalities[$propertyName] : CardinalitiesExtractor::CARDINALITY_1_1; } - $ormColumn = $propertyConfig['ormColumn'] ?? null; - $isArray = in_array($cardinality, [ CardinalitiesExtractor::CARDINALITY_0_N, CardinalitiesExtractor::CARDINALITY_1_N, @@ -622,8 +624,10 @@ private function generateField(array $config, array $class, \EasyRdf_Resource $t 'resource' => $property, 'range' => $ranges[0], 'cardinality' => $cardinality, - 'ormColumn' => $ormColumn, + 'ormColumn' => $propertyConfig['ormColumn'] ?? null, 'isArray' => $isArray, + 'isReadable' => $propertyConfig['readable'] ?? true, + 'isWritable' => $propertyConfig['writable'] ?? true, 'isNullable' => $isNullable, 'isUnique' => isset($propertyConfig['unique']) && $propertyConfig['unique'], 'isCustom' => empty($property), diff --git a/src/TypesGeneratorConfiguration.php b/src/TypesGeneratorConfiguration.php index 0b8a056c..660239c2 100644 --- a/src/TypesGeneratorConfiguration.php +++ b/src/TypesGeneratorConfiguration.php @@ -162,8 +162,10 @@ function ($rdfa) { ->info('Symfony Serialization Groups') ->prototype('scalar')->end() ->end() - ->scalarNode('nullable')->defaultTrue()->info('The property nullable')->end() - ->scalarNode('unique')->defaultFalse()->info('The property unique')->end() + ->booleanNode('readable')->defaultTrue()->info('Is the property readable?')->end() + ->booleanNode('writable')->defaultTrue()->info('Is the property writable?')->end() + ->booleanNode('nullable')->defaultTrue()->info('Is the property nullable?')->end() + ->booleanNode('unique')->defaultFalse()->info('The property unique')->end() ->booleanNode('embedded')->defaultFalse()->info('Is the property embedded?')->end() ->booleanNode('columnPrefix')->defaultFalse()->info('The property columnPrefix')->end() ->end() diff --git a/templates/class.php.twig b/templates/class.php.twig index dc51b22b..5fbc76bd 100644 --- a/templates/class.php.twig +++ b/templates/class.php.twig @@ -61,6 +61,7 @@ use {{ use }}; {% if config.accessorMethods %} {% for field in class.fields %} +{% if field.isWritable %} {% if field.isArray %} /** {% for annotation in field.adderAnnotations %} @@ -112,7 +113,9 @@ use {{ use }}; {% endif %} } {% endif %} +{% endif %} +{% if field.isReadable %} /** {% for annotation in field.getterAnnotations %} * {{ annotation }} @@ -123,6 +126,7 @@ use {{ use }}; return $this->{{ field.name }}; } +{% endif %} {% endfor %} {% endif %} } diff --git a/tests/Command/DumpConfigurationTest.php b/tests/Command/DumpConfigurationTest.php index 41b208ce..aee1438c 100644 --- a/tests/Command/DumpConfigurationTest.php +++ b/tests/Command/DumpConfigurationTest.php @@ -157,7 +157,13 @@ interface: null # Symfony Serialization Groups groups: [] - # The property nullable + # Is the property readable? + readable: true + + # Is the property writable? + writable: true + + # Is the property nullable? nullable: true # The property unique diff --git a/tests/Command/GenerateTypesCommandTest.php b/tests/Command/GenerateTypesCommandTest.php index 94a8bba8..27eed9cc 100644 --- a/tests/Command/GenerateTypesCommandTest.php +++ b/tests/Command/GenerateTypesCommandTest.php @@ -66,7 +66,6 @@ public function testDoctrineCollection() $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); @@ -86,8 +85,8 @@ public function testFluentMutators() $this->fs->mkdir($outputDir); $commandTester = new CommandTester(new GenerateTypesCommand()); $this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config])); - $person = 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 { @@ -126,10 +125,30 @@ public function testDoNotGenerateAccessorMethods() $commandTester = new CommandTester(new GenerateTypesCommand()); $this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config])); - $organization = file_get_contents($outputDir.'/AppBundle/Entity/Person.php'); - $this->assertNotContains('function get', $organization); - $this->assertNotContains('function set', $organization); - $this->assertNotContains('function add', $organization); - $this->assertNotContains('function remove', $organization); + $person = file_get_contents($outputDir.'/AppBundle/Entity/Person.php'); + $this->assertNotContains('function get', $person); + $this->assertNotContains('function set', $person); + $this->assertNotContains('function add', $person); + $this->assertNotContains('function remove', $person); + } + + public function testReadableWritable() + { + $outputDir = __DIR__.'/../../build/readable-writable'; + $config = __DIR__.'/../config/readable-writable.yaml'; + + $this->fs->mkdir($outputDir); + + $commandTester = new CommandTester(new GenerateTypesCommand()); + $this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config])); + + $person = file_get_contents($outputDir.'/AppBundle/Entity/Person.php'); + $this->assertContains('function getId(', $person); + $this->assertNotContains('function setId(', $person); + $this->assertContains('function getName(', $person); + $this->assertNotContains('function setName(', $person); + $this->assertContains('function getFriends(', $person); + $this->assertNotContains('function addFriends(', $person); + $this->assertNotContains('function removeFriends(', $person); } } diff --git a/tests/TypesGeneratorTest.php b/tests/TypesGeneratorTest.php index 242a3de1..9a60f493 100644 --- a/tests/TypesGeneratorTest.php +++ b/tests/TypesGeneratorTest.php @@ -14,6 +14,7 @@ namespace ApiPlatform\SchemaGenerator\Tests; use ApiPlatform\SchemaGenerator\CardinalitiesExtractor; +use ApiPlatform\SchemaGenerator\GoodRelationsBridge; use ApiPlatform\SchemaGenerator\TypesGenerator; use ApiPlatform\SchemaGenerator\TypesGeneratorConfiguration; use PHPUnit\Framework\TestCase; @@ -27,19 +28,19 @@ class TypesGeneratorTest extends TestCase { public function testGenerate(): void { - $twigProphecy = $this->prophesize('Twig_Environment'); + $twigProphecy = $this->prophesize(\Twig_Environment::class); foreach ($this->getClasses() as $class) { $twigProphecy->render('class.php.twig', Argument::that($this->getContextMatcher($class)))->willReturn()->shouldBeCalled(); } $twigProphecy->render('class.php.twig', Argument::type('array'))->willReturn(); $twig = $twigProphecy->reveal(); - $cardinalitiesExtractorProphecy = $this->prophesize('ApiPlatform\SchemaGenerator\CardinalitiesExtractor'); + $cardinalitiesExtractorProphecy = $this->prophesize(CardinalitiesExtractor::class); $cardinalities = $this->getCardinalities(); $cardinalitiesExtractorProphecy->extract()->willReturn($cardinalities)->shouldBeCalled(); $cardinalitiesExtractor = $cardinalitiesExtractorProphecy->reveal(); - $goodRelationsBridgeProphecy = $this->prophesize('ApiPlatform\SchemaGenerator\GoodRelationsBridge'); + $goodRelationsBridgeProphecy = $this->prophesize(GoodRelationsBridge::class); $goodRelationsBridge = $goodRelationsBridgeProphecy->reveal(); $typesGenerator = new TypesGenerator($twig, new NullLogger(), $this->getGraphs(), $cardinalitiesExtractor, $goodRelationsBridge); @@ -190,6 +191,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'articleBody', @@ -201,6 +204,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'articleSection', @@ -223,6 +228,8 @@ private function getClasses(): array 'isCustom' => true, 'isEnum' => false, 'isId' => true, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => false, 'isUnique' => false, 'name' => 'id', @@ -245,6 +252,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'author', @@ -256,6 +265,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'datePublished', @@ -267,6 +278,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'headline', @@ -278,6 +291,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'isFamilyFriendly', @@ -300,6 +315,8 @@ private function getClasses(): array 'isCustom' => true, 'isEnum' => false, 'isId' => true, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => false, 'isUnique' => false, 'name' => 'id', @@ -322,6 +339,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'sharedContent', @@ -344,6 +363,8 @@ private function getClasses(): array 'isCustom' => false, 'isEnum' => false, 'isId' => false, + 'isReadable' => true, + 'isWritable' => true, 'isNullable' => true, 'isUnique' => false, 'name' => 'name', diff --git a/tests/config/readable-writable.yaml b/tests/config/readable-writable.yaml new file mode 100644 index 00000000..e4482756 --- /dev/null +++ b/tests/config/readable-writable.yaml @@ -0,0 +1,9 @@ +rdfa: [{ uri: tests/data/schema.rdfa, format: rdfa }] +relations: [tests/data/v1.owl] + +types: + Person: + properties: + name: { writable: false } + familyName: { readable: false } + friends: { range: "Person", cardinality: (0..*), writable: false }