diff --git a/src/OrderByAnalyzer.php b/src/OrderByAnalyzer.php index 6055baec..7e499c5c 100644 --- a/src/OrderByAnalyzer.php +++ b/src/OrderByAnalyzer.php @@ -131,7 +131,7 @@ private function analyzeOrderByNoCache(string $orderBy) : array */ private function trimDirection(string $sql) : string { - preg_match('/^(.*)(\s+(DESC|ASC|))*$/Ui', $sql, $matches); + preg_match('/^((.|\n)*)(\s+(DESC|ASC))?$/Ui', $sql, $matches); return $matches[1]; } diff --git a/src/Utils/BeanDescriptor.php b/src/Utils/BeanDescriptor.php index d3dafb9f..b65b32c1 100644 --- a/src/Utils/BeanDescriptor.php +++ b/src/Utils/BeanDescriptor.php @@ -1275,7 +1275,6 @@ private function removeDuplicateIndexes(array $indexes): array private function generateFindByDaoCodeForIndex(Index $index, string $beanNamespace, string $beanClassName): ?MethodGenerator { $columns = $index->getColumns(); - $usedBeans = []; /** * The list of elements building this index (expressed as columns or foreign keys) @@ -1301,42 +1300,26 @@ private function generateFindByDaoCodeForIndex(Index $index, string $beanNamespa } $parameters = []; - //$functionParameters = []; $first = true; /** @var AbstractBeanPropertyDescriptor $element */ foreach ($elements as $element) { $parameter = new ParameterGenerator(ltrim($element->getSafeVariableName(), '$')); if (!$first && !($element->isCompulsory() && $index->isUnique())) { $parameterType = '?'; - //$functionParameter = '?'; } else { $parameterType = ''; - //$functionParameter = ''; } $parameterType .= $element->getPhpType(); $parameter->setType($parameterType); if (!$first && !($element->isCompulsory() && $index->isUnique())) { $parameter->setDefaultValue(null); } - //$functionParameter .= $element->getPhpType(); - $elementClassName = $element->getClassName(); - if ($elementClassName) { - $usedBeans[] = $beanNamespace.'\\'.$elementClassName; - } - //$functionParameter .= ' '.$element->getVariableName(); if ($first) { $first = false; - } /*else { - $functionParameter .= ' = null'; - }*/ - //$functionParameters[] = $functionParameter; + } $parameters[] = $parameter; } - //$functionParametersString = implode(', ', $functionParameters); - - $count = 0; - $params = []; $filterArrayCode = ''; $commentArguments = []; @@ -1358,12 +1341,11 @@ private function generateFindByDaoCodeForIndex(Index $index, string $beanNamespa } elseif ($element instanceof ObjectBeanPropertyDescriptor) { $foreignKey = $element->getForeignKey(); $columns = SafeFunctions::arrayCombine($foreignKey->getUnquotedLocalColumns(), $foreignKey->getUnquotedForeignColumns()); - ++$count; $foreignTable = $this->schema->getTable($foreignKey->getForeignTableName()); foreach ($columns as $localColumn => $foreignColumn) { // TODO: a foreign key could point to another foreign key. In this case, there is no getter for the pointed column. We don't support this case. $targetedElement = new ScalarBeanPropertyDescriptor($foreignTable, $foreignTable->getColumn($foreignColumn), $this->namingStrategy, $this->annotationParser); - if ($first || $element->isCompulsory() && $index->isUnique()) { + if ($first || ($element->isCompulsory() && $index->isUnique())) { // First parameter for index is not nullable $filterArrayCode .= ' '.var_export($localColumn, true).' => '.$element->getSafeVariableName().'->'.$targetedElement->getGetterName()."(),\n"; } else { @@ -1378,9 +1360,6 @@ private function generateFindByDaoCodeForIndex(Index $index, string $beanNamespa } } - //$paramsString = implode("\n", $params); - - $methodName = $this->namingStrategy->getFindByIndexMethodName($index, $elements); $method = new MethodGenerator($methodName); @@ -1459,7 +1438,11 @@ private function generateOnDeleteCode(): ?MethodGenerator foreach ($relationships as $relationship) { if ($relationship instanceof ObjectBeanPropertyDescriptor) { $tdbmFk = ForeignKey::createFromFk($relationship->getForeignKey()); - $code .= '$this->setRef('.var_export($tdbmFk->getCacheKey(), true).', null, '.var_export($this->table->getName(), true).");\n"; + $code .= sprintf( + "\$this->setRef(%s, null, %s);\n", + var_export($tdbmFk->getCacheKey(), true), + var_export($this->table->getName(), true) + ); } } @@ -1678,10 +1661,21 @@ private function generateGetForeignKeys(array $fks): MethodGenerator foreach ($fks as $fk) { $tdbmFk = ForeignKey::createFromFk($fk); + + // Override column name in case of inheritance + $foreignTableName = $fk->getForeignTableName(); + $foreignColumns = $fk->getUnquotedForeignColumns(); + foreach ($foreignColumns as $key => $foreignColumn) { + $descriptor = $this->findScalarPropertyDescriptorInTable($foreignTableName, $foreignColumn); + if ($descriptor instanceof InheritanceReferencePropertyDescriptor) { + $foreignColumns[$key] = $this->foreignColumnNameInInheritance($descriptor, $foreignColumn); + } + } + $fkArray[$tdbmFk->getCacheKey()] = [ ForeignKey::FOREIGN_TABLE => $fk->getForeignTableName(), ForeignKey::LOCAL_COLUMNS => $fk->getUnquotedLocalColumns(), - ForeignKey::FOREIGN_COLUMNS => $fk->getUnquotedForeignColumns(), + ForeignKey::FOREIGN_COLUMNS => $foreignColumns, ]; } @@ -1717,6 +1711,39 @@ private function generateGetForeignKeys(array $fks): MethodGenerator return $method; } + private function findScalarPropertyDescriptorInTable(string $tableName, string $columnName): ?ScalarBeanPropertyDescriptor + { + $beanDescriptor = $this->registry->getBeanForTableName($tableName); + foreach ($beanDescriptor->getBeanPropertyDescriptors() as $descriptor) { + if ($descriptor instanceof ScalarBeanPropertyDescriptor && $descriptor->getColumnName() === $columnName) { + return $descriptor; + } + } + return null; + } + + /** + * Extract the foreign column name from a InheritanceReferencePropertyDescriptor + */ + private function foreignColumnNameInInheritance(InheritanceReferencePropertyDescriptor $descriptor, string $column): string + { + $nonReferenceDescriptor = $descriptor->getNonScalarReferencedPropertyDescriptor(); + if ($nonReferenceDescriptor instanceof ScalarBeanPropertyDescriptor) { + return $nonReferenceDescriptor->getColumnName(); + } + if ($nonReferenceDescriptor instanceof ObjectBeanPropertyDescriptor) { + $foreignKey = $nonReferenceDescriptor->getForeignKey(); + $localColumns = $foreignKey->getLocalColumns(); + $foreignColumns = $foreignKey->getForeignColumns(); + foreach ($localColumns as $key => $localColumn) { + if ($localColumn === $column) { + return $foreignColumns[$key]; + } + } + } + return $column; + } + /** * @param mixed $var * @param string $indent diff --git a/src/Utils/ObjectBeanPropertyDescriptor.php b/src/Utils/ObjectBeanPropertyDescriptor.php index a96e9128..483ddddd 100644 --- a/src/Utils/ObjectBeanPropertyDescriptor.php +++ b/src/Utils/ObjectBeanPropertyDescriptor.php @@ -292,6 +292,9 @@ private function getBeanPropertyDescriptor(string $column): AbstractBeanProperty if ($descriptor instanceof ScalarBeanPropertyDescriptor && $descriptor->getColumnName() === $column) { return $descriptor; } + if ($descriptor instanceof ObjectBeanPropertyDescriptor && in_array($column, $descriptor->getForeignKey()->getLocalColumns(), true)) { + return $descriptor; + } if ($descriptor instanceof ObjectBeanPropertyDescriptor && in_array($column, $descriptor->getForeignKey()->getUnquotedLocalColumns(), true)) { return $descriptor; } diff --git a/tests/TDBMAbstractServiceTest.php b/tests/TDBMAbstractServiceTest.php index dcd9cd9b..04f3d905 100644 --- a/tests/TDBMAbstractServiceTest.php +++ b/tests/TDBMAbstractServiceTest.php @@ -392,6 +392,10 @@ private static function initSchema(Connection $connection): void ->column('base_object_id')->references('base_objects')->unique()->comment('@JsonCollection'); } + $db->table('composite_fk_target_reference') + ->column('id')->integer()->primaryKey()->autoIncrement() + ->column('label')->string(); + $db->table('composite_fk_target_reference') ->column('id')->integer()->primaryKey()->autoIncrement() ->column('label')->string(); @@ -410,10 +414,10 @@ private static function initSchema(Connection $connection): void // - `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(); + ->column('id')->integer()->primaryKey()->autoIncrement() + ->column('name')->string(); $db->table('inheritance_society') - ->column('id_entity')->references('inheritance_entity')->primaryKey() - ->then(); + ->column('id_entity')->references('inheritance_entity')->primaryKey(); $db->table('inheritance_agency') ->column('id')->integer()->primaryKey()->autoIncrement() ->column('id_parent_society')->references('inheritance_society'); diff --git a/tests/TDBMDaoGeneratorTest.php b/tests/TDBMDaoGeneratorTest.php index 67258ba3..2395567e 100644 --- a/tests/TDBMDaoGeneratorTest.php +++ b/tests/TDBMDaoGeneratorTest.php @@ -64,6 +64,8 @@ use TheCodingMachine\TDBM\Test\Dao\Bean\Generated\BoatBaseBean; use TheCodingMachine\TDBM\Test\Dao\Bean\Generated\FileBaseBean; use TheCodingMachine\TDBM\Test\Dao\Bean\Generated\UserBaseBean; +use TheCodingMachine\TDBM\Test\Dao\Bean\InheritanceAgencyBean; +use TheCodingMachine\TDBM\Test\Dao\Bean\InheritanceSocietyBean; use TheCodingMachine\TDBM\Test\Dao\Bean\InheritedObjectBean; use TheCodingMachine\TDBM\Test\Dao\Bean\NodeBean; use TheCodingMachine\TDBM\Test\Dao\Bean\PersonBean; @@ -81,6 +83,8 @@ use TheCodingMachine\TDBM\Test\Dao\DogDao; use TheCodingMachine\TDBM\Test\Dao\FileDao; use TheCodingMachine\TDBM\Test\Dao\Generated\UserBaseDao; +use TheCodingMachine\TDBM\Test\Dao\InheritanceAgencyDao; +use TheCodingMachine\TDBM\Test\Dao\InheritanceSocietyDao; use TheCodingMachine\TDBM\Test\Dao\InheritedObjectDao; use TheCodingMachine\TDBM\Test\Dao\NodeDao; use TheCodingMachine\TDBM\Test\Dao\PersonDao; @@ -2354,4 +2358,15 @@ private function skipOracle() $this->markTestSkipped('Not supported in Oracle'); } } + + public function testInheritanceFkWithDifferentPkName(): void + { + $inheritanceSocietyDao = new InheritanceSocietyDao($this->tdbmService); + $inheritanceAgencyDao = new InheritanceAgencyDao($this->tdbmService); + $society = new InheritanceSocietyBean('test'); + $inheritanceSocietyDao->save($society); + $this->assertNotNull($society->getId()); + $agency = new InheritanceAgencyBean($society); + $inheritanceAgencyDao->save($agency); + } }