From 193b65d023f90b77dd71226f5ae1aec8f5e870a8 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 21 May 2017 12:52:18 +0300 Subject: [PATCH 1/3] Added dispatcher::beforeForward event --- CHANGELOG.md | 3 +- phalcon/dispatcher.zep | 7 ++-- phalcon/mvc/dispatcher.zep | 69 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a969f0730c..c573cd3a93d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,8 +16,9 @@ - Added parameters `skip_on_insert`, `skip_on_update` and `allow_empty_string` and fixed a bug for renamed integer columns in `Phalcon\Mvc\Model\MetaData\Strategy\Annotations::getMetaData` - Added way to disable setters in `Phalcon\Mvc\Model::assign` by using `Phalcon\Mvc\Model::setup` or ini option - Added ability to sanitize special characters to `Phalcon\Filter` -- Added a new `Phalcon\Mvc\Model\Binder::findBoundModel` method. Params fetched from cache are being added to `internalCache` class property in `Phalcon\Mvc\Model\Binder::getParamsFromCache`. +- Added a new `Phalcon\Mvc\Model\Binder::findBoundModel` method. Params fetched from cache are being added to `internalCache` class property in `Phalcon\Mvc\Model\Binder::getParamsFromCache` - Added `Phalcon\Mvc\Model\Criteria::createBuilder` to create a query builder from criteria +- Added `dispatcher::beforeForward` event to allow forwarding request to the separated module [#121](https://github.com/phalcon/cphalcon/issues/121), [#12417](https://github.com/phalcon/cphalcon/issues/12417) - Fixed Dispatcher forwarding when handling exception [#11819](https://github.com/phalcon/cphalcon/issues/11819), [#12154](https://github.com/phalcon/cphalcon/issues/12154) - Fixed params view scope for PHP 7 [#12648](https://github.com/phalcon/cphalcon/issues/12648) - Fixed `Phalcon\Mvc\Micro::handle` to prevent attemps to send response twice [#12668](https://github.com/phalcon/cphalcon/pull/12668) diff --git a/phalcon/dispatcher.zep b/phalcon/dispatcher.zep index 2bdd5325334..8a93c11a942 100755 --- a/phalcon/dispatcher.zep +++ b/phalcon/dispatcher.zep @@ -699,17 +699,16 @@ abstract class Dispatcher implements DispatcherInterface, InjectionAwareInterfac } /** - * Forwards the execution flow to another controller/action - * Dispatchers are unique per module. Forwarding between modules is not allowed + * Forwards the execution flow to another controller/action. * - * + * * $this->dispatcher->forward( * [ * "controller" => "posts", * "action" => "index", * ] * ); - * + * * * @param array forward */ diff --git a/phalcon/mvc/dispatcher.zep b/phalcon/mvc/dispatcher.zep index ef02780d8a6..93761ba92f9 100644 --- a/phalcon/mvc/dispatcher.zep +++ b/phalcon/mvc/dispatcher.zep @@ -163,6 +163,75 @@ class Dispatcher extends BaseDispatcher implements DispatcherInterface } } + /** + * Forwards the execution flow to another controller/action. + * + * + * // Registering modules + * $application->registerModules( + * [ + * "frontend" => [ + * "className" => "App\Frontend\Bootstrap", + * "path" => __DIR__ . "/app/Modules/Frontend/Bootstrap.php", + * "metadata" => [ + * // Enable forwarding to other modules + * "controllersNamespace" => "App\Frontend\Controllers", + * // ... + * ], + * ], + * "backend" => [ + * "className" => "App\Backend\Bootstrap", + * "path" => __DIR__ . "/app/Modules/Backend/Bootstrap.php", + * "metadata" => [ + * // Enable forwarding to other modules + * "controllersNamespace" => "App\Backend\Controllers", + * // ... + * ], + * ], + * ] + * ); + * + * // Setting beforeForward listener + * $di->getShared("eventsManager")->attach("dispatch:beforeForward", function($event, $dispatcher, array $forward) { + * if (!empty($forward["module"])) { + * $modulesRegistry = $this->get("modules"); + * + * // Check module in \Phalcon\Registry + * if (!$modulesRegistry->offsetExists($forward["module"])) { + * throw new \Phalcon\Mvc\Dispatcher\Exception("Module {$forward['module']} does not exist."); + * } + * + * // ... + * + * $dispatcher->setModuleName($forward["module"]); + * $dispatcher->setNamespaceName($forward["metadata"]["controllersNamespace"]); + * } + * }); + * + * // Forward + * $this->dispatcher->forward( + * [ + * "module" => "backend", + * "controller" => "posts", + * "action" => "index", + * ] + * ); + * + * + * @param array forward + */ + public function forward(var forward) + { + var eventsManager; + + let eventsManager = this->_eventsManager; + if typeof eventsManager == "object" { + eventsManager->fire("dispatch:beforeForward", this, forward); + } + + parent::forward(forward); + } + /** * Possible controller class name that will be located to dispatch the request */ From beeb87bc5a75472386e188337607bee9f02ac345 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 21 May 2017 13:34:06 +0300 Subject: [PATCH 2/3] Updated docs [ci skip] --- phalcon/mvc/dispatcher.zep | 59 ++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/phalcon/mvc/dispatcher.zep b/phalcon/mvc/dispatcher.zep index 93761ba92f9..9a4bbf3d40d 100644 --- a/phalcon/mvc/dispatcher.zep +++ b/phalcon/mvc/dispatcher.zep @@ -167,46 +167,43 @@ class Dispatcher extends BaseDispatcher implements DispatcherInterface * Forwards the execution flow to another controller/action. * * + * use Phalcon\Events\Event; + * use Phalcon\Mvc\Dispatcher; + * use App\Backend\Bootstrap as Backend; + * use App\Frontend\Bootstrap as Frontend; + * * // Registering modules - * $application->registerModules( - * [ - * "frontend" => [ - * "className" => "App\Frontend\Bootstrap", - * "path" => __DIR__ . "/app/Modules/Frontend/Bootstrap.php", - * "metadata" => [ - * // Enable forwarding to other modules - * "controllersNamespace" => "App\Frontend\Controllers", - * // ... - * ], + * $modules = [ + * "frontend" => [ + * "className" => Frontend::class, + * "path" => __DIR__ . "/app/Modules/Frontend/Bootstrap.php", + * "metadata" => [ + * "controllersNamespace" => "App\Frontend\Controllers", * ], - * "backend" => [ - * "className" => "App\Backend\Bootstrap", - * "path" => __DIR__ . "/app/Modules/Backend/Bootstrap.php", - * "metadata" => [ - * // Enable forwarding to other modules - * "controllersNamespace" => "App\Backend\Controllers", - * // ... - * ], + * ], + * "backend" => [ + * "className" => Backend::class, + * "path" => __DIR__ . "/app/Modules/Backend/Bootstrap.php", + * "metadata" => [ + * "controllersNamespace" => "App\Backend\Controllers", * ], - * ] - * ); + * ], + * ]; * - * // Setting beforeForward listener - * $di->getShared("eventsManager")->attach("dispatch:beforeForward", function($event, $dispatcher, array $forward) { - * if (!empty($forward["module"])) { - * $modulesRegistry = $this->get("modules"); + * $application->registerModules($modules); * - * // Check module in \Phalcon\Registry - * if (!$modulesRegistry->offsetExists($forward["module"])) { - * throw new \Phalcon\Mvc\Dispatcher\Exception("Module {$forward['module']} does not exist."); - * } + * // Setting beforeForward listener + * $eventsManager = $di->getShared("eventsManager"); * - * // ... + * $eventsManager->attach( + * "dispatch:beforeForward", + * function(Event $event, Dispatcher $dispatcher, array $forward) use ($modules) { + * $metadata = $modules[$forward["module"]]["metadata"]; * * $dispatcher->setModuleName($forward["module"]); - * $dispatcher->setNamespaceName($forward["metadata"]["controllersNamespace"]); + * $dispatcher->setNamespaceName($metadata["controllersNamespace"]); * } - * }); + * ); * * // Forward * $this->dispatcher->forward( From 20543bea661ac4d94a1cf9120288cc2814c72cf8 Mon Sep 17 00:00:00 2001 From: Serghei Iakovlev Date: Sun, 21 May 2017 13:45:04 +0300 Subject: [PATCH 3/3] Added test for dispatcher::beforeForward event --- tests/unit/Mvc/DispatcherTest.php | 60 +++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/tests/unit/Mvc/DispatcherTest.php b/tests/unit/Mvc/DispatcherTest.php index 28cf761dca6..4fe0016e39d 100644 --- a/tests/unit/Mvc/DispatcherTest.php +++ b/tests/unit/Mvc/DispatcherTest.php @@ -441,8 +441,6 @@ public function testDispatcherForward2() function () { $di = new Di(); - //$di->set("response", new Response()); - $dispatcher = new Dispatcher(); $dispatcher->setDI($di); @@ -481,6 +479,64 @@ function () { ); } + /** + * Tests beforeForward event + * + * @test + * @issue 212 + * @author Serghei Iakovlev + * @since 2017-05-21 + */ + public function dispatcherBeforeForward() + { + $this->specify( + 'beforeForward event should be fired', + function () { + $di = new Di(); + $manager = new Manager(); + + $modules = [ + 'backend' => [ + 'className' => 'App\Backend\Bootstrap', + 'path' => '/app/Modules/Backend/Bootstrap.php', + 'metadata' => [ + 'controllersNamespace' => 'App\Backend\Controllers', + ], + ], + ]; + + $manager->attach( + 'dispatch:beforeForward', + function (Event $event, Dispatcher $dispatcher, array $forward) use ($modules) { + $metadata = $modules[$forward['module']]['metadata']; + + $dispatcher->setModuleName($forward['module']); + $dispatcher->setNamespaceName($metadata['controllersNamespace']); + } + ); + + $dispatcher = new Dispatcher(); + $dispatcher->setDI($di); + $dispatcher->setEventsManager($manager); + + $di->set('dispatcher', $dispatcher); + + $dispatcher->forward( + [ + 'module' => 'backend', + 'controller' => 'posts', + 'action' => 'index', + ] + ); + + expect($dispatcher->getModuleName())->equals('backend'); + expect($dispatcher->getNamespaceName())->equals('App\Backend\Controllers'); + expect($dispatcher->getControllerName())->equals('posts'); + expect($dispatcher->getActionName())->equals('index'); + } + ); + } + public function testGetControllerClass() { $this->specify(