Skip to content

Commit 653773d

Browse files
committed
One To One inverse index: implementation
1 parent badd068 commit 653773d

File tree

5 files changed

+73
-20
lines changed

5 files changed

+73
-20
lines changed

src/Utils/BeanDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ private function getDirectForeignKeysDescriptors(): array
356356
$descriptors = [];
357357

358358
foreach ($fks as $fk) {
359-
$descriptors[] = new DirectForeignKeyMethodDescriptor($fk, $this->table, $this->namingStrategy, $this->annotationParser);
359+
$descriptors[] = new DirectForeignKeyMethodDescriptor($fk, $this->table, $this->namingStrategy, $this->annotationParser, $this->beanNamespace);
360360
}
361361

362362
return $descriptors;

src/Utils/DirectForeignKeyMethodDescriptor.php

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,30 @@ class DirectForeignKeyMethodDescriptor implements MethodDescriptorInterface
4040
* @var AnnotationParser
4141
*/
4242
private $annotationParser;
43+
/**
44+
* @var string
45+
*/
46+
private $beanNamespace;
4347

4448
/**
4549
* @param ForeignKeyConstraint $fk The foreign key pointing to our bean
4650
* @param Table $mainTable The main table that is pointed to
4751
* @param NamingStrategyInterface $namingStrategy
52+
* @param AnnotationParser $annotationParser
53+
* @param string $beanNamespace
4854
*/
49-
public function __construct(ForeignKeyConstraint $fk, Table $mainTable, NamingStrategyInterface $namingStrategy, AnnotationParser $annotationParser)
50-
{
55+
public function __construct(
56+
ForeignKeyConstraint $fk,
57+
Table $mainTable,
58+
NamingStrategyInterface $namingStrategy,
59+
AnnotationParser $annotationParser,
60+
string $beanNamespace
61+
) {
5162
$this->foreignKey = $fk;
5263
$this->mainTable = $mainTable;
5364
$this->namingStrategy = $namingStrategy;
5465
$this->annotationParser = $annotationParser;
66+
$this->beanNamespace = $beanNamespace;
5567
}
5668

5769
/**
@@ -100,23 +112,37 @@ public function useAlternativeName(): void
100112
public function getCode() : array
101113
{
102114
$beanClass = $this->getBeanClassName();
115+
$tdbmFk = ForeignKey::createFromFk($this->foreignKey);
103116

104117
$getter = new MethodGenerator($this->getName());
105-
$getter->setDocBlock(sprintf('Returns the list of %s pointing to this bean via the %s column.', $beanClass, implode(', ', $this->foreignKey->getUnquotedLocalColumns())));
106-
$getter->getDocBlock()->setTag(new ReturnTag([
107-
$beanClass.'[]',
108-
'\\'.AlterableResultIterator::class
109-
]));
110-
$getter->setReturnType(AlterableResultIterator::class);
111118

112-
$tdbmFk = ForeignKey::createFromFk($this->foreignKey);
119+
if ($this->hasLocalUniqueIndex()) {
120+
$getter->setDocBlock(sprintf('Returns the %s pointing to this bean via the %s column.', $beanClass, implode(', ', $this->foreignKey->getUnquotedLocalColumns())));
121+
$classType = '\\' . $this->beanNamespace . '\\' . $beanClass;
122+
$getter->getDocBlock()->setTag(new ReturnTag([$classType . '|null']));
123+
$getter->setReturnType('?' . $classType);
113124

114-
$code = sprintf(
115-
'return $this->retrieveManyToOneRelationshipsStorage(%s, %s, %s);',
116-
var_export($this->foreignKey->getLocalTableName(), true),
117-
var_export($tdbmFk->getCacheKey(), true),
118-
$this->getFilters($this->foreignKey)
119-
);
125+
$code = sprintf(
126+
'return $this->retrieveManyToOneRelationshipsStorage(%s, %s, %s)->first();',
127+
var_export($this->foreignKey->getLocalTableName(), true),
128+
var_export($tdbmFk->getCacheKey(), true),
129+
$this->getFilters($this->foreignKey)
130+
);
131+
} else {
132+
$getter->setDocBlock(sprintf('Returns the list of %s pointing to this bean via the %s column.', $beanClass, implode(', ', $this->foreignKey->getUnquotedLocalColumns())));
133+
$getter->getDocBlock()->setTag(new ReturnTag([
134+
$beanClass . '[]',
135+
'\\' . AlterableResultIterator::class
136+
]));
137+
$getter->setReturnType(AlterableResultIterator::class);
138+
139+
$code = sprintf(
140+
'return $this->retrieveManyToOneRelationshipsStorage(%s, %s, %s);',
141+
var_export($this->foreignKey->getLocalTableName(), true),
142+
var_export($tdbmFk->getCacheKey(), true),
143+
$this->getFilters($this->foreignKey)
144+
);
145+
}
120146

121147
$getter->setBody($code);
122148

@@ -144,6 +170,25 @@ private function getFilters(ForeignKeyConstraint $fk) : string
144170
return $parametersCode;
145171
}
146172

173+
/**
174+
* Check if the ForeignKey have an unique index
175+
*
176+
* @return bool
177+
*/
178+
private function hasLocalUniqueIndex(): bool
179+
{
180+
foreach ($this->getForeignKey()->getLocalTable()->getIndexes() as $index) {
181+
if (
182+
$index->isUnique()
183+
&& count($index->getColumns()) === count($this->getForeignKey()->getLocalColumns())
184+
&& !array_diff($index->getColumns(), $this->getForeignKey()->getLocalColumns()) // Check for permuted columns too
185+
) {
186+
return true;
187+
}
188+
}
189+
return false;
190+
}
191+
147192
/**
148193
* Returns an array of classes that needs a "use" for this method.
149194
*
@@ -181,17 +226,21 @@ public function getJsonSerializeCode() : string
181226
$class = $this->getBeanClassName();
182227
$variableName = '$' . TDBMDaoGenerator::toVariableName($class);
183228
$getter = $this->getName();
184-
$code = <<<PHP
229+
if ($this->hasLocalUniqueIndex()) {
230+
$code = "\$array['$index'] = (\$object = \$this->$getter()) ? \$object->$format : null;";
231+
} else {
232+
$code = <<<PHP
185233
\$array['$index'] = array_map(function ($class $variableName) {
186234
return ${variableName}->$format;
187235
}, \$this->$getter()->toArray());
188236
PHP;
237+
}
189238
if (!$isIncluded) {
190239
$code = preg_replace('(\n)', '\0 ', $code);
191240
$code = <<<PHP
192241
if (!\$stopRecursion) {
193242
$code
194-
};
243+
}
195244
PHP;
196245
}
197246
return $code;

tests/TDBMAbstractServiceTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ private static function initSchema(Connection $connection): void
441441
->column('id')->integer()->primaryKey()->autoIncrement();
442442
$db->table('object_inherited')
443443
->column('id')->integer()->primaryKey()->autoIncrement()
444-
->column('object_base_id')->references('object_base')->unique();
444+
->column('object_base_id')->references('object_base')->unique()->comment('@JsonCollection');
445445

446446
$sqlStmts = $toSchema->getMigrateFromSql($fromSchema, $connection->getDatabasePlatform());
447447

tests/TDBMDaoGeneratorTest.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,6 +2079,9 @@ public function testLazyLoad(): void
20792079
$this->assertSame(TDBMObjectStateEnum::STATE_NOT_LOADED, $roleBean->_getDbRows()['roles']->_getStatus());
20802080
}
20812081

2082+
/**
2083+
* @depends testDaoGeneration
2084+
*/
20822085
public function testOneToOneInverseRelationGetter(): void
20832086
{
20842087
$objectBaseDao = new ObjectBaseDao($this->tdbmService);
@@ -2089,5 +2092,6 @@ public function testOneToOneInverseRelationGetter(): void
20892092
$objectInherited = new ObjectInheritedBean($objectBase);
20902093
$objectInheritedDao->save($objectInherited);
20912094
$this->assertInstanceOf(ObjectInheritedBean::class, $objectBase->getObjectInherited());
2095+
$this->assertEquals(1, $objectBase->jsonSerialize()['objectInherited']['id']);
20922096
}
20932097
}

tests/Utils/DirectForeignKeyMethodDescriptorTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public function testGetForeignKey(): void
1515
$table = $this->createMock(Table::class);
1616
$ns = $this->createMock(DefaultNamingStrategy::class);
1717
$ap = $this->createMock(AnnotationParser::class);
18-
$descriptor = new DirectForeignKeyMethodDescriptor($fk, $table, $ns, $ap);
18+
$descriptor = new DirectForeignKeyMethodDescriptor($fk, $table, $ns, $ap, '');
1919

2020
$this->assertSame($fk, $descriptor->getForeignKey());
2121
$this->assertSame($table, $descriptor->getMainTable());

0 commit comments

Comments
 (0)