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..9a4bbf3d40d 100644 --- a/phalcon/mvc/dispatcher.zep +++ b/phalcon/mvc/dispatcher.zep @@ -163,6 +163,72 @@ 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 + * $modules = [ + * "frontend" => [ + * "className" => Frontend::class, + * "path" => __DIR__ . "/app/Modules/Frontend/Bootstrap.php", + * "metadata" => [ + * "controllersNamespace" => "App\Frontend\Controllers", + * ], + * ], + * "backend" => [ + * "className" => Backend::class, + * "path" => __DIR__ . "/app/Modules/Backend/Bootstrap.php", + * "metadata" => [ + * "controllersNamespace" => "App\Backend\Controllers", + * ], + * ], + * ]; + * + * $application->registerModules($modules); + * + * // 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($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 */ 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(