From ffa0dda2049267028f92ec40f986650c6ee52d5f Mon Sep 17 00:00:00 2001 From: Maksim Spirkov <63721828+mspirkov@users.noreply.github.com> Date: Thu, 30 Oct 2025 23:41:32 +0300 Subject: [PATCH] Fix #20658: Add missing generics in `yii\console`, `yii\captcha`, `yii\caching` and `yii\behaviors` namespaces --- framework/CHANGELOG.md | 1 + framework/base/Behavior.php | 3 --- framework/behaviors/AttributeBehavior.php | 4 ++++ .../behaviors/AttributeTypecastBehavior.php | 8 ++++++- framework/behaviors/AttributesBehavior.php | 4 ++++ framework/behaviors/BlameableBehavior.php | 3 +++ .../behaviors/CacheableWidgetBehavior.php | 3 +++ .../behaviors/OptimisticLockBehavior.php | 3 +++ framework/behaviors/SluggableBehavior.php | 3 +++ framework/behaviors/TimestampBehavior.php | 3 +++ framework/caching/CacheInterface.php | 2 ++ framework/captcha/CaptchaValidator.php | 11 +++++++-- framework/console/Controller.php | 24 +++++++++++++++++++ .../controllers/BaseMigrateController.php | 6 ++++- .../console/controllers/MigrateController.php | 6 ++++- phpstan-baseline.neon | 19 ++------------- 16 files changed, 78 insertions(+), 25 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index b4a1c1a5f7..60a6a216b3 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -77,6 +77,7 @@ Yii Framework 2 Change Log - Enh #20650: Add PHPStan/Psalm annotations for `yii\di\Container` (mspirkov) - Bug #20654: Add missing generics in `yii\db` namespace. Fix PHPDoc annotations in `yii\db\ArrayExpression` (mspirkov) - Bug #20651: Add missing generics in `yii\filters` namespace (mspirkov) +- Bug #20658: Add missing generics in `yii\console`, `yii\captcha`, `yii\caching` and `yii\behaviors` namespaces (mspirkov) - Bug #20659: Fix `PHP` `8.5` `null` array offset deprecation warnings in `MariaDB` driver (terabytesoftw) diff --git a/framework/base/Behavior.php b/framework/base/Behavior.php index 53fa8309f9..cb663517e1 100644 --- a/framework/base/Behavior.php +++ b/framework/base/Behavior.php @@ -21,9 +21,6 @@ namespace yii\base; * @since 2.0 * * @template T of Component - * - * @phpstan-property T|null $owner - * @psalm-property T|null $owner */ class Behavior extends BaseObject { diff --git a/framework/behaviors/AttributeBehavior.php b/framework/behaviors/AttributeBehavior.php index c90a8d4d51..facbe85323 100644 --- a/framework/behaviors/AttributeBehavior.php +++ b/framework/behaviors/AttributeBehavior.php @@ -11,6 +11,7 @@ use Closure; use yii\base\Behavior; use yii\base\Event; use yii\db\ActiveRecord; +use yii\db\BaseActiveRecord; /** * AttributeBehavior automatically assigns a specified value to one or multiple attributes of an ActiveRecord @@ -47,6 +48,9 @@ use yii\db\ActiveRecord; * @author Luciano Baraglia * @author Qiang Xue * @since 2.0 + * + * @template T of BaseActiveRecord + * @extends Behavior */ class AttributeBehavior extends Behavior { diff --git a/framework/behaviors/AttributeTypecastBehavior.php b/framework/behaviors/AttributeTypecastBehavior.php index 722d9b48af..7a4e92cd01 100644 --- a/framework/behaviors/AttributeTypecastBehavior.php +++ b/framework/behaviors/AttributeTypecastBehavior.php @@ -108,6 +108,9 @@ use yii\validators\StringValidator; * * @author Paul Klimov * @since 2.0.10 + * + * @template T of Model|BaseActiveRecord + * @extends Behavior */ class AttributeTypecastBehavior extends Behavior { @@ -117,7 +120,10 @@ class AttributeTypecastBehavior extends Behavior public const TYPE_STRING = 'string'; /** - * @var Model|BaseActiveRecord the owner of this behavior. + * @var Model|BaseActiveRecord|null the owner of this behavior. + * + * @phpstan-var T|null + * @psalm-var T|null */ public $owner; /** diff --git a/framework/behaviors/AttributesBehavior.php b/framework/behaviors/AttributesBehavior.php index c3117d883a..26bce08d26 100644 --- a/framework/behaviors/AttributesBehavior.php +++ b/framework/behaviors/AttributesBehavior.php @@ -11,6 +11,7 @@ use Closure; use yii\base\Behavior; use yii\base\Event; use yii\db\ActiveRecord; +use yii\db\BaseActiveRecord; /** * AttributesBehavior automatically assigns values specified to one or multiple attributes of an ActiveRecord @@ -60,6 +61,9 @@ use yii\db\ActiveRecord; * @author Qiang Xue * @author Bogdan Stepanenko * @since 2.0.13 + * + * @template T of BaseActiveRecord + * @extends Behavior */ class AttributesBehavior extends Behavior { diff --git a/framework/behaviors/BlameableBehavior.php b/framework/behaviors/BlameableBehavior.php index 5976b6e219..99fa0e741f 100755 --- a/framework/behaviors/BlameableBehavior.php +++ b/framework/behaviors/BlameableBehavior.php @@ -53,6 +53,9 @@ use yii\db\BaseActiveRecord; * @author Qiang Xue * @author Alexander Kochetov * @since 2.0 + * + * @template T of BaseActiveRecord + * @extends AttributeBehavior */ class BlameableBehavior extends AttributeBehavior { diff --git a/framework/behaviors/CacheableWidgetBehavior.php b/framework/behaviors/CacheableWidgetBehavior.php index 47015849d6..18cb08467f 100644 --- a/framework/behaviors/CacheableWidgetBehavior.php +++ b/framework/behaviors/CacheableWidgetBehavior.php @@ -43,6 +43,9 @@ use yii\di\Instance; * * @author Nikolay Oleynikov * @since 2.0.14 + * + * @template T of Widget + * @extends Behavior */ class CacheableWidgetBehavior extends Behavior { diff --git a/framework/behaviors/OptimisticLockBehavior.php b/framework/behaviors/OptimisticLockBehavior.php index aaaa0ed0bc..9890a81dc0 100644 --- a/framework/behaviors/OptimisticLockBehavior.php +++ b/framework/behaviors/OptimisticLockBehavior.php @@ -61,6 +61,9 @@ use yii\helpers\ArrayHelper; * @author Salem Ouerdani * @since 2.0.16 * @see \yii\db\BaseActiveRecord::optimisticLock() for details on how to enable optimistic lock. + * + * @template T of BaseActiveRecord + * @extends AttributeBehavior */ class OptimisticLockBehavior extends AttributeBehavior { diff --git a/framework/behaviors/SluggableBehavior.php b/framework/behaviors/SluggableBehavior.php index 79acdfee2a..702100622a 100644 --- a/framework/behaviors/SluggableBehavior.php +++ b/framework/behaviors/SluggableBehavior.php @@ -60,6 +60,9 @@ use yii\validators\UniqueValidator; * @author Alexander Kochetov * @author Paul Klimov * @since 2.0 + * + * @template T of BaseActiveRecord + * @extends AttributeBehavior */ class SluggableBehavior extends AttributeBehavior { diff --git a/framework/behaviors/TimestampBehavior.php b/framework/behaviors/TimestampBehavior.php index 6c5de96b7e..301abd68a1 100644 --- a/framework/behaviors/TimestampBehavior.php +++ b/framework/behaviors/TimestampBehavior.php @@ -68,6 +68,9 @@ use yii\db\BaseActiveRecord; * @author Qiang Xue * @author Alexander Kochetov * @since 2.0 + * + * @template T of BaseActiveRecord + * @extends AttributeBehavior */ class TimestampBehavior extends AttributeBehavior { diff --git a/framework/caching/CacheInterface.php b/framework/caching/CacheInterface.php index 51aabf1813..4093534b1f 100644 --- a/framework/caching/CacheInterface.php +++ b/framework/caching/CacheInterface.php @@ -39,6 +39,8 @@ namespace yii\caching; * @author Qiang Xue * @author Dmitry Naumenko * @since 2.0.13. Previous framework versions used abstract class [[yii\caching\Cache]] as interface. + * + * @extends \ArrayAccess */ interface CacheInterface extends \ArrayAccess { diff --git a/framework/captcha/CaptchaValidator.php b/framework/captcha/CaptchaValidator.php index b3aa25ea78..aa75089e04 100644 --- a/framework/captcha/CaptchaValidator.php +++ b/framework/captcha/CaptchaValidator.php @@ -12,6 +12,7 @@ use yii\base\InvalidConfigException; use yii\helpers\Json; use yii\validators\ValidationAsset; use yii\validators\Validator; +use yii\web\Controller; /** * CaptchaValidator validates that the attribute value is the same as the verification code displayed in the CAPTCHA. @@ -67,14 +68,20 @@ class CaptchaValidator extends Validator * Creates the CAPTCHA action object from the route specified by [[captchaAction]]. * @return CaptchaAction the action object * @throws InvalidConfigException + * + * @phpstan-return CaptchaAction + * @psalm-return CaptchaAction */ public function createCaptchaAction() { $ca = Yii::$app->createController($this->captchaAction); if ($ca !== false) { - /** @var \yii\base\Controller $controller */ + /** @var Controller $controller */ list($controller, $actionID) = $ca; - /** @var CaptchaAction|null */ + /** + * @var CaptchaAction|null + * @phpstan-var CaptchaAction|null + */ $action = $controller->createAction($actionID); if ($action !== null) { return $action; diff --git a/framework/console/Controller.php b/framework/console/Controller.php index 177a93fd90..19a27da626 100644 --- a/framework/console/Controller.php +++ b/framework/console/Controller.php @@ -545,6 +545,9 @@ class Controller extends \yii\base\Controller * Returns a one-line short summary describing the specified action. * @param Action $action action to get summary for * @return string a one-line short summary describing the specified action. + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function getActionHelpSummary($action) { @@ -559,6 +562,9 @@ class Controller extends \yii\base\Controller * Returns the detailed help information for the specified action. * @param Action $action action to get help for * @return string the detailed help information for the specified action. + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function getActionHelp($action) { @@ -581,6 +587,9 @@ class Controller extends \yii\base\Controller * * @param Action $action the action instance * @return array the help information of the action arguments + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function getActionArgsHelp($action) { @@ -654,6 +663,9 @@ class Controller extends \yii\base\Controller * * @param Action $action * @return array the help information of the action options + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function getActionOptionsHelp($action) { @@ -709,6 +721,9 @@ class Controller extends \yii\base\Controller /** * @param Action $action * @return \ReflectionFunctionAbstract + * + * @phpstan-param Action $action + * @psalm-param Action $action */ protected function getActionMethodReflection($action) { @@ -727,6 +742,9 @@ class Controller extends \yii\base\Controller * Parses the comment block into tags. * @param \ReflectionClass|\ReflectionProperty|\ReflectionFunctionAbstract $reflection the comment block * @return array the parsed tags + * + * @phpstan-param \ReflectionClass|\ReflectionProperty|\ReflectionFunctionAbstract $reflection + * @psalm-param \ReflectionClass|\ReflectionProperty|\ReflectionFunctionAbstract $reflection */ protected function parseDocCommentTags($reflection) { @@ -755,6 +773,9 @@ class Controller extends \yii\base\Controller * * @param \ReflectionClass|\ReflectionProperty|\ReflectionFunctionAbstract $reflection * @return string + * + * @phpstan-param \ReflectionClass<$this>|\ReflectionProperty|\ReflectionFunctionAbstract $reflection + * @psalm-param \ReflectionClass<$this>|\ReflectionProperty|\ReflectionFunctionAbstract $reflection */ protected function parseDocCommentSummary($reflection) { @@ -771,6 +792,9 @@ class Controller extends \yii\base\Controller * * @param \ReflectionClass|\ReflectionProperty|\ReflectionFunctionAbstract $reflection * @return string + * + * @phpstan-param \ReflectionClass<$this>|\ReflectionProperty|\ReflectionFunctionAbstract $reflection + * @psalm-param \ReflectionClass<$this>|\ReflectionProperty|\ReflectionFunctionAbstract $reflection */ protected function parseDocCommentDetail($reflection) { diff --git a/framework/console/controllers/BaseMigrateController.php b/framework/console/controllers/BaseMigrateController.php index abf712c95d..1304a45a8e 100644 --- a/framework/console/controllers/BaseMigrateController.php +++ b/framework/console/controllers/BaseMigrateController.php @@ -8,6 +8,7 @@ namespace yii\console\controllers; use Yii; +use yii\base\Action; use yii\base\BaseObject; use yii\base\InvalidConfigException; use yii\base\NotSupportedException; @@ -122,9 +123,12 @@ abstract class BaseMigrateController extends Controller /** * This method is invoked right before an action is to be executed (after all possible filters.) * It checks the existence of the [[migrationPath]]. - * @param \yii\base\Action $action the action to be executed. + * @param Action $action the action to be executed. * @throws InvalidConfigException if directory specified in migrationPath doesn't exist and action isn't "create". * @return bool whether the action should continue to be executed. + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function beforeAction($action) { diff --git a/framework/console/controllers/MigrateController.php b/framework/console/controllers/MigrateController.php index 43206e43ac..56c09330db 100644 --- a/framework/console/controllers/MigrateController.php +++ b/framework/console/controllers/MigrateController.php @@ -8,6 +8,7 @@ namespace yii\console\controllers; use Yii; +use yii\base\Action; use yii\db\Connection; use yii\db\Query; use yii\di\Instance; @@ -174,8 +175,11 @@ class MigrateController extends BaseMigrateController /** * This method is invoked right before an action is to be executed (after all possible filters.) * It checks the existence of the [[migrationPath]]. - * @param \yii\base\Action $action the action to be executed. + * @param Action $action the action to be executed. * @return bool whether the action should continue to be executed. + * + * @phpstan-param Action $action + * @psalm-param Action $action */ public function beforeAction($action) { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c7136aa85b..7af0f462c1 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -351,27 +351,12 @@ parameters: path: framework/console/Controller.php - - message: "#^Call to an undefined method yii\\\\base\\\\Component\\:\\:isAttributeChanged\\(\\)\\.$#" - count: 1 - path: framework/behaviors/SluggableBehavior.php - - - - message: "#^Call to an undefined method yii\\\\base\\\\Component\\:\\:formName\\(\\)\\.$#" - count: 1 - path: framework/behaviors/OptimisticLockBehavior.php - - - - message: "#^Access to an undefined property yii\\\\base\\\\Component\\:\\:\\$view\\.$#" - count: 2 - path: framework/behaviors/CacheableWidgetBehavior.php - - - - message: "#^Call to an undefined method yii\\\\base\\\\Model\\:\\:canSetOldAttribute\\(\\)\\.$#" + message: "#^Call to an undefined method T of yii\\\\base\\\\Model\\:\\:canSetOldAttribute\\(\\)\\.$#" count: 1 path: framework/behaviors/AttributeTypecastBehavior.php - - message: "#^Call to an undefined method yii\\\\base\\\\Model\\:\\:setOldAttribute\\(\\)\\.$#" + message: "#^Call to an undefined method T of yii\\\\base\\\\Model\\:\\:setOldAttribute\\(\\)\\.$#" count: 1 path: framework/behaviors/AttributeTypecastBehavior.php