From e8bafbfe9d96a376b03755f3d4c7ae5f1dfe787b Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 13 Dec 2019 10:51:57 +0100 Subject: [PATCH 1/6] Inheritance: mcve for different column name in inheritance --- tests/TDBMAbstractServiceTest.php | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tests/TDBMAbstractServiceTest.php b/tests/TDBMAbstractServiceTest.php index 5a204397..372f0aa4 100644 --- a/tests/TDBMAbstractServiceTest.php +++ b/tests/TDBMAbstractServiceTest.php @@ -466,6 +466,17 @@ private static function initSchema(Connection $connection): void ->column('fk_2')->integer() ->then()->getDbalTable()->addForeignKeyConstraint($targetTable->getDbalTable(), ['fk_1', 'fk_2'], ['id_1', 'id_2']); + // Test case, the problem here is: + // - `inheritance_agency` have an FK to `inheritance_society.**id_entity**` + // - `inheritance_society` have an FK to `inheritance_entity.**id**` + $db->table('inheritance_entity') + ->column('id')->integer()->primaryKey()->autoIncrement(); + $db->table('inheritance_society') + ->column('id_entity')->references('inheritance_entity')->primaryKey() + ->then(); + $db->table('inheritance_agency') + ->column('id')->integer()->primaryKey()->autoIncrement() + ->column('id_parent_society')->references('inheritance_society'); $sqlStmts = $toSchema->getMigrateFromSql($fromSchema, $connection->getDatabasePlatform()); From d5625f393cd932b5411c5b9fd25b3da013c1774c Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 13 Dec 2019 14:36:02 +0100 Subject: [PATCH 2/6] Inheritance: handle different pk column name --- src/Utils/BeanDescriptor.php | 21 +++++++---- src/Utils/DefaultNamingStrategy.php | 6 +-- src/Utils/ObjectBeanPropertyDescriptor.php | 3 ++ .../ScalarReferencePropertyDescriptor.php | 37 +++++++++++++++++++ 4 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 src/Utils/ScalarReferencePropertyDescriptor.php diff --git a/src/Utils/BeanDescriptor.php b/src/Utils/BeanDescriptor.php index c2846414..e43d73e6 100644 --- a/src/Utils/BeanDescriptor.php +++ b/src/Utils/BeanDescriptor.php @@ -230,7 +230,7 @@ public function getPropertiesWithDefault(): array public function getExposedProperties(): array { $exposedProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) { - return $property->getTable()->getName() == $this->table->getName(); + return !$property instanceof ScalarReferencePropertyDescriptor && $property->getTable()->getName() === $this->table->getName(); }); return $exposedProperties; @@ -256,7 +256,7 @@ private function getProperties(Table $table): array $localProperties = $this->getPropertiesForTable($table); foreach ($localProperties as $name => $property) { // We do not override properties if this is a primary key! - if ($property->isPrimaryKey()) { + if (!$property instanceof ScalarReferencePropertyDescriptor && $property->isPrimaryKey()) { continue; } $properties[$name] = $property; @@ -279,14 +279,14 @@ private function getPropertiesForTable(Table $table): array { $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName()); if ($parentRelationship) { - $ignoreColumns = $parentRelationship->getUnquotedLocalColumns(); + $ignoreColumns = $parentRelationship->getUnquotedForeignColumns(); } else { $ignoreColumns = []; } $beanPropertyDescriptors = []; foreach ($table->getColumns() as $column) { - if (array_search($column->getName(), $ignoreColumns) !== false) { + if (in_array($column->getName(), $ignoreColumns, true)) { continue; } @@ -300,11 +300,18 @@ private function getPropertiesForTable(Table $table): array } // Check that this property is not an inheritance relationship $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName()); - if ($parentRelationship === $fk) { - continue; + if ($parentRelationship !== null && $parentRelationship->getName() === $fk->getName()) { + $beanPropertyDescriptors[] = new ScalarReferencePropertyDescriptor( + $table, + $column, + $this->namingStrategy, + $this->annotationParser, + new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy, $this->annotationParser) + ); + } else { + $beanPropertyDescriptors[] = new ObjectBeanPropertyDescriptor($table, $fk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser, $this->registry->getBeanForTableName($fk->getForeignTableName()));; } - $beanPropertyDescriptors[] = new ObjectBeanPropertyDescriptor($table, $fk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser, $this->registry->getBeanForTableName($fk->getForeignTableName())); } else { $beanPropertyDescriptors[] = new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy, $this->annotationParser); } diff --git a/src/Utils/DefaultNamingStrategy.php b/src/Utils/DefaultNamingStrategy.php index 410cdcfa..a00245d9 100644 --- a/src/Utils/DefaultNamingStrategy.php +++ b/src/Utils/DefaultNamingStrategy.php @@ -312,11 +312,11 @@ protected function getUpperCamelCaseName(AbstractBeanPropertyDescriptor $propert { if ($property instanceof ObjectBeanPropertyDescriptor) { return $this->getForeignKeyUpperCamelCaseName($property->getForeignKey(), $property->isAlternativeName()); - } elseif ($property instanceof ScalarBeanPropertyDescriptor) { + } + if ($property instanceof ScalarBeanPropertyDescriptor) { return $this->getScalarColumnUpperCamelCaseName($property->getColumnName(), $property->isAlternativeName()); - } else { - throw new TDBMException('Unexpected property type. Should be either ObjectBeanPropertyDescriptor or ScalarBeanPropertyDescriptor'); // @codeCoverageIgnore } + throw new TDBMException('Unexpected property type. Should be either ObjectBeanPropertyDescriptor or ScalarBeanPropertyDescriptor'); // @codeCoverageIgnore } private function getSchema(): Schema diff --git a/src/Utils/ObjectBeanPropertyDescriptor.php b/src/Utils/ObjectBeanPropertyDescriptor.php index 6d0087e4..da7077b1 100644 --- a/src/Utils/ObjectBeanPropertyDescriptor.php +++ b/src/Utils/ObjectBeanPropertyDescriptor.php @@ -258,6 +258,9 @@ private function getLazySerializeCode(string $propertyAccess): string $rows = []; foreach ($this->getForeignKey()->getUnquotedForeignColumns() as $column) { $descriptor = $this->getBeanPropertyDescriptor($column); + if ($descriptor instanceof ScalarReferencePropertyDescriptor) { + $descriptor = $descriptor->getReferencedPropertyDescriptor(); + } $indexName = ltrim($descriptor->getVariableName(), '$'); $columnGetterName = $descriptor->getGetterName(); $rows[] = "'$indexName' => $propertyAccess->$columnGetterName()"; diff --git a/src/Utils/ScalarReferencePropertyDescriptor.php b/src/Utils/ScalarReferencePropertyDescriptor.php new file mode 100644 index 00000000..0d060d7c --- /dev/null +++ b/src/Utils/ScalarReferencePropertyDescriptor.php @@ -0,0 +1,37 @@ +referencedPropertyDescriptor = $referencedPropertyDescriptor; + } + + /** + * @return AbstractBeanPropertyDescriptor + */ + public function getReferencedPropertyDescriptor(): AbstractBeanPropertyDescriptor + { + return $this->referencedPropertyDescriptor; + } +} From 57523c12d06fee24e650ae736af2bf086f4a33de Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 13 Dec 2019 15:14:04 +0100 Subject: [PATCH 3/6] Inheritance: Correct serialization on different pk column name --- src/Utils/BeanDescriptor.php | 6 +++--- src/Utils/ObjectBeanPropertyDescriptor.php | 12 ++++++++---- src/Utils/ScalarReferencePropertyDescriptor.php | 5 +++++ 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Utils/BeanDescriptor.php b/src/Utils/BeanDescriptor.php index e43d73e6..04389faf 100644 --- a/src/Utils/BeanDescriptor.php +++ b/src/Utils/BeanDescriptor.php @@ -298,6 +298,7 @@ private function getPropertiesForTable(Table $table): array continue 2; } } + $propertyDescriptor = new ObjectBeanPropertyDescriptor($table, $fk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser, $this->registry->getBeanForTableName($fk->getForeignTableName())); // Check that this property is not an inheritance relationship $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName()); if ($parentRelationship !== null && $parentRelationship->getName() === $fk->getName()) { @@ -306,12 +307,11 @@ private function getPropertiesForTable(Table $table): array $column, $this->namingStrategy, $this->annotationParser, - new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy, $this->annotationParser) + $propertyDescriptor ); } else { - $beanPropertyDescriptors[] = new ObjectBeanPropertyDescriptor($table, $fk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser, $this->registry->getBeanForTableName($fk->getForeignTableName()));; + $beanPropertyDescriptors[] = $propertyDescriptor; } - } else { $beanPropertyDescriptors[] = new ScalarBeanPropertyDescriptor($table, $column, $this->namingStrategy, $this->annotationParser); } diff --git a/src/Utils/ObjectBeanPropertyDescriptor.php b/src/Utils/ObjectBeanPropertyDescriptor.php index da7077b1..3c941a16 100644 --- a/src/Utils/ObjectBeanPropertyDescriptor.php +++ b/src/Utils/ObjectBeanPropertyDescriptor.php @@ -253,7 +253,7 @@ public function getJsonSerializeCode(): string return $code; } - private function getLazySerializeCode(string $propertyAccess): string + public function getLazySerializeCode(string $propertyAccess): string { $rows = []; foreach ($this->getForeignKey()->getUnquotedForeignColumns() as $column) { @@ -261,9 +261,13 @@ private function getLazySerializeCode(string $propertyAccess): string if ($descriptor instanceof ScalarReferencePropertyDescriptor) { $descriptor = $descriptor->getReferencedPropertyDescriptor(); } - $indexName = ltrim($descriptor->getVariableName(), '$'); - $columnGetterName = $descriptor->getGetterName(); - $rows[] = "'$indexName' => $propertyAccess->$columnGetterName()"; + if ($descriptor instanceof ObjectBeanPropertyDescriptor) { + $rows[] = trim($descriptor->getLazySerializeCode($propertyAccess), '[]'); + } else { + $indexName = ltrim($descriptor->getVariableName(), '$'); + $columnGetterName = $descriptor->getGetterName(); + $rows[] = "'$indexName' => $propertyAccess->$columnGetterName()"; + } } return '[' . implode(', ', $rows) . ']'; } diff --git a/src/Utils/ScalarReferencePropertyDescriptor.php b/src/Utils/ScalarReferencePropertyDescriptor.php index 0d060d7c..7d51e348 100644 --- a/src/Utils/ScalarReferencePropertyDescriptor.php +++ b/src/Utils/ScalarReferencePropertyDescriptor.php @@ -34,4 +34,9 @@ public function getReferencedPropertyDescriptor(): AbstractBeanPropertyDescripto { return $this->referencedPropertyDescriptor; } + + public function getJsonSerializeCode(): string + { + return $this->referencedPropertyDescriptor->getJsonSerializeCode(); + } } From e551877d0f3f6345a0d08ed8977c1e6fc5f8e44d Mon Sep 17 00:00:00 2001 From: Guillaume Date: Fri, 13 Dec 2019 15:22:13 +0100 Subject: [PATCH 4/6] Inheritance: Correct constructor on different pk column name --- src/Utils/BeanDescriptor.php | 2 +- src/Utils/ScalarReferencePropertyDescriptor.php | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Utils/BeanDescriptor.php b/src/Utils/BeanDescriptor.php index 04389faf..7b163e96 100644 --- a/src/Utils/BeanDescriptor.php +++ b/src/Utils/BeanDescriptor.php @@ -201,7 +201,7 @@ public function getBeanPropertyDescriptors(): array public function getConstructorProperties(): array { $constructorProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) { - return $property->isCompulsory(); + return !$property instanceof ScalarReferencePropertyDescriptor && $property->isCompulsory(); }); return $constructorProperties; diff --git a/src/Utils/ScalarReferencePropertyDescriptor.php b/src/Utils/ScalarReferencePropertyDescriptor.php index 7d51e348..8319f72c 100644 --- a/src/Utils/ScalarReferencePropertyDescriptor.php +++ b/src/Utils/ScalarReferencePropertyDescriptor.php @@ -21,8 +21,7 @@ public function __construct( NamingStrategyInterface $namingStrategy, AnnotationParser $annotationParser, AbstractBeanPropertyDescriptor $referencedPropertyDescriptor - ) - { + ) { parent::__construct($table, $column, $namingStrategy, $annotationParser); $this->referencedPropertyDescriptor = $referencedPropertyDescriptor; } From 6b5eecb53f7fb175ddcdd8a0be12464ba6d271e8 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Mon, 16 Dec 2019 11:07:06 +0100 Subject: [PATCH 5/6] Inheritance: Allow reference to reference, more specific classname --- src/Utils/BeanDescriptor.php | 8 ++++---- ...p => InheritanceReferencePropertyDescriptor.php} | 13 ++++++++----- src/Utils/ObjectBeanPropertyDescriptor.php | 10 ++++++---- 3 files changed, 18 insertions(+), 13 deletions(-) rename src/Utils/{ScalarReferencePropertyDescriptor.php => InheritanceReferencePropertyDescriptor.php} (61%) diff --git a/src/Utils/BeanDescriptor.php b/src/Utils/BeanDescriptor.php index 7b163e96..819e0988 100644 --- a/src/Utils/BeanDescriptor.php +++ b/src/Utils/BeanDescriptor.php @@ -201,7 +201,7 @@ public function getBeanPropertyDescriptors(): array public function getConstructorProperties(): array { $constructorProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) { - return !$property instanceof ScalarReferencePropertyDescriptor && $property->isCompulsory(); + return !$property instanceof InheritanceReferencePropertyDescriptor && $property->isCompulsory(); }); return $constructorProperties; @@ -230,7 +230,7 @@ public function getPropertiesWithDefault(): array public function getExposedProperties(): array { $exposedProperties = array_filter($this->beanPropertyDescriptors, function (AbstractBeanPropertyDescriptor $property) { - return !$property instanceof ScalarReferencePropertyDescriptor && $property->getTable()->getName() === $this->table->getName(); + return !$property instanceof InheritanceReferencePropertyDescriptor && $property->getTable()->getName() === $this->table->getName(); }); return $exposedProperties; @@ -256,7 +256,7 @@ private function getProperties(Table $table): array $localProperties = $this->getPropertiesForTable($table); foreach ($localProperties as $name => $property) { // We do not override properties if this is a primary key! - if (!$property instanceof ScalarReferencePropertyDescriptor && $property->isPrimaryKey()) { + if (!$property instanceof InheritanceReferencePropertyDescriptor && $property->isPrimaryKey()) { continue; } $properties[$name] = $property; @@ -302,7 +302,7 @@ private function getPropertiesForTable(Table $table): array // Check that this property is not an inheritance relationship $parentRelationship = $this->schemaAnalyzer->getParentRelationship($table->getName()); if ($parentRelationship !== null && $parentRelationship->getName() === $fk->getName()) { - $beanPropertyDescriptors[] = new ScalarReferencePropertyDescriptor( + $beanPropertyDescriptors[] = new InheritanceReferencePropertyDescriptor( $table, $column, $this->namingStrategy, diff --git a/src/Utils/ScalarReferencePropertyDescriptor.php b/src/Utils/InheritanceReferencePropertyDescriptor.php similarity index 61% rename from src/Utils/ScalarReferencePropertyDescriptor.php rename to src/Utils/InheritanceReferencePropertyDescriptor.php index 8319f72c..fc5a42c0 100644 --- a/src/Utils/ScalarReferencePropertyDescriptor.php +++ b/src/Utils/InheritanceReferencePropertyDescriptor.php @@ -8,9 +8,9 @@ use TheCodingMachine\TDBM\Utils\Annotation\AnnotationParser; /** - * This class represents a reference to a AbstractBeanPropertyDescriptor + * This class represents a reference to a AbstractBeanPropertyDescriptor used in an inheritance schema */ -class ScalarReferencePropertyDescriptor extends ScalarBeanPropertyDescriptor +class InheritanceReferencePropertyDescriptor extends ScalarBeanPropertyDescriptor { /** @var AbstractBeanPropertyDescriptor */ private $referencedPropertyDescriptor; @@ -27,15 +27,18 @@ public function __construct( } /** - * @return AbstractBeanPropertyDescriptor + * @return ScalarBeanPropertyDescriptor|ObjectBeanPropertyDescriptor */ - public function getReferencedPropertyDescriptor(): AbstractBeanPropertyDescriptor + public function getNonScalarReferencedPropertyDescriptor(): AbstractBeanPropertyDescriptor { + if ($this->referencedPropertyDescriptor instanceof InheritanceReferencePropertyDescriptor) { + return $this->referencedPropertyDescriptor->getNonScalarReferencedPropertyDescriptor(); + } return $this->referencedPropertyDescriptor; } public function getJsonSerializeCode(): string { - return $this->referencedPropertyDescriptor->getJsonSerializeCode(); + return $this->getNonScalarReferencedPropertyDescriptor()->getJsonSerializeCode(); } } diff --git a/src/Utils/ObjectBeanPropertyDescriptor.php b/src/Utils/ObjectBeanPropertyDescriptor.php index 3c941a16..8a14be67 100644 --- a/src/Utils/ObjectBeanPropertyDescriptor.php +++ b/src/Utils/ObjectBeanPropertyDescriptor.php @@ -253,20 +253,22 @@ public function getJsonSerializeCode(): string return $code; } - public function getLazySerializeCode(string $propertyAccess): string + private function getLazySerializeCode(string $propertyAccess): string { $rows = []; foreach ($this->getForeignKey()->getUnquotedForeignColumns() as $column) { $descriptor = $this->getBeanPropertyDescriptor($column); - if ($descriptor instanceof ScalarReferencePropertyDescriptor) { - $descriptor = $descriptor->getReferencedPropertyDescriptor(); + if ($descriptor instanceof InheritanceReferencePropertyDescriptor) { + $descriptor = $descriptor->getNonScalarReferencedPropertyDescriptor(); } if ($descriptor instanceof ObjectBeanPropertyDescriptor) { $rows[] = trim($descriptor->getLazySerializeCode($propertyAccess), '[]'); - } else { + } elseif ($descriptor instanceof ScalarBeanPropertyDescriptor) { $indexName = ltrim($descriptor->getVariableName(), '$'); $columnGetterName = $descriptor->getGetterName(); $rows[] = "'$indexName' => $propertyAccess->$columnGetterName()"; + } else { + throw new TDBMException('PropertyDescriptor of class `' . get_class($descriptor) . '` cannot be serialized.'); } } return '[' . implode(', ', $rows) . ']'; From d37eec81c63c8c8ef35243d9ff5928fbc20886b3 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Mon, 16 Dec 2019 14:07:21 +0100 Subject: [PATCH 6/6] Inheritance: Assert type is right --- src/Utils/InheritanceReferencePropertyDescriptor.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utils/InheritanceReferencePropertyDescriptor.php b/src/Utils/InheritanceReferencePropertyDescriptor.php index fc5a42c0..4c7f7301 100644 --- a/src/Utils/InheritanceReferencePropertyDescriptor.php +++ b/src/Utils/InheritanceReferencePropertyDescriptor.php @@ -34,6 +34,7 @@ public function getNonScalarReferencedPropertyDescriptor(): AbstractBeanProperty if ($this->referencedPropertyDescriptor instanceof InheritanceReferencePropertyDescriptor) { return $this->referencedPropertyDescriptor->getNonScalarReferencedPropertyDescriptor(); } + assert($this->referencedPropertyDescriptor instanceof ScalarBeanPropertyDescriptor || $this->referencedPropertyDescriptor instanceof ObjectBeanPropertyDescriptor); return $this->referencedPropertyDescriptor; }