diff --git a/demos/init-db.php b/demos/init-db.php index b9d8571535..18eefb828e 100644 --- a/demos/init-db.php +++ b/demos/init-db.php @@ -146,7 +146,7 @@ public function atomic(\Closure $fx) } /** - * @param \Closure(Model): string $outputCallback + * @param \Closure(static): string $outputCallback */ protected function wrapUserActionCallbackPreventModification(Model\UserAction $action, \Closure $outputCallback): void { @@ -169,7 +169,7 @@ protected function wrapUserActionCallbackPreventModification(Model\UserAction $a $action->callback = $callbackBackup; } - return $outputCallback($model->isEntity() && !$model->isLoaded() ? $loadedEntity : $model, ...$args); + return $outputCallback($model->isEntity() && !$model->isLoaded() ? $loadedEntity : $model, ...$args); // @phpstan-ignore-line }; } @@ -198,7 +198,7 @@ protected function initPreventModification(): void /** * Improve testing by using prefixed real field and SQL names. * - * @method (static|null) tryLoad(WrappedId $id = null) remove parentheses around return type once https://github.com/phpstan/phpstan/issues/10548 is fixed + * @method static|null tryLoad(WrappedId $id = null) * @method static load(WrappedId $id) * @method \Traversable getIterator() * @method WrappedId insert(array $row) diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 9a7e99999a..3c18aae495 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -23,6 +23,12 @@ parameters: message: '~^Call to method Atk4\\Ui\\App::callExit\(\) with true will always evaluate to true\.$~' count: 2 + # assign to generic callable property is broken https://github.com/phpstan/phpstan/issues/8964 + - + message: '~^Property Atk4\\Data\\Model\\UserAction::\$(callback|enabled) .*Closure<.+ does not accept .*Closure\(.+\.$~' + path: '*' + count: 2 + # TODO these rules are generated, this ignores should be fixed in the code # for level = 2 - diff --git a/src/Form/Control/Dropdown.php b/src/Form/Control/Dropdown.php index 366ae3dcee..47d8561a3a 100644 --- a/src/Form/Control/Dropdown.php +++ b/src/Form/Control/Dropdown.php @@ -84,7 +84,7 @@ class Dropdown extends Input * ]; * } * - * @var \Closure(Model): array{title: mixed, icon?: mixed}|\Closure(mixed, array-key): array{value: mixed, title: mixed, icon?: mixed} + * @var \Closure(T): array{title: mixed, icon?: mixed}|\Closure(mixed, array-key): array{value: mixed, title: mixed, icon?: mixed} */ public ?\Closure $renderRowFunction = null; @@ -276,8 +276,8 @@ protected function _addCallBackRow($row, $key = null): void $res = ($this->renderRowFunction)($row); $this->_tItem->set('value', $this->getApp()->uiPersistence->typecastAttributeSaveField($this->model->getIdField(), $row->getId())); } else { - $res = ($this->renderRowFunction)($row, $key); // @phpstan-ignore-line https://github.com/phpstan/phpstan/issues/10283#issuecomment-1850438891 - $this->_tItem->set('value', (string) $res['value']); // @phpstan-ignore-line https://github.com/phpstan/phpstan/issues/10283 + $res = ($this->renderRowFunction)($row, $key); + $this->_tItem->set('value', (string) $res['value']); } $this->_tItem->set('title', $res['title']); diff --git a/src/Form/Control/Lookup.php b/src/Form/Control/Lookup.php index b8214a527e..79a1091598 100644 --- a/src/Form/Control/Lookup.php +++ b/src/Form/Control/Lookup.php @@ -42,7 +42,7 @@ class Lookup extends Input * * If left null, then search will be performed on a model's title field * - * @var list|\Closure(Model, string): void|null + * @var list|\Closure(T, string): void|null */ public $search; @@ -54,7 +54,7 @@ class Lookup extends Input * with dependency * Then model of the 'state' field can be limited to states of the currently selected 'country'. * - * @var \Closure(Model, array): void|null + * @var \Closure(T, array): void|null */ public $dependency; @@ -113,7 +113,7 @@ class Lookup extends Input * Define callback for generating the row data * If left empty default callback Lookup::defaultRenderRow is used. * - * @var \Closure($this, Model): array{title: mixed} + * @var \Closure($this, T): array{title: mixed} */ public ?\Closure $renderRowFunction = null; diff --git a/src/Form/Control/Multiline.php b/src/Form/Control/Multiline.php index 57a332e49f..13f953094d 100644 --- a/src/Form/Control/Multiline.php +++ b/src/Form/Control/Multiline.php @@ -171,7 +171,7 @@ class Multiline extends Form\Control * Set during fieldDefinition and apply during renderView() after getValue(). * Must contains callable function and function will receive $model field and value as parameter. * - * @var array + * @var array(T, string): void> */ private array $valuePropsBinding = []; diff --git a/src/Grid.php b/src/Grid.php index 6b5d202dfc..65c3d6da3c 100644 --- a/src/Grid.php +++ b/src/Grid.php @@ -345,9 +345,9 @@ public function jsReload($args = [], $afterSuccess = null, array $apiConfig = [] * Adds a new button into the action column on the right. For Crud this * column will already contain "delete" and "edit" buttons. * - * @param string|array|View $button Label text, object or seed for the Button + * @param string|array|View $button Label text, object or seed for the Button * @param JsExpressionable|JsCallbackSetClosure $action - * @param bool|\Closure(Model): bool $isDisabled + * @param bool|\Closure(T): bool $isDisabled * * @return View */ @@ -395,7 +395,7 @@ private function getActionButtons(): Table\Column\ActionButtons * * @param View|string $view * @param JsExpressionable|JsCallbackSetClosure $action - * @param bool|\Closure(Model): bool $isDisabled + * @param bool|\Closure(T): bool $isDisabled * * @return View */ @@ -499,8 +499,8 @@ public function addPopup($columnName, $popup = null, $icon = 'caret square down' * @param string|array|View $button * @param string $title * @param \Closure(View, mixed): void $callback - * @param array $args extra URL argument for callback - * @param bool|\Closure(Model): bool $isDisabled + * @param array $args extra URL argument for callback + * @param bool|\Closure(T): bool $isDisabled * * @return View */ @@ -526,9 +526,9 @@ private function explodeSelectionValue(string $value): array * Similar to addActionButton but apply to a multiple records selection and display in menu. * When menu item is clicked, $callback is executed. * - * @param string|array|MenuItem $item - * @param \Closure(Js\Jquery, list): JsExpressionable $callback - * @param array $args extra URL argument for callback + * @param string|array|MenuItem $item + * @param \Closure(Jquery, list): JsExpressionable $callback + * @param array $args extra URL argument for callback * * @return View */ diff --git a/src/Panel/Right.php b/src/Panel/Right.php index 724afad87b..d81cd9254d 100644 --- a/src/Panel/Right.php +++ b/src/Panel/Right.php @@ -148,7 +148,7 @@ public function addConfirmation(string $msg, string $title = 'Closing panel!', s * Callback to execute when panel open if dynamic content is set. * Differ the callback execution to the FlyoutContent. * - * @param \Closure(object): void $fx + * @param \Closure(T): void $fx */ public function onOpen(\Closure $fx): void { diff --git a/src/Table/Column/ActionButtons.php b/src/Table/Column/ActionButtons.php index 6c192eb2f0..790181741b 100644 --- a/src/Table/Column/ActionButtons.php +++ b/src/Table/Column/ActionButtons.php @@ -25,7 +25,7 @@ class ActionButtons extends Table\Column /** @var array Stores all the buttons that have been added. */ public $buttons = []; - /** @var array Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */ + /** @var array(T): bool> Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */ protected $isEnabledFxs = []; #[\Override] @@ -41,7 +41,7 @@ protected function init(): void * * @param string|array|View $button * @param JsExpressionable|JsCallbackSetClosure|ExecutorInterface $action - * @param bool|\Closure(Model): bool $isDisabled + * @param bool|\Closure(T): bool $isDisabled * * @return View */ @@ -79,11 +79,11 @@ public function addButton($button, $action = null, string $confirmMsg = '', $isD * load contents through $callback. Will pass a virtual page. * * @param string|array|View $button - * @param string|array $defaults modal title or modal defaults array + * @param string|array $defaults modal title or modal defaults array * @param \Closure(View, mixed): void $callback * @param View $owner * @param array $args - * @param bool|\Closure(Model): bool $isDisabled + * @param bool|\Closure(T): bool $isDisabled * * @return View */ diff --git a/src/Table/Column/ActionMenu.php b/src/Table/Column/ActionMenu.php index 099c866062..67fac95f62 100644 --- a/src/Table/Column/ActionMenu.php +++ b/src/Table/Column/ActionMenu.php @@ -25,7 +25,7 @@ class ActionMenu extends Table\Column /** @var array Menu items collections. */ protected $items = []; - /** @var array Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */ + /** @var array(T): bool> Callbacks as defined in UserAction->enabled for evaluating row-specific if an action is enabled. */ protected $isEnabledFxs = []; /** @var string Dropdown label. */ @@ -55,7 +55,7 @@ public function getTag(string $position, $attr, $value): string * * @param View|string $item * @param JsExpressionable|JsCallbackSetClosure|ExecutorInterface $action - * @param bool|\Closure(Model): bool $isDisabled + * @param bool|\Closure(T): bool $isDisabled * * @return View */ diff --git a/src/Table/Column/Multiformat.php b/src/Table/Column/Multiformat.php index 4ab78af114..4636dcee1b 100644 --- a/src/Table/Column/Multiformat.php +++ b/src/Table/Column/Multiformat.php @@ -14,11 +14,11 @@ */ class Multiformat extends Table\Column { - /** @var \Closure(Model, Field|null): list|Table\Column> Method to execute which will return array of seeds for decorators */ + /** @var \Closure(TModel, TField|null): list|Table\Column> Method to execute which will return array of seeds for decorators */ protected \Closure $decoratorsFx; /** - * @param \Closure(Model, Field|null): list|Table\Column> $decoratorsFx + * @param \Closure(TModel, TField|null): list|Table\Column> $decoratorsFx */ public function __construct(\Closure $decoratorsFx) {