Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ parameters:
author: false|string,
fieldVisibility: 'private'|'protected'|'public'|null,
accessorMethods: boolean,
useSimpleArraySetter: boolean,
fluentMutatorMethods: boolean,
rangeMapping: array<string, string>,
allTypes: boolean,
Expand Down
3 changes: 2 additions & 1 deletion src/Model/Class_.php
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ public function toNetteFile(array $config, InflectorInterface $inflector, ?PhpFi
{
$useDoctrineCollections = $config['doctrine']['useCollection'];
$useAccessors = $config['accessorMethods'];
$useSimpleArraySetter = $config['useSimpleArraySetter'];
$useFluentMutators = $config['fluentMutatorMethods'];
$fileHeader = $config['header'] ?? null;
$fieldVisibility = $config['fieldVisibility'];
Expand Down Expand Up @@ -333,7 +334,7 @@ public function toNetteFile(array $config, InflectorInterface $inflector, ?PhpFi
foreach ($sortedProperties as $property) {
foreach ($property->generateNetteMethods(static function ($string) use ($inflector) {
return $inflector->singularize($string)[0];
}, $namespace, $useDoctrineCollections, $useFluentMutators) as $method) {
}, $namespace, $useDoctrineCollections, $useFluentMutators, $useSimpleArraySetter) as $method) {
$methods[] = $method;
}
}
Expand Down
15 changes: 11 additions & 4 deletions src/Model/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,11 @@ public function isArray(): bool
return $this->type instanceof ArrayType;
}

public function isSimpleArray(): bool
{
return 'array' === $this->typeHint;
}

public function addAnnotation(string $annotation): self
{
if ('' === $annotation || !\in_array($annotation, $this->annotations, true)) {
Expand Down Expand Up @@ -154,7 +159,7 @@ public function toNetteProperty(PhpNamespace $namespace, ?string $visibility = n
$property->setType($this->resolveName($namespace, $this->typeHint));
}

if (!$this->isArray() || $this->isTypeHintedAsCollection()) {
if (!$this->isArray() || $this->isSimpleArray() || $this->isTypeHintedAsCollection()) {
$property->setNullable($this->isNullable);
}

Expand Down Expand Up @@ -195,9 +200,10 @@ public function generateNetteMethods(
PhpNamespace $namespace,
bool $useDoctrineCollections = true,
bool $useFluentMutators = false,
bool $useSimpleArraySetter = false,
): array {
return array_merge(
$this->generateMutators($singularize, $namespace, $useDoctrineCollections, $useFluentMutators),
$this->generateMutators($singularize, $namespace, $useDoctrineCollections, $useFluentMutators, $useSimpleArraySetter),
$this->isReadable ? [$this->generateGetter($namespace)] : []
);
}
Expand All @@ -214,7 +220,7 @@ private function generateGetter(PhpNamespace $namespace): Method
}
if ($this->typeHint) {
$getter->setReturnType($this->resolveName($namespace, $this->typeHint));
if ($this->isNullable && !$this->isArray()) {
if ($this->isNullable && (!$this->isArray() || $this->isSimpleArray())) {
$getter->setReturnNullable();
}
}
Expand All @@ -231,13 +237,14 @@ private function generateMutators(
PhpNamespace $namespace,
bool $useDoctrineCollections = true,
bool $useFluentMutators = false,
bool $useSimpleArraySetter = false,
): array {
if (!$this->isWritable) {
return [];
}

$mutators = [];
if ($this->isArray()) {
if ($this->isArray() && (!$this->isSimpleArray() || !$useSimpleArraySetter)) {
$singularProperty = $singularize($this->name());

$adder = (new Method('add'.ucfirst($singularProperty)))->setVisibility(ClassType::VISIBILITY_PUBLIC);
Expand Down
1 change: 1 addition & 0 deletions src/SchemaGeneratorConfiguration.php
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ public function getConfigTreeBuilder(): TreeBuilder
->scalarNode('author')->defaultFalse()->info('The value of the phpDoc\'s @author annotation')->example('Kévin Dunglas <dunglas@gmail.com>')->end()
->enumNode('fieldVisibility')->values(['private', 'protected', 'public'])->defaultValue('private')->cannotBeEmpty()->info('Visibility of entities fields')->end()
->booleanNode('accessorMethods')->defaultTrue()->info('Set this flag to false to not generate getter, setter, adder and remover methods')->end()
->booleanNode('useSimpleArraySetter')->defaultFalse()->info('Set this flag to true to generate setter method for simple arrays instead of adder and remover methods')->end()
->booleanNode('fluentMutatorMethods')->defaultFalse()->info('Set this flag to true to generate fluent setter, adder and remover methods')->end()
->arrayNode('rangeMapping')
->useAttributeAsKey('name')
Expand Down
6 changes: 4 additions & 2 deletions tests/Command/DumpConfigurationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ interface: App\Model # Example: App\Model
# Set this flag to false to not generate getter, setter, adder and remover methods
accessorMethods: true

# Set this flag to true to generate setter method for simple arrays instead of adder and remover methods
useSimpleArraySetter: false

# Set this flag to true to generate fluent setter, adder and remover methods
fluentMutatorMethods: false
rangeMapping:
Expand Down Expand Up @@ -275,8 +278,7 @@ interface: null
generatorTemplates: []


YAML
,
YAML,
$commandTester->getDisplay()
);
}
Expand Down
3 changes: 1 addition & 2 deletions tests/Command/ExtractCardinalitiesCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1475,7 +1475,6 @@ public function testExtractCardinalities(): void
"https:\/\/schema.org\/mainEntityOfPage": "unknown"
}

JSON
, $commandTester->getDisplay());
JSON, $commandTester->getDisplay());
}
}
104 changes: 58 additions & 46 deletions tests/Command/GenerateCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,7 @@ public function getFriends(): Collection
{
return $this->friends;
}
PHP
, $person);
PHP, $person);
}

public function testCustomAttributes(): void
Expand Down Expand Up @@ -106,29 +105,24 @@ public function testCustomAttributes(): void
#[MyAttribute]
class Book
{
PHP
, $book);
PHP, $book);

// Attributes given as unordered map.
$this->assertStringContainsString(<<<'PHP'
#[ORM\OneToMany(targetEntity: 'App\Entity\Review', mappedBy: 'book', cascade: ['persist', 'remove'])]
PHP
, $book);
PHP, $book);
$this->assertStringContainsString(<<<'PHP'
#[ORM\OrderBy(name: 'ASC')]
PHP
, $book);
PHP, $book);
// Generated attribute could be merged with next one that is a configured one.
$this->assertStringContainsString(<<<'PHP'
#[ORM\InverseJoinColumn(nullable: false, unique: true, name: 'first_join_column')]
PHP
, $book);
PHP, $book);
// Configured attribute could not be merged with next one and it is treated
// as repeated.
$this->assertStringContainsString(<<<'PHP'
#[ORM\InverseJoinColumn(name: 'second_join_column')]
PHP
, $book);
PHP, $book);
}

public function testFluentMutators(): void
Expand All @@ -147,8 +141,7 @@ public function setUrl(?string $url): self

return $this;
}
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function addFriend(Person $friend): self
Expand All @@ -164,8 +157,7 @@ public function removeFriend(Person $friend): self

return $this;
}
PHP
, $person);
PHP, $person);
}

public function testDoNotGenerateAccessorMethods(): void
Expand Down Expand Up @@ -230,8 +222,7 @@ public function testPropertyDefault(): void

$this->assertStringContainsString(<<<'PHP'
private string $availability = 'https://schema.org/InStock';
PHP
, $book);
PHP, $book);
}

public function testReadableWritable(): void
Expand Down Expand Up @@ -274,16 +265,14 @@ public function testGeneratedId(): void
#[ORM\GeneratedValue(strategy: 'AUTO')]
#[ORM\Column(type: 'integer')]
private ?int $id = null;
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function getId(): ?int
{
return $this->id;
}
PHP
, $person);
PHP, $person);

$this->assertStringNotContainsString('setId(', $person);
}
Expand All @@ -304,24 +293,21 @@ public function testNonGeneratedId(): void
#[ORM\Id]
#[ORM\Column(type: 'string')]
private string $id;
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function getId(): string
{
return $this->id;
}
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function setId(string $id): void
{
$this->id = $id;
}
PHP
, $person);
PHP, $person);
}

public function testGeneratedUuid(): void
Expand All @@ -342,16 +328,14 @@ public function testGeneratedUuid(): void
#[ORM\Column(type: 'guid')]
#[Assert\Uuid]
private ?string $id = null;
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function getId(): ?string
{
return $this->id;
}
PHP
, $person);
PHP, $person);

$this->assertStringNotContainsString('setId(', $person);
}
Expand All @@ -373,25 +357,22 @@ public function testNonGeneratedUuid(): void
#[ORM\Column(type: 'guid')]
#[Assert\Uuid]
private string $id;
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function getId(): string
{
return $this->id;
}
PHP
, $person);
PHP, $person);

$this->assertStringContainsString(<<<'PHP'
public function setId(string $id): void
{
$this->id = $id;
}

PHP
, $person);
PHP, $person);
}

public function testDoNotGenerateId(): void
Expand Down Expand Up @@ -463,8 +444,7 @@ public function testGeneratedEnum(): void
$this->assertStringContainsString(<<<'PHP'
/** @var string The female gender. */
public const FEMALE = 'https://schema.org/Female';
PHP
, $gender);
PHP, $gender);

$this->assertStringNotContainsString('function setId(', $gender);
}
Expand All @@ -490,8 +470,7 @@ public function testSupersededProperties(): void
#[ORM\Column(type: 'text', nullable: true)]
#[ApiProperty(types: ['https://schema.org/award'])]
private ?string $award = null;
PHP
, $creativeWork);
PHP, $creativeWork);

$this->assertStringNotContainsString('protected', $creativeWork);
}
Expand All @@ -517,8 +496,7 @@ public function testActivityStreams(): void
#[ORM\Column(type: 'text', nullable: true, name: '`content`')]
#[ApiProperty(types: ['http://www.w3.org/ns/activitystreams#content'])]
private ?string $content = null;
PHP
, $object);
PHP, $object);

$page = file_get_contents("$outputDir/App/Entity/Page.php");

Expand All @@ -531,13 +509,47 @@ public function testActivityStreams(): void
#[ORM\Entity]
#[ApiResource(types: ['http://www.w3.org/ns/activitystreams#Page'], routePrefix: 'as')]
class Page extends Object_
PHP
, $page);
PHP, $page);

self::assertFalse($this->fs->exists("$outputDir/App/Entity/Delete.php"));
self::assertFalse($this->fs->exists("$outputDir/App/Entity/Travel.php"));
}

public function testGeneratedSimpleArray(): void
{
$outputDir = __DIR__.'/../../build/simple-array';
$config = __DIR__.'/../config/simple-array.yaml';

$this->fs->mkdir($outputDir);

$commandTester = new CommandTester(new GenerateCommand());
$this->assertEquals(0, $commandTester->execute(['output' => $outputDir, 'config' => $config]));
$source = file_get_contents("$outputDir/App/Entity/Project.php");

$this->assertStringContainsString(<<<'PHP'
/**
* @see _:shareWith
*/
#[ORM\Column(type: 'simple_array', nullable: true)]
#[Assert\Unique]
private ?array $shareWith = [];
PHP, $source);

$this->assertStringContainsString(<<<'PHP'
public function setShareWith(?array $shareWith): void
{
$this->shareWith = $shareWith;
}

public function getShareWith(): ?array
{
return $this->shareWith;
}
PHP, $source);
$this->assertStringNotContainsString('function addShareWith', $source);
$this->assertStringNotContainsString('function removeShareWith', $source);
}

public function testGenerationWithoutConfigFileQuestion(): void
{
// No config file is given.
Expand Down
2 changes: 1 addition & 1 deletion tests/TypesGeneratorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public function testGenerate(): void
$article = file_get_contents("$this->outputDir/App/Entity/Article.php");
$this->assertStringContainsString('abstract class Article extends CreativeWork', $article);
$this->assertStringContainsString('private ?string $articleBody = null;', $article);
$this->assertStringContainsString('private array $articleSection = [];', $article);
$this->assertStringContainsString('private ?array $articleSection = [];', $article);
$this->assertStringContainsString('public function setArticleBody(?string $articleBody): void', $article);
$this->assertStringContainsString('public function getArticleBody(): ?string', $article);
$this->assertStringContainsString('public function addArticleSection(string $articleSection): void', $article);
Expand Down
12 changes: 12 additions & 0 deletions tests/config/simple-array.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
useSimpleArraySetter: true
types:
Project:
properties:
name:
range: "https://schema.org/Text"
shareWith:
range: "https://schema.org/email"
cardinality: "(0..*)"
attributes:
Assert\Unique: ~
ORM\Column: { type: "simple_array" }
Loading