diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 22f40f05b3..d1d67c35dd 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1248,7 +1248,7 @@ parameters: message: '~^Method Atk4\\Ui\\Callback::setUrlTrigger\(\) has no return typehint specified\.$~' - path: 'src/Callback.php' - message: '~^Method Atk4\\Ui\\Callback::isTriggered\(\) has no return typehint specified\.$~' + message: '~^Method Atk4\\Ui\\Callback::add\(\) has parameter \$args with no typehint specified\.$~' - path: 'src/Card.php' message: '~^Method Atk4\\Ui\\Card::setDataId\(\) has no return typehint specified\.$~' diff --git a/src/Callback.php b/src/Callback.php index ed29b5d498..75d9bf478e 100644 --- a/src/Callback.php +++ b/src/Callback.php @@ -34,6 +34,11 @@ class Callback extends AbstractView /** @var bool Allow this callback to trigger during a reload. */ public $triggerOnReload = true; + public function add($object, $args = null): AbstractView + { + throw new Exception('Callback can NOT contains children'); + } + /** * Initialization. */ @@ -84,7 +89,7 @@ public function terminateJson(AbstractView $view): void /** * Return true if urlTrigger is part of the request. */ - public function isTriggered() + public function isTriggered(): bool { return isset($_GET[self::URL_QUERY_TRIGGER_PREFIX . $this->urlTrigger]); } diff --git a/src/View.php b/src/View.php index 76888d73c3..a1a244205a 100644 --- a/src/View.php +++ b/src/View.php @@ -625,7 +625,7 @@ protected function getRunningCallbackArgs(bool $isTerminated, array $page): arra $isTerminated = true; } - if ($isTerminated) { + if ($isTerminated && $v->isTriggered() && $v->canTrigger()) { $args[Callback::URL_QUERY_TRIGGER_PREFIX . $v->getUrlTrigger()] = $v->getTriggeredValue(); } } diff --git a/tests/CallbackTest.php b/tests/CallbackTest.php index d8e43b9039..9f8a97c538 100644 --- a/tests/CallbackTest.php +++ b/tests/CallbackTest.php @@ -82,14 +82,22 @@ public function testCallbackTrigger(): void public function testViewUrlCallback(): void { $cbApp = \Atk4\Ui\Callback::addTo($this->app, ['urlTrigger' => 'aa']); - $v1 = \Atk4\Ui\View::addTo($cbApp); + $v1 = \Atk4\Ui\View::addTo($this->app); $cb = \Atk4\Ui\Callback::addTo($v1, ['urlTrigger' => 'bb']); - $cb->name = 'bbx'; + $this->simulateCallbackTriggering($cbApp); $this->simulateCallbackTriggering($cb); - $this->assertSame('?__atk_cb_aa=callback&__atk_cbtarget=aa', $cbApp->getUrl()); - $this->assertSame('?__atk_cb_bb=callback&__atk_cbtarget=bb', $cb->getUrl()); + $expectedUrlCbApp = '?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=callback&' . Callback::URL_QUERY_TARGET . '=aa'; + $expectedUrlCb = '?' . Callback::URL_QUERY_TRIGGER_PREFIX . 'aa=1&' . Callback::URL_QUERY_TRIGGER_PREFIX . 'bb=callback&' . Callback::URL_QUERY_TARGET . '=bb'; + $this->assertSame($expectedUrlCbApp, $cbApp->getUrl()); + $this->assertSame($expectedUrlCb, $cb->getUrl()); + + // URL must remain the same when urlTrigger is set but name is changed + $cbApp->name = 'aax'; + $cb->name = 'bbx'; + $this->assertSame($expectedUrlCbApp, $cbApp->getUrl()); + $this->assertSame($expectedUrlCb, $cb->getUrl()); $var = null; $cb->set(function ($x) use (&$var, $v1) { @@ -109,7 +117,7 @@ public function testCallbackNotFiring(): void { $cb = \Atk4\Ui\Callback::addTo($this->app); - // do NOT simulate triggering + // do NOT simulate triggering in this test $var = null; $cb->set(function ($x) use (&$var) {