From 7af20992c7db78dee94aeb7e5c7ed9dbcce85c93 Mon Sep 17 00:00:00 2001 From: Patrick Kusebauch Date: Sat, 20 Feb 2016 11:41:58 +0100 Subject: [PATCH 01/13] tests: fixed latte test --- tests/Bridges.Latte/Template.filters.phpt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/Bridges.Latte/Template.filters.phpt b/tests/Bridges.Latte/Template.filters.phpt index 57c339c20..a6a6cca6f 100644 --- a/tests/Bridges.Latte/Template.filters.phpt +++ b/tests/Bridges.Latte/Template.filters.phpt @@ -14,13 +14,13 @@ $engine = new Latte\Engine; $template = new Template($engine); Assert::exception(function () use ($template) { - @$template->length('abc'); -}, 'LogicException', "Filter 'length' is not defined."); + @$template->undefinedFilter('abc'); +}, 'LogicException', "Filter 'undefinedFilter' is not defined."); -$engine->addFilter('length', 'strlen'); +$engine->addFilter('undefinedFilter', 'strlen'); -Assert::same(3, @$template->length('abc')); +Assert::same(3, @$template->undefinedFilter('abc')); Assert::error(function () use ($template) { - $template->length('abc'); + $template->undefinedFilter('abc'); }, E_USER_DEPRECATED, 'Invoking filters on Template object is deprecated, use getLatte()->invokeFilter().'); From e8b02c75063db9044e9a0ce9d75727dd838386d1 Mon Sep 17 00:00:00 2001 From: Patrick Kusebauch Date: Sat, 20 Feb 2016 10:35:51 +0100 Subject: [PATCH 02/13] JsonResponse: sends utf-8 charset [Closes #120] User agents should ignore charset for application/json, this is just workaround for bug in Firefox and Chrome. --- src/Application/Responses/JsonResponse.php | 2 +- tests/Responses/JsonResponse.contentType.phpt | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/Responses/JsonResponse.contentType.phpt diff --git a/src/Application/Responses/JsonResponse.php b/src/Application/Responses/JsonResponse.php index aece0e5b9..832b53660 100644 --- a/src/Application/Responses/JsonResponse.php +++ b/src/Application/Responses/JsonResponse.php @@ -61,7 +61,7 @@ public function getContentType() */ public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse) { - $httpResponse->setContentType($this->contentType); + $httpResponse->setContentType($this->contentType, 'utf-8'); $httpResponse->setExpiration(FALSE); echo Nette\Utils\Json::encode($this->payload); } diff --git a/tests/Responses/JsonResponse.contentType.phpt b/tests/Responses/JsonResponse.contentType.phpt new file mode 100644 index 000000000..b160215a6 --- /dev/null +++ b/tests/Responses/JsonResponse.contentType.phpt @@ -0,0 +1,28 @@ + 'hello world'); + $encoded = json_encode($data); + $jsonResponse = new JsonResponse($data, 'application/json'); + + ob_start(); + $jsonResponse->send(new Http\Request(new Http\UrlScript), $response = new Http\Response); + + Assert::same($encoded, ob_get_clean()); + Assert::same('application/json; charset=utf-8', $response->getHeader('Content-Type')); +}); From 1fde99191bcdd30b9e6cf9563cebde7c3cc083c6 Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 23 Feb 2016 14:18:13 +0100 Subject: [PATCH 03/13] ob_start() is protected against flush when error occurs --- src/Bridges/ApplicationLatte/UIMacros.php | 2 +- src/Bridges/ApplicationLatte/UIRuntime.php | 2 +- src/Bridges/ApplicationTracy/RoutingPanel.php | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Bridges/ApplicationLatte/UIMacros.php b/src/Bridges/ApplicationLatte/UIMacros.php index 497bd27a9..3c0702231 100644 --- a/src/Bridges/ApplicationLatte/UIMacros.php +++ b/src/Bridges/ApplicationLatte/UIMacros.php @@ -76,7 +76,7 @@ public function macroControl(MacroNode $node, PhpWriter $writer) return ($name[0] === '$' ? "if (is_object($name)) \$_l->tmp = $name; else " : '') . '$_l->tmp = $_control->getComponent(' . $name . '); ' . 'if ($_l->tmp instanceof Nette\Application\UI\IRenderable) $_l->tmp->redrawControl(NULL, FALSE); ' - . ($node->modifiers === '' ? "\$_l->tmp->$method($param)" : $writer->write("ob_start(); \$_l->tmp->$method($param); echo %modify(ob_get_clean())")); + . ($node->modifiers === '' ? "\$_l->tmp->$method($param)" : $writer->write("ob_start(function () {}); \$_l->tmp->$method($param); echo %modify(ob_get_clean())")); } diff --git a/src/Bridges/ApplicationLatte/UIRuntime.php b/src/Bridges/ApplicationLatte/UIRuntime.php index a79f91183..14e26df3a 100644 --- a/src/Bridges/ApplicationLatte/UIRuntime.php +++ b/src/Bridges/ApplicationLatte/UIRuntime.php @@ -27,7 +27,7 @@ public static function renderSnippets(UI\Control $control, \stdClass $local, arr if ($name[0] !== '_' || !$control->isControlInvalid((string) substr($name, 1))) { continue; } - ob_start(); + ob_start(function () {}); $function = reset($function); $snippets = $function($local, $params + array('_snippetMode' => TRUE)); $payload->snippets[$id = $control->getSnippetId((string) substr($name, 1))] = ob_get_clean(); diff --git a/src/Bridges/ApplicationTracy/RoutingPanel.php b/src/Bridges/ApplicationTracy/RoutingPanel.php index c0cbd93a6..03652c693 100644 --- a/src/Bridges/ApplicationTracy/RoutingPanel.php +++ b/src/Bridges/ApplicationTracy/RoutingPanel.php @@ -65,7 +65,7 @@ public function __construct(Nette\Application\IRouter $router, Nette\Http\IReque public function getTab() { $this->analyse($this->router); - ob_start(); + ob_start(function () {}); $request = $this->request; require __DIR__ . '/templates/RoutingPanel.tab.phtml'; return ob_get_clean(); @@ -78,7 +78,7 @@ public function getTab() */ public function getPanel() { - ob_start(); + ob_start(function () {}); $request = $this->request; $routers = $this->routers; $source = $this->source; From 83bee45f8c33dae7cc555e931cf0663fe85cd64e Mon Sep 17 00:00:00 2001 From: David Grudl Date: Tue, 23 Feb 2016 17:07:02 +0100 Subject: [PATCH 04/13] tests: fixed compatibility with new Latte --- tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.alt.phtml | 2 +- tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.phtml | 2 +- tests/Bridges.Latte/expected/UIMacros.snippet.alt.phtml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.alt.phtml b/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.alt.phtml index 8cf68b339..d191da14f 100644 --- a/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.alt.phtml +++ b/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.alt.phtml @@ -36,7 +36,7 @@ if (!function_exists($_b->blocks['_outer2'][] = '_%[a-z0-9]+%__outer2')) { funct $_l->extends = empty($_g->extended) && isset($_control) && $_control instanceof Nette\Application\UI\Presenter ? $_control->findLayoutTemplateFile() : NULL; $_g->extended = TRUE; -if ($_l->extends) { ob_start();} +if ($_l->extends) { ob_start(%a?%);} // prolog Nette\Bridges\ApplicationLatte\UIMacros diff --git a/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.phtml b/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.phtml index be1f5056e..70100788b 100644 --- a/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.phtml +++ b/tests/Bridges.Latte/expected/UIMacros.dynamicsnippets.phtml @@ -26,7 +26,7 @@ if (!function_exists($_b->blocks['_outer'][] = '_%[a-z0-9]+%__outer')) { functio $_l->extends = empty($_g->extended) && isset($_control) && $_control instanceof Nette\Application\UI\Presenter ? $_control->findLayoutTemplateFile() : NULL; $_g->extended = TRUE; -if ($_l->extends) { ob_start();} +if ($_l->extends) { ob_start(%a?%);} // prolog Nette\Bridges\ApplicationLatte\UIMacros diff --git a/tests/Bridges.Latte/expected/UIMacros.snippet.alt.phtml b/tests/Bridges.Latte/expected/UIMacros.snippet.alt.phtml index e3d541cdc..16d71f658 100644 --- a/tests/Bridges.Latte/expected/UIMacros.snippet.alt.phtml +++ b/tests/Bridges.Latte/expected/UIMacros.snippet.alt.phtml @@ -33,7 +33,7 @@ if (!function_exists($_b->blocks['_gallery'][] = '_%[a-z0-9]+%__gallery')) { fun $_l->extends = empty($_g->extended) && isset($_control) && $_control instanceof Nette\Application\UI\Presenter ? $_control->findLayoutTemplateFile() : NULL; $_g->extended = TRUE; -if ($_l->extends) { ob_start();} +if ($_l->extends) { ob_start(%a?%);} // prolog Nette\Bridges\ApplicationLatte\UIMacros From 5b3d838c05c805bc7f8bfa18850a03b5b946b4cc Mon Sep 17 00:00:00 2001 From: David Grudl Date: Thu, 3 Mar 2016 03:17:38 +0100 Subject: [PATCH 05/13] RoutingPanel: fixed displaying of empty mask '' --- src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml b/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml index 705bb4362..65a9e5585 100644 --- a/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml +++ b/src/Bridges/ApplicationTracy/templates/RoutingPanel.panel.phtml @@ -59,7 +59,7 @@ use Tracy\Dumper; - + $value): ?> From 37da191c519cabac90cc36b49aa3e33e7dae2721 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2016 15:29:48 +0200 Subject: [PATCH 06/13] tests: Moved MockPresenterFactory to separate file to be reusable across tests --- tests/UI/MockPresenterFactory.php | 12 ++++++++++++ tests/UI/Presenter.link().php7.phpt | 13 +------------ tests/UI/Presenter.link().phpt | 13 +------------ 3 files changed, 14 insertions(+), 24 deletions(-) create mode 100644 tests/UI/MockPresenterFactory.php diff --git a/tests/UI/MockPresenterFactory.php b/tests/UI/MockPresenterFactory.php new file mode 100644 index 000000000..5611616d5 --- /dev/null +++ b/tests/UI/MockPresenterFactory.php @@ -0,0 +1,12 @@ +setScriptPath('/index.php'); diff --git a/tests/UI/Presenter.link().phpt b/tests/UI/Presenter.link().phpt index e9c2be335..26a54be1f 100644 --- a/tests/UI/Presenter.link().phpt +++ b/tests/UI/Presenter.link().phpt @@ -10,6 +10,7 @@ use Tester\Assert; require __DIR__ . '/../bootstrap.php'; +require __DIR__ . '/MockPresenterFactory.php'; class TestControl extends Application\UI\Control @@ -207,18 +208,6 @@ class OtherPresenter extends TestPresenter } -class MockPresenterFactory extends Nette\Object implements Nette\Application\IPresenterFactory -{ - function getPresenterClass(& $name) - { - return str_replace(':', 'Module\\', $name) . 'Presenter'; - } - - function createPresenter($name) - {} -} - - $url = new Http\UrlScript('http://localhost/index.php'); $url->setScriptPath('/index.php'); From 7f8fc8d9d2ec71f6aecbdf0b640825ae9fec325b Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2016 15:37:43 +0200 Subject: [PATCH 07/13] tests: added tests for PresenterComponent:isLinkCurrent() --- ...enterComponent.isLinkCurrent().asserts.php | 167 ++++++++++++++++++ .../PresenterComponent.isLinkCurrent().phpt | 29 +++ 2 files changed, 196 insertions(+) create mode 100644 tests/UI/PresenterComponent.isLinkCurrent().asserts.php create mode 100644 tests/UI/PresenterComponent.isLinkCurrent().phpt diff --git a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php new file mode 100644 index 000000000..53b2d70bb --- /dev/null +++ b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php @@ -0,0 +1,167 @@ +setScriptPath('/index.php'); + + $presenter->injectPrimary( + NULL, + new MockPresenterFactory, + new Application\Routers\SimpleRouter, + new Http\Request($url), + new Http\Response + ); + $presenter->run($request); + + return $presenter->isLinkCurrent($destination, $args); +} + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array()), + 'Test:default', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1)), + 'Test:default', + array() +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1)), + 'Test:default', + array('int' => 2) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:default', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:otherAction', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:default', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:default', + array('bool' => TRUE) +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:default', + array( + 'bool' => TRUE, + 'int' => 1, + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:default', + array( + 'bool' => FALSE, + 'int' => 1, + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:default', + array( + 'bool' => FALSE, + 'int' => 2, + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE, Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:default', + array( + 'bool' => TRUE, + 'int' => 1, + ) +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE, Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:otherAction', + array( + 'bool' => TRUE, + 'int' => 1, + ) +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array()), + 'Test:*', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1)), + 'Test:*', + array() +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET), + 'Test:*', + array('int' => 1) +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:*', + array( + 'int' => 1, + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 2, Application\UI\Presenter::ACTION_KEY => 'otherAction')), + 'Test:*', + array( + 'int' => 1, + ) +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + 'Test:default', + array() +)); + +Assert::true(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + 'signal!', + array() +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + 'otherSignal!', + array() +)); diff --git a/tests/UI/PresenterComponent.isLinkCurrent().phpt b/tests/UI/PresenterComponent.isLinkCurrent().phpt new file mode 100644 index 000000000..ec2e49be1 --- /dev/null +++ b/tests/UI/PresenterComponent.isLinkCurrent().phpt @@ -0,0 +1,29 @@ + Date: Fri, 1 Apr 2016 21:49:23 +0200 Subject: [PATCH 08/13] PresenterFactory: added possibility to configure mapping via array; thanks @achse [Closes #101][Closes #119] --- src/Application/PresenterFactory.php | 12 +++++-- ...PresenterFactory.formatPresenterClass.phpt | 31 +++++++++++++++++++ 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Application/PresenterFactory.php b/src/Application/PresenterFactory.php index 97a828a3b..f67474ae8 100644 --- a/src/Application/PresenterFactory.php +++ b/src/Application/PresenterFactory.php @@ -99,10 +99,16 @@ public function getPresenterClass(& $name) public function setMapping(array $mapping) { foreach ($mapping as $module => $mask) { - if (!preg_match('#^\\\\?([\w\\\\]*\\\\)?(\w*\*\w*?\\\\)?([\w\\\\]*\*\w*)\z#', $mask, $m)) { - throw new Nette\InvalidStateException("Invalid mapping mask '$mask'."); + if (is_string($mask)) { + if (!preg_match('#^\\\\?([\w\\\\]*\\\\)?(\w*\*\w*?\\\\)?([\w\\\\]*\*\w*)\z#', $mask, $m)) { + throw new Nette\InvalidStateException("Invalid mapping mask '$mask'."); + } + $this->mapping[$module] = array($m[1], $m[2] ?: '*Module\\', $m[3]); + } elseif (is_array($mask) && count($mask) === 3) { + $this->mapping[$module] = array($mask[0] ? $mask[0] . '\\' : '', $mask[1] . '\\', $mask[2]); + } else { + throw new Nette\InvalidStateException("Invalid mapping mask for module $module."); } - $this->mapping[$module] = array($m[1], $m[2] ?: '*Module\\', $m[3]); } return $this; } diff --git a/tests/Application/PresenterFactory.formatPresenterClass.phpt b/tests/Application/PresenterFactory.formatPresenterClass.phpt index ef18fbbd6..cfbc0103c 100644 --- a/tests/Application/PresenterFactory.formatPresenterClass.phpt +++ b/tests/Application/PresenterFactory.formatPresenterClass.phpt @@ -49,3 +49,34 @@ test(function () { Assert::same('My\App\BarPresenter', $factory->formatPresenterClass('Foo3:Bar')); Assert::same('My\App\BarModule\BazPresenter', $factory->formatPresenterClass('Foo3:Bar:Baz')); }); + + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping(array( + '*' => array('App', 'Module\*', 'Presenter\*'), + )); + Assert::same('App\Module\Foo\Presenter\Bar', $factory->formatPresenterClass('Foo:Bar')); + Assert::same('App\Module\Universe\Module\Foo\Presenter\Bar', $factory->formatPresenterClass('Universe:Foo:Bar')); +}); + + +test(function () { + $factory = new PresenterFactory; + $factory->setMapping(array( + '*' => array('', '*', '*'), + )); + Assert::same('Module\Foo\Bar', $factory->formatPresenterClass('Module:Foo:Bar')); +}); + + +Assert::exception( + function () { + $factory = new PresenterFactory; + $factory->setMapping(array( + '*' => array('*', '*'), + )); + }, + 'Nette\InvalidStateException', + 'Invalid mapping mask for module *.' +); From 9859b394fdbe6c43aae53caf0afd22f0db9efa6e Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2016 18:53:02 +0200 Subject: [PATCH 09/13] tests: isLinkCurrent tests must run presenter with all required parameters --- ...enterComponent.isLinkCurrent().asserts.php | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php index 53b2d70bb..5893d3b3c 100644 --- a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php +++ b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php @@ -28,19 +28,13 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar } Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array()), - 'Test:default', - array() -)); - -Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array('int' => 1)), + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), 'Test:default', array() )); Assert::false(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array('int' => 1)), + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), 'Test:default', array('int' => 2) )); @@ -57,12 +51,6 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar array() )); -Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), - 'Test:default', - array() -)); - Assert::true(callIsLinkCurrent( new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), 'Test:default', @@ -115,21 +103,27 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar )); Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array()), + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), 'Test:*', array() )); +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE)), + 'Test:*', + array('float' => 1.0) +)); + Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array('int' => 1)), + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE, 'float' => 1.0)), 'Test:*', - array() + array('float' => 1.0) )); Assert::false(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET), + new Application\Request('Test', Http\Request::GET, array('int' => 1, 'bool' => TRUE, 'float' => 1.0)), 'Test:*', - array('int' => 1) + array('float' => 2.0) )); Assert::true(callIsLinkCurrent( @@ -149,19 +143,31 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar )); Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + 'int' => 1, + 'bool' => TRUE, + )), 'Test:default', array() )); Assert::true(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + 'int' => 1, + 'bool' => TRUE, + )), 'signal!', array() )); Assert::false(callIsLinkCurrent( - new Application\Request('Test', Http\Request::GET, array(Application\UI\Presenter::SIGNAL_KEY => 'signal')), + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + 'int' => 1, + 'bool' => TRUE, + )), 'otherSignal!', array() )); From 4814045afffceacc353dbb8a3625522bcf8ba5cd Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2016 19:30:26 +0200 Subject: [PATCH 10/13] tests: specify isLinkCurrent behavior for conflicting action and signal between destination string and args --- ...enterComponent.isLinkCurrent().asserts.php | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php index 5893d3b3c..13fcccee6 100644 --- a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php +++ b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php @@ -171,3 +171,55 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar 'otherSignal!', array() )); + + +// conflicting action in destination string and args +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::ACTION_KEY => 'default', + 'int' => 1, + 'bool' => TRUE, + )), + 'Test:default', + array( + Application\UI\Presenter::ACTION_KEY => 'otherAction', + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::ACTION_KEY => 'default', + 'int' => 1, + 'bool' => TRUE, + )), + 'Test:otherAction', + array( + Application\UI\Presenter::ACTION_KEY => 'default', + ) +)); + + +// conflicting signal in destination string and args +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + 'int' => 1, + 'bool' => TRUE, + )), + 'signal!', + array( + Application\UI\Presenter::SIGNAL_KEY => 'otherSignal', + ) +)); + +Assert::false(callIsLinkCurrent( + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + 'int' => 1, + 'bool' => TRUE, + )), + 'otherSignal!', + array( + Application\UI\Presenter::SIGNAL_KEY => 'signal', + ) +)); From a6daabb987b9ac900f907bd59fce98447527e585 Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 28 Mar 2016 19:59:05 +0200 Subject: [PATCH 11/13] tests: isLinkCurrent for nested components --- ...enterComponent.isLinkCurrent().asserts.php | 117 +++++++++++++++++- .../PresenterComponent.isLinkCurrent().phpt | 13 ++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php index 13fcccee6..07e60ad82 100644 --- a/tests/UI/PresenterComponent.isLinkCurrent().asserts.php +++ b/tests/UI/PresenterComponent.isLinkCurrent().asserts.php @@ -11,7 +11,16 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $args) { $presenter = new TestPresenter; + return callIsComponentLinkCurrent($presenter, $presenter, $request, $destination, $args); +} +function callIsComponentLinkCurrent( + Application\UI\Presenter $presenter, + Application\UI\PresenterComponent $component, + Application\Request $request, + $destination, + array $args +) { $url = new Http\UrlScript('http://localhost/index.php'); $url->setScriptPath('/index.php'); @@ -24,7 +33,7 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar ); $presenter->run($request); - return $presenter->isLinkCurrent($destination, $args); + return $component->isLinkCurrent($destination, $args); } Assert::true(callIsLinkCurrent( @@ -223,3 +232,109 @@ function callIsLinkCurrent(Application\Request $request, $destination, array $ar Application\UI\Presenter::SIGNAL_KEY => 'signal', ) )); + + +// signal for nested component +$testPresenter = new TestPresenter; +$testControl = new TestControl; +$testPresenter['test'] = $testControl; +Assert::true(callIsComponentLinkCurrent( + $testPresenter, + $testControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-click', + 'int' => 1, + 'bool' => TRUE, + )), + 'click!', + array() +)); + +$testPresenter = new TestPresenter; +$testControl = new TestControl; +$testPresenter['test'] = $testControl; +Assert::false(callIsComponentLinkCurrent( + $testPresenter, + $testControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-click', + 'int' => 1, + 'bool' => TRUE, + )), + 'otherSignal!', + array() +)); + +$testPresenter = new TestPresenter; +$testControl = new TestControl; +$testPresenter['test'] = $testControl; +Assert::true(callIsComponentLinkCurrent( + $testPresenter, + $testControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-click', + 'int' => 1, + 'bool' => TRUE, + 'test-x' => 1, + )), + 'click!', + array( + 'x' => 1, + ) +)); + +$testPresenter = new TestPresenter; +$testControl = new TestControl; +$testPresenter['test'] = $testControl; +Assert::false(callIsComponentLinkCurrent( + $testPresenter, + $testControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-click', + 'int' => 1, + 'bool' => TRUE, + 'test-x' => 1, + )), + 'click!', + array( + 'x' => 2, + ) +)); + +$testPresenter = new TestPresenter; +$testControlWithAnotherTestControl = new TestControl; +$testPresenter['test'] = $testControlWithAnotherTestControl; +$testControlWithAnotherTestControl['test'] = new TestControl; +Assert::true(callIsComponentLinkCurrent( + $testPresenter, + $testControlWithAnotherTestControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-test-click', + 'int' => 1, + 'bool' => TRUE, + 'test-test-x' => 1, + )), + 'test:click!', + array( + 'x' => 1, + ) +)); + +$testPresenter = new TestPresenter; +$testControlWithAnotherTestControl = new TestControl; +$testPresenter['test'] = $testControlWithAnotherTestControl; +$testControlWithAnotherTestControl['test'] = new TestControl; +Assert::false(callIsComponentLinkCurrent( + $testPresenter, + $testControlWithAnotherTestControl, + new Application\Request('Test', Http\Request::GET, array( + Application\UI\Presenter::SIGNAL_KEY => 'test-test-click', + 'int' => 1, + 'bool' => TRUE, + 'test-test-x' => 1, + )), + 'test:click!', + array( + 'x' => 2, + ) +)); diff --git a/tests/UI/PresenterComponent.isLinkCurrent().phpt b/tests/UI/PresenterComponent.isLinkCurrent().phpt index ec2e49be1..1b4f986a7 100644 --- a/tests/UI/PresenterComponent.isLinkCurrent().phpt +++ b/tests/UI/PresenterComponent.isLinkCurrent().phpt @@ -26,4 +26,17 @@ class TestPresenter extends Application\UI\Presenter } +class TestControl extends Application\UI\Control +{ + + public function handleClick($x, $y) + { + } + + public function handleOtherSignal() + { + } + +} + require __DIR__ . '/PresenterComponent.isLinkCurrent().asserts.php'; From c292b85089f91fcfeff4b0e42794cb49cff4626f Mon Sep 17 00:00:00 2001 From: David Grudl Date: Sat, 2 Apr 2016 18:17:57 +0200 Subject: [PATCH 12/13] Presenter: isLinkCurrent is compatible with PHP 7 typehints [Closes #126] --- src/Application/UI/Presenter.php | 13 +++--- ...esenterComponent.isLinkCurrent().php7.phpt | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 tests/UI/PresenterComponent.isLinkCurrent().php7.phpt diff --git a/src/Application/UI/Presenter.php b/src/Application/UI/Presenter.php index ab4031a58..3cabb6920 100644 --- a/src/Application/UI/Presenter.php +++ b/src/Application/UI/Presenter.php @@ -873,7 +873,7 @@ protected function createRequest($component, $destination, array $args, $mode) throw new InvalidLinkException("Unknown signal '$signal', missing handler {$reflection->getName()}::$method()"); } // convert indexed parameters to named - self::argsToParams(get_class($component), $method, $args); + self::argsToParams(get_class($component), $method, $args, array(), $mode === 'test'); } // counterpart of IStatePersistent @@ -914,12 +914,8 @@ protected function createRequest($component, $destination, array $args, $mode) if (array_key_exists(0, $args)) { throw new InvalidLinkException("Unable to pass parameters to action '$presenter:$action', missing corresponding method."); } - - } elseif ($destination === 'this') { - self::argsToParams($presenterClass, $method, $args, $this->params); - } else { - self::argsToParams($presenterClass, $method, $args); + self::argsToParams($presenterClass, $method, $args, $destination === 'this' ? $this->params : array(), $mode === 'test'); } // counterpart of IStatePersistent @@ -1003,11 +999,12 @@ protected function createRequest($component, $destination, array $args, $mode) * @param string method name * @param array arguments * @param array supplemental arguments + * @param bool prevents 'Missing parameter' exception * @return void * @throws InvalidLinkException * @internal */ - public static function argsToParams($class, $method, & $args, $supplemental = array()) + public static function argsToParams($class, $method, & $args, $supplemental = array(), $ignoreMissing = FALSE) { $i = 0; $rm = new \ReflectionMethod($class, $method); @@ -1028,7 +1025,7 @@ public static function argsToParams($class, $method, & $args, $supplemental = ar } if (!isset($args[$name])) { - if ($param->isDefaultValueAvailable() || $type === 'NULL' || $type === 'array' || $isClass) { + if ($param->isDefaultValueAvailable() || $type === 'NULL' || $type === 'array' || $isClass || $ignoreMissing) { continue; } throw new InvalidLinkException("Missing parameter \$$name required by $class::{$rm->getName()}()"); diff --git a/tests/UI/PresenterComponent.isLinkCurrent().php7.phpt b/tests/UI/PresenterComponent.isLinkCurrent().php7.phpt new file mode 100644 index 000000000..2a2c7defc --- /dev/null +++ b/tests/UI/PresenterComponent.isLinkCurrent().php7.phpt @@ -0,0 +1,43 @@ + Date: Wed, 9 Mar 2016 01:26:30 +0000 Subject: [PATCH 13/13] RouteList: added warmupCache() --- src/Application/Routers/RouteList.php | 40 +++++++++++-------- .../ApplicationDI/RoutingExtension.php | 8 +++- 2 files changed, 30 insertions(+), 18 deletions(-) diff --git a/src/Application/Routers/RouteList.php b/src/Application/Routers/RouteList.php index 4c1adbbf3..878913915 100644 --- a/src/Application/Routers/RouteList.php +++ b/src/Application/Routers/RouteList.php @@ -55,22 +55,7 @@ public function match(Nette\Http\IRequest $httpRequest) public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\Url $refUrl) { if ($this->cachedRoutes === NULL) { - $routes = array(); - $routes['*'] = array(); - - foreach ($this as $route) { - $presenters = $route instanceof Route && is_array($tmp = $route->getTargetPresenters()) - ? $tmp : array_keys($routes); - - foreach ($presenters as $presenter) { - if (!isset($routes[$presenter])) { - $routes[$presenter] = $routes['*']; - } - $routes[$presenter][] = $route; - } - } - - $this->cachedRoutes = $routes; + $this->warmupCache(); } if ($this->module) { @@ -98,6 +83,29 @@ public function constructUrl(Nette\Application\Request $appRequest, Nette\Http\U } + /** @internal */ + public function warmupCache() + { + $routes = array(); + $routes['*'] = array(); + + foreach ($this as $route) { + $presenters = $route instanceof Route && is_array($tmp = $route->getTargetPresenters()) + ? $tmp + : array_keys($routes); + + foreach ($presenters as $presenter) { + if (!isset($routes[$presenter])) { + $routes[$presenter] = $routes['*']; + } + $routes[$presenter][] = $route; + } + } + + $this->cachedRoutes = $routes; + } + + /** * Adds the router. * @param mixed diff --git a/src/Bridges/ApplicationDI/RoutingExtension.php b/src/Bridges/ApplicationDI/RoutingExtension.php index ea594d146..93f7e0e55 100644 --- a/src/Bridges/ApplicationDI/RoutingExtension.php +++ b/src/Bridges/ApplicationDI/RoutingExtension.php @@ -68,13 +68,17 @@ public function afterCompile(Nette\PhpGenerator\ClassType $class) if (!empty($this->config['cache'])) { $method = $class->getMethod(Nette\DI\Container::getMethodName($this->prefix('router'))); try { - $router = serialize(eval($method->getBody())); + $router = eval($method->getBody()); + if ($router instanceof Nette\Application\Routers\RouteList) { + $router->warmupCache(); + } + $s = serialize($router); } catch (\Throwable $e) { throw new Nette\DI\ServiceCreationException('Unable to cache router due to error: ' . $e->getMessage(), 0, $e); } catch (\Exception $e) { throw new Nette\DI\ServiceCreationException('Unable to cache router due to error: ' . $e->getMessage(), 0, $e); } - $method->setBody('return unserialize(?);', array($router)); + $method->setBody('return unserialize(?);', array($s)); } }