%PDF- %PDF-
Direktori : /home1/lightco1/upgrade.lightco.com.au/libraries/fof30/Dispatcher/ |
Current File : //home1/lightco1/upgrade.lightco.com.au/libraries/fof30/Dispatcher/Dispatcher.php |
<?php /** * @package FOF * @copyright 2010-2017 Nicholas K. Dionysopoulos / Akeeba Ltd * @license GNU GPL version 2 or later */ namespace FOF30\Dispatcher; use Exception; use FOF30\Container\Container; use FOF30\Controller\Controller; use FOF30\Dispatcher\Exception\AccessForbidden; use FOF30\TransparentAuthentication\TransparentAuthentication; defined('_JEXEC') or die; /** * A generic MVC dispatcher * * @property-read \FOF30\Input\Input $input The input object (magic __get returns the Input from the Container) */ class Dispatcher { /** @var string The name of the default view, in case none is specified */ public $defaultView = 'main'; /** @var array Local cache of the dispatcher configuration */ protected $config = array(); /** @var Container The container we belong to */ protected $container = null; /** @var string The view which will be rendered by the dispatcher */ protected $view = null; /** @var string The layout for rendering the view */ protected $layout = null; /** @var Controller The controller which will be used */ protected $controller = null; /** @var bool Is this user transparently logged in? */ protected $isTransparentlyLoggedIn = false; /** * Public constructor * * The $config array can contain the following optional values: * defaultView string The view to render if none is specified in $input * * Do note that $config is passed to the Controller and through it to the Model and View. Please see these classes * for more information on the configuration variables they accept. * * @param \FOF30\Container\Container $container * @param array $config */ public function __construct(Container $container, array $config = array()) { $this->container = $container; $this->config = $config; if (isset($config['defaultView'])) { $this->defaultView = $config['defaultView']; } // Get the default values for the view and layout names $this->view = $this->input->getCmd('view', null); $this->layout = $this->input->getCmd('layout', null); // Not redundant; you may pass an empty but non-null view which is invalid, so we need the fallback if (empty($this->view)) { $this->view = $this->defaultView; $this->container->input->set('view', $this->view); } } /** * Magic get method. Handles magic properties: * $this->input mapped to $this->container->input * * @param string $name The property to fetch * * @return mixed|null */ public function __get($name) { // Handle $this->input if ($name == 'input') { return $this->container->input; } // Property not found; raise error $trace = debug_backtrace(); trigger_error( 'Undefined property via __get(): ' . $name . ' in ' . $trace[0]['file'] . ' on line ' . $trace[0]['line'], E_USER_NOTICE); return null; } /** * The main code of the Dispatcher. It spawns the necessary controller and * runs it. * * @return void * * @throws AccessForbidden When the access is forbidden */ public function dispatch() { // Load the translations for this component; $this->container->platform->loadTranslations($this->container->componentName); // Perform transparent authentication if ($this->container->platform->getUser()->guest) { $this->transparentAuthenticationLogin(); } // Get the event names (different for CLI) $onBeforeEventName = 'onBeforeDispatch'; $onAfterEventName = 'onAfterDispatch'; if ($this->container->platform->isCli()) { $onBeforeEventName = 'onBeforeDispatchCLI'; $onAfterEventName = 'onAfterDispatchCLI'; } try { $result = $this->triggerEvent($onBeforeEventName); $error = ''; } catch (\Exception $e) { $result = false; $error = $e->getMessage(); } if ($result === false) { if ($this->container->platform->isCli()) { $this->container->platform->setHeader('Status', '403 Forbidden', true); } $this->transparentAuthenticationLogout(); $this->container->platform->showErrorPage(new AccessForbidden); } // Get and execute the controller $view = $this->input->getCmd('view', $this->defaultView); $task = $this->input->getCmd('task', 'default'); if (empty($task)) { $task = 'default'; $this->input->set('task', $task); } try { $this->controller = $this->container->factory->controller($view, $this->config); $status = $this->controller->execute($task); } catch (Exception $e) { $this->container->platform->showErrorPage($e); // Redundant; just to make code sniffers happy return; } if ($status !== false) { try { $this->triggerEvent($onAfterEventName); } catch (\Exception $e) { $status = false; } } if (($status === false)) { if ($this->container->platform->isCli()) { $this->container->platform->setHeader('Status', '403 Forbidden', true); } $this->transparentAuthenticationLogout(); $this->container->platform->showErrorPage(new AccessForbidden); } $this->transparentAuthenticationLogout(); $this->controller->redirect(); } /** * Returns a reference to the Controller object currently in use by the dispatcher * * @return Controller */ public function &getController() { return $this->controller; } /** * Triggers an object-specific event. The event runs both locally –if a suitable method exists– and through the * Joomla! plugin system. A true/false return value is expected. The first false return cancels the event. * * EXAMPLE * Component: com_foobar, Object name: item, Event: onBeforeDispatch, Arguments: array(123, 456) * The event calls: * 1. $this->onBeforeDispatch(123, 456) * 2. Joomla! plugin event onComFoobarDispatcherBeforeDispatch($this, 123, 456) * * @param string $event The name of the event, typically named onPredicateVerb e.g. onBeforeKick * @param array $arguments The arguments to pass to the event handlers * * @return bool */ protected function triggerEvent($event, array $arguments = array()) { $result = true; // If there is an object method for this event, call it if (method_exists($this, $event)) { switch (count($arguments)) { case 0: $result = $this->{$event}(); break; case 1: $result = $this->{$event}($arguments[0]); break; case 2: $result = $this->{$event}($arguments[0], $arguments[1]); break; case 3: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2]); break; case 4: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3]); break; case 5: $result = $this->{$event}($arguments[0], $arguments[1], $arguments[2], $arguments[3], $arguments[4]); break; default: $result = call_user_func_array(array($this, $event), $arguments); break; } } if ($result === false) { return false; } // All other event handlers live outside this object, therefore they need to be passed a reference to this // objects as the first argument. array_unshift($arguments, $this); // If we have an "on" prefix for the event (e.g. onFooBar) remove it and stash it for later. $prefix = ''; if (substr($event, 0, 2) == 'on') { $prefix = 'on'; $event = substr($event, 2); } // Get the component/model prefix for the event $prefix .= 'Com' . ucfirst($this->container->bareComponentName) . 'Dispatcher'; // The event name will be something like onComFoobarItemsBeforeSomething $event = $prefix . $event; // Call the Joomla! plugins $results = $this->container->platform->runPlugins($event, $arguments); if (!empty($results)) { foreach ($results as $result) { if ($result === false) { return false; } } } return true; } /** * Handles the transparent authentication log in */ protected function transparentAuthenticationLogin() { /** @var TransparentAuthentication $transparentAuth */ $transparentAuth = $this->container->transparentAuth; $authInfo = $transparentAuth->getTransparentAuthenticationCredentials(); if (empty($authInfo)) { return; } $this->isTransparentlyLoggedIn = $this->container->platform->loginUser($authInfo); } /** * Handles the transparent authentication log out */ protected function transparentAuthenticationLogout() { if (!$this->isTransparentlyLoggedIn) { return; } /** @var TransparentAuthentication $transparentAuth */ $transparentAuth = $this->container->transparentAuth; if (!$transparentAuth->getLogoutOnExit()) { return; } $this->container->platform->logoutUser(); } }