diff options
-rw-r--r-- | core/FrontController.php | 90 | ||||
-rw-r--r-- | core/Http/ControllerResolver.php | 132 |
2 files changed, 140 insertions, 82 deletions
diff --git a/core/FrontController.php b/core/FrontController.php index bd473bba8f..7c3740d93d 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -14,10 +14,9 @@ use Piwik\API\Request; use Piwik\API\ResponseBuilder; use Piwik\Container\StaticContainer; use Piwik\Exception\AuthenticationFailedException; +use Piwik\Http\ControllerResolver; use Piwik\Http\Router; -use Piwik\Plugin\Controller; use Piwik\Plugin\Report; -use Piwik\Plugin\Widgets; use Piwik\Session; /** @@ -110,83 +109,6 @@ class FrontController extends Singleton } } - protected function makeController($module, $action, &$parameters) - { - $container = StaticContainer::getContainer(); - - $controllerClassName = $this->getClassNameController($module); - - // TRY TO FIND ACTION IN CONTROLLER - if (class_exists($controllerClassName)) { - - $class = $this->getClassNameController($module); - /** @var $controller Controller */ - $controller = $container->make($class); - - $controllerAction = $action; - if ($controllerAction === false) { - $controllerAction = $controller->getDefaultAction(); - } - - if (is_callable(array($controller, $controllerAction))) { - - return array($controller, $controllerAction); - } - - if ($action === false) { - $this->triggerControllerActionNotFoundError($module, $controllerAction); - } - - } - - // TRY TO FIND ACTION IN WIDGET - $widget = Widgets::factory($module, $action); - - if (!empty($widget)) { - - $parameters['widgetModule'] = $module; - $parameters['widgetMethod'] = $action; - - return array($container->make('Piwik\Plugins\CoreHome\Controller'), 'renderWidget'); - } - - // TRY TO FIND ACTION IN REPORT - $report = Report::factory($module, $action); - - if (!empty($report)) { - - $parameters['reportModule'] = $module; - $parameters['reportAction'] = $action; - - return array($container->make('Piwik\Plugins\CoreHome\Controller'), 'renderReportWidget'); - } - - if (!empty($action) && Report::PREFIX_ACTION_IN_MENU === substr($action, 0, strlen(Report - ::PREFIX_ACTION_IN_MENU))) { - $reportAction = lcfirst(substr($action, 4)); // menuGetPageUrls => getPageUrls - $report = Report::factory($module, $reportAction); - - if (!empty($report)) { - $parameters['reportModule'] = $module; - $parameters['reportAction'] = $reportAction; - - return array($container->make('Piwik\Plugins\CoreHome\Controller'), 'renderReportMenu'); - } - } - - $this->triggerControllerActionNotFoundError($module, $action); - } - - protected function triggerControllerActionNotFoundError($module, $action) - { - throw new Exception("Action '$action' not found in the module '$module'."); - } - - protected function getClassNameController($module) - { - return "\\Piwik\\Plugins\\$module\\Controller"; - } - /** * Executes the requested plugin controller method and returns the data, capturing anything the * method `echo`s. @@ -195,7 +117,7 @@ class FrontController extends Singleton * of whatever is in the output buffer._ * * @param string $module The name of the plugin whose controller to execute, eg, `'UserCountryMap'`. - * @param string $action The controller action name, eg, `'realtimeMap'`. + * @param string $actionName The controller action name, eg, `'realtimeMap'`. * @param array $parameters Array of parameters to pass to the controller action method. * @return string The `echo`'d data or the return value of the controller action. * @deprecated @@ -586,7 +508,10 @@ class FrontController extends Singleton */ Piwik::postEvent('Request.dispatch', array(&$module, &$action, &$parameters)); - list($controller, $actionToCall) = $this->makeController($module, $action, $parameters); + /** @var ControllerResolver $controllerResolver */ + $controllerResolver = StaticContainer::get('Piwik\Http\ControllerResolver'); + + $controller = $controllerResolver->getController($module, $action, $parameters); /** * Triggered directly before controller actions are dispatched. @@ -601,7 +526,7 @@ class FrontController extends Singleton */ Piwik::postEvent(sprintf('Controller.%s.%s', $module, $action), array(&$parameters)); - $result = call_user_func_array(array($controller, $actionToCall), $parameters); + $result = call_user_func_array($controller, $parameters); /** * Triggered after a controller action is successfully called. @@ -627,6 +552,7 @@ class FrontController extends Singleton * @param array $parameters The arguments passed to the controller action. */ Piwik::postEvent('Request.dispatch.end', array(&$result, $module, $action, $parameters)); + return $result; } diff --git a/core/Http/ControllerResolver.php b/core/Http/ControllerResolver.php new file mode 100644 index 0000000000..253cd8cb9f --- /dev/null +++ b/core/Http/ControllerResolver.php @@ -0,0 +1,132 @@ +<?php +/** + * Piwik - free/libre analytics platform + * + * @link http://piwik.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ + +namespace Piwik\Http; + +use DI\FactoryInterface; +use Exception; +use Piwik\Plugin\Controller; +use Piwik\Plugin\Report; +use Piwik\Plugin\Widgets; +use Piwik\Session; + +/** + * Resolves the controller that will handle the request. + * + * A controller is a PHP callable. + */ +class ControllerResolver +{ + /** + * @var FactoryInterface + */ + private $abstractFactory; + + public function __construct(FactoryInterface $abstractFactory) + { + $this->abstractFactory = $abstractFactory; + } + + /** + * @param string $module + * @param string|null $action + * @param array $parameters + * @throws Exception Controller not found. + * @return callable The controller is a PHP callable. + */ + public function getController($module, $action, array &$parameters) + { + // Controller action + $controllerClass = $this->getControllerClass($module); + if (class_exists($controllerClass)) { + $controller = $this->createPluginController($controllerClass, $action); + if ($controller) { + return $controller; + } + } + + // Widget action + $widget = Widgets::factory($module, $action); + if ($widget) { + return $this->createWidgetController($module, $action, $parameters); + } + + // Report action + $report = Report::factory($module, $action); + if ($report) { + return $this->createReportController($module, $action, $parameters); + } + + // Report menu action + if ($this->isReportMenuAction($action)) { + $controller = $this->createReportMenuController($module, $action, $parameters); + if ($controller) { + return $controller; + } + } + + throw new Exception(sprintf("Action '%s' not found in the module '%s'", $action, $module)); + } + + private function getControllerClass($module) + { + return "Piwik\\Plugins\\$module\\Controller"; + } + + private function createPluginController($controllerClass, $action) + { + /** @var $controller Controller */ + $controller = $this->abstractFactory->make($controllerClass); + + $action = $action ?: $controller->getDefaultAction(); + + if (!is_callable(array($controller, $action))) { + return null; + } + + return array($controller, $action); + } + + private function createWidgetController($module, $action, array &$parameters) + { + $parameters['widgetModule'] = $module; + $parameters['widgetMethod'] = $action; + + return array($this->abstractFactory->make('Piwik\Plugins\CoreHome\Controller'), 'renderWidget'); + } + + private function createReportController($module, $action, array &$parameters) + { + $parameters['reportModule'] = $module; + $parameters['reportAction'] = $action; + + return array($this->abstractFactory->make('Piwik\Plugins\CoreHome\Controller'), 'renderReportWidget'); + } + + private function createReportMenuController($module, $action, array &$parameters) + { + $action = lcfirst(substr($action, 4)); // menuGetPageUrls => getPageUrls + $report = Report::factory($module, $action); + + if ($report) { + $parameters['reportModule'] = $module; + $parameters['reportAction'] = $action; + + return array($this->abstractFactory->make('Piwik\Plugins\CoreHome\Controller'), 'renderReportMenu'); + } + + return null; + } + + private function isReportMenuAction($action) + { + $startsWithMenu = (Report::PREFIX_ACTION_IN_MENU === substr($action, 0, strlen(Report::PREFIX_ACTION_IN_MENU))); + + return !empty($action) && $startsWithMenu; + } +} |