Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion extension.neon
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,14 @@ services:
tags:
- phpstan.broker.expressionTypeResolverExtension
-
factory: CakeDC\PHPStan\Type\BaseTraitExpressionTypeResolverExtension(Cake\ORM\Locator\LocatorAwareTrait, fetchTable, %s\Model\Table\%sTable, defaultTable)
factory: CakeDC\PHPStan\Type\BaseTraitExpressionTypeResolverExtension(Cake\ORM\Locator\LocatorAwareTrait, fetchTable, %s\Model\Table\%sTable, @CakeDC\PHPStan\Utility\CakeNameRegistry, defaultTable)
tags:
- phpstan.broker.expressionTypeResolverExtension
-
class: CakeDC\PHPStan\Type\TypeFactoryBuildDynamicReturnTypeExtension
tags:
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
-
class: CakeDC\PHPStan\Utility\CakeNameRegistry
arguments:
appNamespace: %cakeDC.appNamespace%
2 changes: 2 additions & 0 deletions rules.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
parameters:
cakeDC:
appNamespace: App
addAssociationExistsTableClassRule: true
addAssociationMatchOptionsTypesRule: true
addBehaviorExistsClassRule: true
Expand All @@ -13,6 +14,7 @@ parameters:
disallowDebugStaticCallRule: true
parametersSchema:
cakeDC: structure([
appNamespace: string()
addAssociationExistsTableClassRule: anyOf(bool(), arrayOf(bool()))
addAssociationMatchOptionsTypesRule: anyOf(bool(), arrayOf(bool()))
addBehaviorExistsClassRule: anyOf(bool(), arrayOf(bool()))
Expand Down
12 changes: 11 additions & 1 deletion src/Rule/Controller/LoadComponentExistsClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ class LoadComponentExistsClassRule extends LoadObjectExistsCakeClassRule
'load',
];

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param \CakeDC\PHPStan\Utility\CakeNameRegistry $cakeNameRegistry
*/
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
}

/**
* @inheritDoc
*/
protected function getTargetClassName(string $name): ?string
{
return CakeNameRegistry::getComponentClassName($name);
return $this->cakeNameRegistry->getComponentClassName($name);
}

/**
Expand Down
12 changes: 11 additions & 1 deletion src/Rule/Mailer/GetMailerExistsClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ class GetMailerExistsClassRule implements Rule
*/
protected string $identifier = 'cake.getMailer.existClass';

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param \CakeDC\PHPStan\Utility\CakeNameRegistry $cakeNameRegistry
*/
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -66,7 +76,7 @@ public function processNode(Node $node, Scope $scope): array
}
$reflection = $callerType->getClassReflection();

if (CakeNameRegistry::getMailerClassName($value->value) !== null) {
if ($this->cakeNameRegistry->getMailerClassName($value->value) !== null) {
return [];
}

Expand Down
12 changes: 11 additions & 1 deletion src/Rule/Model/AddAssociationExistsTableClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,12 +42,22 @@ class AddAssociationExistsTableClassRule extends LoadObjectExistsCakeClassRule
*/
protected array $associationCollectionMethods = ['load'];

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param \CakeDC\PHPStan\Utility\CakeNameRegistry $cakeNameRegistry
*/
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
* @inheritDoc
*/
protected function getTargetClassName(string $name): ?string
{
return CakeNameRegistry::getTableClassName($name);
return $this->cakeNameRegistry->getTableClassName($name);
}

/**
Expand Down
12 changes: 11 additions & 1 deletion src/Rule/Model/AddBehaviorExistsClassRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,22 @@ class AddBehaviorExistsClassRule extends LoadObjectExistsCakeClassRule
'load',
];

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param \CakeDC\PHPStan\Utility\CakeNameRegistry $cakeNameRegistry
*/
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
* @inheritDoc
*/
protected function getTargetClassName(string $name): ?string
{
return CakeNameRegistry::getBehaviorClassName($name);
return $this->cakeNameRegistry->getBehaviorClassName($name);
}

/**
Expand Down
3 changes: 1 addition & 2 deletions src/Traits/BaseCakeRegistryReturnTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

namespace CakeDC\PHPStan\Traits;

use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
Expand Down Expand Up @@ -75,7 +74,7 @@ public function isMethodSupported(MethodReflection $methodReflection): bool
*/
protected function getCakeType(string $baseName): ObjectType
{
$className = CakeNameRegistry::getClassName($baseName, $this->namespaceFormat);
$className = $this->cakeNameRegistry->getClassName($baseName, $this->namespaceFormat);
if ($className !== null) {
return new ObjectType($className);
}
Expand Down
3 changes: 2 additions & 1 deletion src/Type/BaseTraitExpressionTypeResolverExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ public function __construct(
protected string $targetTrait,
protected string $methodName,
protected string $namespaceFormat,
protected CakeNameRegistry $cakeNameRegistry,
protected ?string $propertyDefaultValue = null,
) {
}
Expand Down Expand Up @@ -74,7 +75,7 @@ public function getType(Expr $expr, Scope $scope): ?Type
if ($baseName === null) {
return null;
}
$className = CakeNameRegistry::getClassName($baseName, $this->namespaceFormat);
$className = $this->cakeNameRegistry->getClassName($baseName, $this->namespaceFormat);
if ($className !== null) {
return new ObjectType($className);
}
Expand Down
6 changes: 5 additions & 1 deletion src/Type/ComponentLoadDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Cake\Controller\Component;
use Cake\Controller\Controller;
use CakeDC\PHPStan\Traits\BaseCakeRegistryReturnTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PHPStan\Type\DynamicMethodReturnTypeExtension;

class ComponentLoadDynamicReturnTypeExtension implements DynamicMethodReturnTypeExtension
Expand All @@ -40,14 +41,17 @@ class ComponentLoadDynamicReturnTypeExtension implements DynamicMethodReturnType
*/
protected string $namespaceFormat;

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* TableLocatorDynamicReturnTypeExtension constructor.
*/
public function __construct()
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->className = Controller::class;
$this->methodName = 'loadComponent';
$this->defaultClass = Component::class;
$this->namespaceFormat = '%s\\Controller\Component\\%sComponent';
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
}
}
6 changes: 5 additions & 1 deletion src/Type/ConsoleHelperLoadDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
use Cake\Console\ConsoleIo;
use Cake\Console\Helper;
use CakeDC\PHPStan\Traits\BaseCakeRegistryReturnTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PHPStan\Type\DynamicMethodReturnTypeExtension;
use PHPStan\Type\Type;

Expand All @@ -42,15 +43,18 @@ class ConsoleHelperLoadDynamicReturnTypeExtension implements DynamicMethodReturn
*/
protected string $namespaceFormat;

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* TableLocatorDynamicReturnTypeExtension constructor.
*/
public function __construct()
public function __construct(?CakeNameRegistry $cakeNameRegistry = null)
{
$this->className = ConsoleIo::class;
$this->methodName = 'helper';
$this->defaultClass = Helper::class;
$this->namespaceFormat = '%s\\Command\Helper\\%sHelper';
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/Type/RepositoryEntityDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Cake\Utility\Inflector;
use CakeDC\PHPStan\Traits\BaseCakeRegistryReturnTrait;
use CakeDC\PHPStan\Traits\RepositoryReferenceTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
Expand Down Expand Up @@ -56,14 +57,17 @@ class RepositoryEntityDynamicReturnTypeExtension implements DynamicMethodReturnT
*/
protected string $namespaceFormat;

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param class-string $className The target className.
*/
public function __construct(string $className)
public function __construct(string $className, ?CakeNameRegistry $cakeNameRegistry = null)
{
$this->className = $className;
$this->defaultClass = EntityInterface::class;
$this->namespaceFormat = '%s\\Model\Entity\\%s';
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/Type/RepositoryFirstArgIsTheReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Cake\Datasource\EntityInterface;
use CakeDC\PHPStan\Traits\BaseCakeRegistryReturnTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node\Expr\MethodCall;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\MethodReflection;
Expand Down Expand Up @@ -56,14 +57,17 @@ class RepositoryFirstArgIsTheReturnTypeExtension implements DynamicMethodReturnT
*/
protected string $namespaceFormat;

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* @param class-string $className The target className.
*/
public function __construct(string $className)
public function __construct(string $className, ?CakeNameRegistry $cakeNameRegistry = null)
{
$this->className = $className;
$this->defaultClass = EntityInterface::class;
$this->namespaceFormat = '%s\\Model\Entity\\%s';
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
Comment thread
dereuromark marked this conversation as resolved.
}

/**
Expand Down
6 changes: 5 additions & 1 deletion src/Type/TableLocatorDynamicReturnTypeExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

use Cake\ORM\Table;
use CakeDC\PHPStan\Traits\BaseCakeRegistryReturnTrait;
use CakeDC\PHPStan\Utility\CakeNameRegistry;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Scalar\String_;
use PHPStan\Analyser\Scope;
Expand All @@ -41,18 +42,21 @@ class TableLocatorDynamicReturnTypeExtension implements DynamicMethodReturnTypeE
protected string $defaultClass;
protected string $namespaceFormat;

private readonly CakeNameRegistry $cakeNameRegistry;

/**
* TableLocatorDynamicReturnTypeExtension constructor.
*
* @param class-string $className The target className.
* @param string $methodName The dynamic method to handle.
*/
public function __construct(string $className, string $methodName)
public function __construct(string $className, string $methodName, ?CakeNameRegistry $cakeNameRegistry = null)
{
$this->className = $className;
$this->methodName = $methodName;
$this->defaultClass = Table::class;
$this->namespaceFormat = '%s\\Model\\Table\\%sTable';
$this->cakeNameRegistry = $cakeNameRegistry ?? CakeNameRegistry::instance();
}

/**
Expand Down
35 changes: 25 additions & 10 deletions src/Utility/CakeNameRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,21 @@

class CakeNameRegistry
{
/**
* @param string $appNamespace The application's namespace.
*/
public function __construct(private readonly string $appNamespace)
{
}

/**
* @param string $appNamespace The application's namespace.
*/
public static function instance(string $appNamespace = 'App'): self
{
return new self($appNamespace);
}

/**
* @param string $baseName
* @return array{string|null,string}
Expand All @@ -22,14 +37,14 @@ protected static function pluginSplit(string $baseName): array
* @param array<string>|string $namespaceFormat
* @return string|null
*/
public static function getClassName(string $baseName, string|array $namespaceFormat): ?string
public function getClassName(string $baseName, string|array $namespaceFormat): ?string
{
if (str_contains($baseName, '\\')) {
return class_exists($baseName) ? $baseName : null;
}

[$plugin, $name] = static::pluginSplit($baseName);
$prefixes = $plugin !== null ? [$plugin] : ['App', 'Cake'];
$prefixes = $plugin !== null ? [$plugin] : [$this->appNamespace, 'Cake'];
$namespaceFormat = (array)$namespaceFormat;
foreach ($namespaceFormat as $format) {
foreach ($prefixes as $prefix) {
Expand All @@ -48,9 +63,9 @@ public static function getClassName(string $baseName, string|array $namespaceFor
* @param string $name
* @return string|null
*/
public static function getComponentClassName(string $name): ?string
public function getComponentClassName(string $name): ?string
{
return static::getClassName($name, [
return $this->getClassName($name, [
'%s\\Controller\\Component\\%sComponent',
'%s\\Controller\\Component\\%sComponent',
]);
Expand All @@ -60,9 +75,9 @@ public static function getComponentClassName(string $name): ?string
* @param string $name
* @return string|null
*/
public static function getBehaviorClassName(string $name): ?string
public function getBehaviorClassName(string $name): ?string
{
return static::getClassName($name, [
return $this->getClassName($name, [
'%s\\Model\\Behavior\\%sBehavior',
'%s\\ORM\\Behavior\\%sBehavior',
]);
Expand All @@ -72,9 +87,9 @@ public static function getBehaviorClassName(string $name): ?string
* @param string $name
* @return string|null
*/
public static function getTableClassName(string $name): ?string
public function getTableClassName(string $name): ?string
{
return static::getClassName($name, [
return $this->getClassName($name, [
'%s\\Model\\Table\\%sTable',
]);
}
Expand All @@ -83,9 +98,9 @@ public static function getTableClassName(string $name): ?string
* @param string $name
* @return string|null
*/
public static function getMailerClassName(string $name): ?string
public function getMailerClassName(string $name): ?string
{
return static::getClassName($name, [
return $this->getClassName($name, [
'%s\\Mailer\\%sMailer',
]);
}
Expand Down
Loading
Loading