Skip to content

Commit 686ab36

Browse files
authored
Merge pull request #160 from Kharhamel/nameConflicts
better bean method names conflicts resolution
2 parents 992f64c + 3b06b5c commit 686ab36

8 files changed

+131
-59
lines changed

src/Utils/AbstractBeanPropertyDescriptor.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
/**
1111
* This class represent a property in a bean (a property has a getter, a setter, etc...).
1212
*/
13-
abstract class AbstractBeanPropertyDescriptor
13+
abstract class AbstractBeanPropertyDescriptor implements MethodDescriptorInterface
1414
{
1515
/**
1616
* @var Table
@@ -80,6 +80,14 @@ public function getSetterName(): string
8080
return $this->namingStrategy->getSetterName($this);
8181
}
8282

83+
/**
84+
* Alias of the method getGetterName(). Used to validate MethodDescriptorInterface
85+
*/
86+
public function getName(): string
87+
{
88+
return $this->getGetterName();
89+
}
90+
8391
public function getGetterName(): string
8492
{
8593
return $this->namingStrategy->getGetterName($this);

src/Utils/BeanDescriptor.php

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,18 @@ class BeanDescriptor implements BeanDescriptorInterface
110110
* @var BeanRegistry
111111
*/
112112
private $registry;
113+
/**
114+
* @var MethodDescriptorInterface[][]
115+
*/
116+
private $descriptorsByMethodName = [];
117+
/**
118+
* @var DirectForeignKeyMethodDescriptor[]|null
119+
*/
120+
private $directForeignKeysDescriptors = null;
121+
/**
122+
* @var PivotTableMethodsDescriptor[]|null
123+
*/
124+
private $pivotTableDescriptors = null;
113125

114126
public function __construct(
115127
Table $table,
@@ -144,6 +156,11 @@ public function __construct(
144156
public function initBeanPropertyDescriptors(): void
145157
{
146158
$this->beanPropertyDescriptors = $this->getProperties($this->table);
159+
160+
//init the list of method names with regular properties names
161+
foreach ($this->beanPropertyDescriptors as $beanPropertyDescriptor) {
162+
$this->checkForDuplicate($beanPropertyDescriptor);
163+
}
147164
}
148165

149166
/**
@@ -373,68 +390,82 @@ private function generateBeanConstructor() : MethodGenerator
373390
*/
374391
private function getDirectForeignKeysDescriptors(): array
375392
{
393+
if ($this->directForeignKeysDescriptors !== null) {
394+
return $this->directForeignKeysDescriptors;
395+
}
376396
$fks = $this->tdbmSchemaAnalyzer->getIncomingForeignKeys($this->table->getName());
377397

378398
$descriptors = [];
379399

380400
foreach ($fks as $fk) {
381-
$descriptors[] = new DirectForeignKeyMethodDescriptor($fk, $this->table, $this->namingStrategy, $this->annotationParser, $this->beanNamespace);
401+
$desc = new DirectForeignKeyMethodDescriptor($fk, $this->table, $this->namingStrategy, $this->annotationParser, $this->beanNamespace);
402+
$this->checkForDuplicate($desc);
403+
$descriptors[] = $desc;
382404
}
383405

384-
return $descriptors;
406+
$this->directForeignKeysDescriptors = $descriptors;
407+
return $this->directForeignKeysDescriptors;
385408
}
386409

387410
/**
388411
* @return PivotTableMethodsDescriptor[]
389412
*/
390413
private function getPivotTableDescriptors(): array
391414
{
415+
if ($this->pivotTableDescriptors !== null) {
416+
return $this->pivotTableDescriptors;
417+
}
392418
$descs = [];
393419
foreach ($this->schemaAnalyzer->detectJunctionTables(true) as $table) {
394420
// There are exactly 2 FKs since this is a pivot table.
395421
$fks = array_values($table->getForeignKeys());
396422

397423
if ($fks[0]->getForeignTableName() === $this->table->getName()) {
398424
list($localFk, $remoteFk) = $fks;
399-
$descs[] = new PivotTableMethodsDescriptor($table, $localFk, $remoteFk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser);
425+
$desc = new PivotTableMethodsDescriptor($table, $localFk, $remoteFk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser);
426+
$this->checkForDuplicate($desc);
427+
$descs[] = $desc;
400428
}
401429
if ($fks[1]->getForeignTableName() === $this->table->getName()) {
402430
list($remoteFk, $localFk) = $fks;
403-
$descs[] = new PivotTableMethodsDescriptor($table, $localFk, $remoteFk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser);
431+
$desc = new PivotTableMethodsDescriptor($table, $localFk, $remoteFk, $this->namingStrategy, $this->beanNamespace, $this->annotationParser);
432+
$this->checkForDuplicate($desc);
433+
$descs[] = $desc;
404434
}
405435
}
406436

407-
return $descs;
437+
$this->pivotTableDescriptors = $descs;
438+
return $this->pivotTableDescriptors;
439+
}
440+
441+
/**
442+
* Check the method name isn't already used and flag the associated descriptors to use their alternative names if it is the case
443+
*/
444+
private function checkForDuplicate(MethodDescriptorInterface $descriptor): void
445+
{
446+
$name = $descriptor->getName();
447+
if (!isset($this->descriptorsByMethodName[$name])) {
448+
$this->descriptorsByMethodName[$name] = [];
449+
}
450+
$this->descriptorsByMethodName[$name][] = $descriptor;
451+
if (count($this->descriptorsByMethodName[$name]) > 1) {
452+
foreach ($this->descriptorsByMethodName[$name] as $duplicateDescriptor) {
453+
$duplicateDescriptor->useAlternativeName();
454+
}
455+
}
408456
}
409457

410458
/**
411459
* Returns the list of method descriptors (and applies the alternative name if needed).
412460
*
413-
* @return MethodDescriptorInterface[]
461+
* @return RelationshipMethodDescriptorInterface[]
414462
*/
415463
public function getMethodDescriptors(): array
416464
{
417465
$directForeignKeyDescriptors = $this->getDirectForeignKeysDescriptors();
418466
$pivotTableDescriptors = $this->getPivotTableDescriptors();
419467

420-
$descriptors = array_merge($directForeignKeyDescriptors, $pivotTableDescriptors);
421-
422-
// Descriptors by method names
423-
$descriptorsByMethodName = [];
424-
425-
foreach ($descriptors as $descriptor) {
426-
$descriptorsByMethodName[$descriptor->getName()][] = $descriptor;
427-
}
428-
429-
foreach ($descriptorsByMethodName as $descriptorsForMethodName) {
430-
if (count($descriptorsForMethodName) > 1) {
431-
foreach ($descriptorsForMethodName as $descriptor) {
432-
$descriptor->useAlternativeName();
433-
}
434-
}
435-
}
436-
437-
return $descriptors;
468+
return array_merge($directForeignKeyDescriptors, $pivotTableDescriptors);
438469
}
439470

440471
public function generateJsonSerialize(): MethodGenerator

src/Utils/DirectForeignKeyMethodDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/**
1919
* Represents a method to get a list of beans from a direct foreign key pointing to our bean.
2020
*/
21-
class DirectForeignKeyMethodDescriptor implements MethodDescriptorInterface
21+
class DirectForeignKeyMethodDescriptor implements RelationshipMethodDescriptorInterface
2222
{
2323
use ForeignKeyAnalyzerTrait;
2424

src/Utils/MethodDescriptorInterface.php

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33

44
namespace TheCodingMachine\TDBM\Utils;
55

6-
use Zend\Code\Generator\MethodGenerator;
7-
86
interface MethodDescriptorInterface
97
{
108
/**
@@ -14,36 +12,8 @@ interface MethodDescriptorInterface
1412
*/
1513
public function getName() : string;
1614

17-
/**
18-
* Returns the name of the class that will be returned by the getter (short name).
19-
*
20-
* @return string
21-
*/
22-
public function getBeanClassName(): string;
23-
2415
/**
2516
* Requests the use of an alternative name for this method.
2617
*/
2718
public function useAlternativeName(): void;
28-
29-
/**
30-
* Returns the code of the method.
31-
*
32-
* @return MethodGenerator[]
33-
*/
34-
public function getCode() : array;
35-
36-
/**
37-
* Returns an array of classes that needs a "use" for this method.
38-
*
39-
* @return string[]
40-
*/
41-
public function getUsedClasses() : array;
42-
43-
/**
44-
* Returns the code to past in jsonSerialize.
45-
*
46-
* @return string
47-
*/
48-
public function getJsonSerializeCode() : string;
4919
}

src/Utils/PivotTableMethodsDescriptor.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
use Zend\Code\Generator\ParameterGenerator;
1818
use function var_export;
1919

20-
class PivotTableMethodsDescriptor implements MethodDescriptorInterface
20+
class PivotTableMethodsDescriptor implements RelationshipMethodDescriptorInterface
2121
{
2222
/**
2323
* @var Table
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace TheCodingMachine\TDBM\Utils;
5+
6+
use Zend\Code\Generator\MethodGenerator;
7+
8+
interface RelationshipMethodDescriptorInterface extends MethodDescriptorInterface
9+
{
10+
/**
11+
* Returns the name of the method to be generated.
12+
*
13+
* @return string
14+
*/
15+
public function getName() : string;
16+
17+
/**
18+
* Returns the name of the class that will be returned by the getter (short name).
19+
*
20+
* @return string
21+
*/
22+
public function getBeanClassName(): string;
23+
24+
/**
25+
* Requests the use of an alternative name for this method.
26+
*/
27+
public function useAlternativeName(): void;
28+
29+
/**
30+
* Returns the code of the method.
31+
*
32+
* @return MethodGenerator[]
33+
*/
34+
public function getCode() : array;
35+
36+
/**
37+
* Returns an array of classes that needs a "use" for this method.
38+
*
39+
* @return string[]
40+
*/
41+
public function getUsedClasses() : array;
42+
43+
/**
44+
* Returns the code to past in jsonSerialize.
45+
*
46+
* @return string
47+
*/
48+
public function getJsonSerializeCode() : string;
49+
}

tests/TDBMAbstractServiceTest.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,7 @@ private static function initSchema(Connection $connection): void
416416

417417
$db->table('artists')
418418
->column('id')->integer()->primaryKey()->autoIncrement()
419+
->column('children')->array()->null() //used to test conflicts with autopivot
419420
->column('name')->string();
420421

421422
$db->table('albums')
@@ -437,11 +438,15 @@ private static function initSchema(Connection $connection): void
437438
->column('track_id')->references('tracks')
438439
->column('artist_id')->references('artists')->comment('@JsonKey("feat") @JsonInclude');
439440

440-
$db->table('artists_relations')
441+
$db->table('artists_relations') //used to test the auto pivot case
441442
->column('id')->integer()->primaryKey()->autoIncrement()
442443
->column('parent_id')->references('artists')
443444
->column('child_id')->references('artists');
444445

446+
$db->table('children') //used to test conflicts with autopivot
447+
->column('id')->integer()->primaryKey()->autoIncrement()
448+
->column('artist_id')->references('artists');
449+
445450
$db->junctionTable('person', 'boats');
446451

447452
$db->table('base_objects')

tests/TDBMDaoGeneratorTest.php

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2008,7 +2008,7 @@ public function testFloydHasOneChild(): void
20082008
{
20092009
$artists = new ArtistDao($this->tdbmService);
20102010
$pinkFloyd = $artists->getById(1);
2011-
$children = $pinkFloyd->getChildren();
2011+
$children = $pinkFloyd->getChildrenByArtistsRelations();
20122012

20132013
$this->assertEquals(1, count($children));
20142014
$this->assertEquals(2, $children[0]->getId());
@@ -2160,4 +2160,13 @@ public function testLazyStopRecursionOnCompositeForeignKey(): void
21602160
$this->assertEquals(1, $json['compositeFkTarget']['id1']);
21612161
$this->assertEquals(1, $json['compositeFkTarget']['id2']);
21622162
}
2163+
2164+
public function testMethodNameConflictsBetweenRegularAndAutoPivotProperties()
2165+
{
2166+
$artist = new ArtistBean('Super');
2167+
$artist->getChildren(); // regular property
2168+
$artist->getChildrenByArtistId(); // one-to-may relationship
2169+
$artist->getChildrenByArtistsRelations(); // auto-pivot relationship
2170+
$this->assertEquals(1, 1);
2171+
}
21632172
}

0 commit comments

Comments
 (0)