From 0aadcc6675f1faccf7a0e2e69d50ddf2abae11b6 Mon Sep 17 00:00:00 2001 From: Samuel Georges Date: Wed, 2 Nov 2016 08:50:15 +1100 Subject: [PATCH] Merge paths and vars when calling widget handler When an AJAX handler is called for a widget, the view paths and specified variables should be merged in to the controller. This sets the appropriate context: 1) Look at the widget first 2) Fall back to the controller Fixes #2432 --- modules/backend/classes/Controller.php | 20 ++++++++++++++++-- modules/system/traits/ViewMaker.php | 29 +++++++++++++++++++------- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/modules/backend/classes/Controller.php b/modules/backend/classes/Controller.php index f8230a40f..62fa762d3 100644 --- a/modules/backend/classes/Controller.php +++ b/modules/backend/classes/Controller.php @@ -512,7 +512,7 @@ class Controller extends Extendable } if (($widget = $this->widget->{$widgetName}) && $widget->methodExists($handlerName)) { - $result = call_user_func_array([$widget, $handlerName], $this->params); + $result = $this->runAjaxHandlerForWidget($widget, $handlerName); return ($result) ?: true; } } @@ -543,7 +543,7 @@ class Controller extends Extendable foreach ((array) $this->widget as $widget) { if ($widget->methodExists($handler)) { - $result = call_user_func_array([$widget, $handler], $this->params); + $result = $this->runAjaxHandlerForWidget($widget, $handlerName); return ($result) ?: true; } } @@ -552,6 +552,22 @@ class Controller extends Extendable return false; } + /** + * Specific code for executing an AJAX handler for a widget. + * This will append the widget view paths to the controller and merge the vars. + * @return mixed + */ + protected function runAjaxHandlerForWidget($widget, $handler) + { + $this->addViewPath($widget->getViewPaths()); + + $result = call_user_func_array([$widget, $handler], $this->params); + + $this->vars = $widget->vars + $this->vars; + + return $result; + } + /** * Returns the controllers public actions. */ diff --git a/modules/system/traits/ViewMaker.php b/modules/system/traits/ViewMaker.php index 0dcecaa7c..00d711a4d 100644 --- a/modules/system/traits/ViewMaker.php +++ b/modules/system/traits/ViewMaker.php @@ -25,7 +25,7 @@ trait ViewMaker public $vars = []; /** - * @var string Specifies a path to the views directory. + * @var string|array Specifies a path to the views directory. */ protected $viewPath; @@ -45,14 +45,29 @@ trait ViewMaker public $suppressLayout = false; /** - * Prepends a path on the available view locations. - * @param string $path + * Prepends a path on the available view path locations. + * @param string|array $path * @return void */ public function addViewPath($path) { $this->viewPath = (array) $this->viewPath; - array_unshift($this->viewPath, $path); + + if (is_array($path)) { + $this->viewPath = array_merge($path, $this->viewPath); + } + else { + array_unshift($this->viewPath, $path); + } + } + + /** + * Returns the active view path locations. + * @return array + */ + public function getViewPaths() + { + return (array) $this->viewPath; } /** @@ -160,9 +175,9 @@ trait ViewMaker } /** - * Locates a file based on it's definition. If the file starts with - * an "at symbol", it will be returned in context of the application base path, - * otherwise it will be returned in context of the view path. + * Locates a file based on its definition. The file name can be prefixed with a + * symbol (~|$) to return in context of the application or plugin base path, + * otherwise it will be returned in context of this object view path. * @param string $fileName File to load. * @param mixed $viewPath Explicitly define a view path. * @return string Full path to the view file.