Skip to content

Commit 8d8463f

Browse files
committed
Fix up Reflection.
1 parent a96c5f2 commit 8d8463f

File tree

3 files changed

+55
-15
lines changed

3 files changed

+55
-15
lines changed

src/Method/AssociationTableMixinClassReflectionExtension.php

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,23 @@ protected function getTableReflection(): ClassReflection
4848
*/
4949
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
5050
{
51-
// magic findBy* method
52-
if ($classReflection->is(Table::class) && preg_match('/^find(?:\w+)?By/', $methodName) > 0) {
53-
return true;
51+
// Handle Table classes
52+
if ($classReflection->is(Table::class)) {
53+
if ($classReflection->hasNativeMethod($methodName)) {
54+
return false; // Let the native method be used
55+
}
56+
// magic findBy* and findAllBy* methods - available on ALL table classes
57+
if (preg_match('/^find(All)?By/', $methodName) === 1) {
58+
return true;
59+
}
5460
}
5561

5662
if (!$classReflection->is(Association::class)) {
5763
return false;
5864
}
5965

60-
// magic findBy* method on Association
61-
if (preg_match('/^find(?:\w+)?By/', $methodName) > 0) {
66+
// For associations, provide magic find(All)?By methods
67+
if (preg_match('/^find(All)?By/', $methodName) === 1) {
6268
return true;
6369
}
6470

@@ -72,17 +78,19 @@ public function hasMethod(ClassReflection $classReflection, string $methodName):
7278
*/
7379
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
7480
{
75-
// magic findBy* method
76-
if ($classReflection->is(Table::class) && preg_match('/^find(?:\w+)?By/', $methodName) > 0) {
77-
return new TableFindByPropertyMethodReflection($methodName, $classReflection);
81+
// Handle Table classes
82+
if ($classReflection->is(Table::class)) {
83+
if ($classReflection->hasNativeMethod($methodName)) {
84+
return $classReflection->getNativeMethod($methodName);
85+
}
86+
// magic findBy* and findAllBy* methods
87+
if (preg_match('/^find(All)?By/', $methodName) === 1) {
88+
return new TableFindByPropertyMethodReflection($methodName, $classReflection);
89+
}
7890
}
7991

80-
// magic findBy* method on Association
81-
$associationReflection = $this->reflectionProvider->getClass(Association::class);
82-
if (
83-
$classReflection->isSubclassOfClass($associationReflection)
84-
&& preg_match('/^find(?:\w+)?By/', $methodName) > 0
85-
) {
92+
// For associations, handle magic find(All)?By methods
93+
if (preg_match('/^find(All)?By/', $methodName) === 1) {
8694
return new TableFindByPropertyMethodReflection($methodName, $this->getTableReflection());
8795
}
8896

src/Method/TableFindByPropertyMethodReflection.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,15 @@ public function hasSideEffects(): TrinaryLogic
210210
protected function getParams(string $method): array
211211
{
212212
$method = Inflector::underscore($method);
213-
$fields = substr($method, 8);
213+
// Extract the part after "find" and before "_by"
214+
// Handles: findBy, findAllBy, findOrCreateBy, etc.
215+
if (preg_match('/^find(?:_\w+)?_by_(.+)$/', $method, $matches) === 1) {
216+
$fields = $matches[1];
217+
} else {
218+
// Fallback for simple cases
219+
$fields = substr($method, 8);
220+
}
221+
214222
if (str_contains($fields, '_and_')) {
215223
return explode('_and_', $fields);
216224
}

tests/test_app/Model/Table/VeryCustomize00009ArticlesTable.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,11 @@ public function fixArticle($article)
5252
$article = $this->findByTitleAndActive('sample', true)->first();
5353
$article->set('title', 'sample two');
5454

55+
// Test actual (non-magic) findOrCreateBySku method with specific signature (issue #55)
56+
// When called directly on the table (not through association), PHPStan should use the native method
57+
$entityOrCreate = $this->findOrCreateBySku('TEST-SKU', 'Test Value');
58+
$entityOrCreate->set('title', 'Updated Title');
59+
5560
return true;
5661
}
5762

@@ -69,4 +74,23 @@ public function newSample()
6974
],
7075
);
7176
}
77+
78+
/**
79+
* Custom non-magic findOrCreateBySku method with specific signature
80+
*
81+
* @param string $sku
82+
* @param string $foo
83+
* @return \Cake\Datasource\EntityInterface
84+
*/
85+
public function findOrCreateBySku(string $sku, string $foo)
86+
{
87+
/** @var \Cake\ORM\Entity|null $entity */
88+
$entity = $this->findBySku($sku)->first();
89+
if ($entity === null) {
90+
$entity = $this->newEntity(['sku' => $sku, 'foo' => $foo]);
91+
$entity = $this->saveOrFail($entity);
92+
}
93+
94+
return $entity;
95+
}
7296
}

0 commit comments

Comments
 (0)