/** * Loads the controller class and instantiate it. * @return object * @throws Exception_Exido_404 * @throws Exception_Exido_403 */ public static function &instance() { // ExidoEngine logo if (Input::instance()->checkGet(EXIDO_LOGO_GUID)) { self::_logo(); } elseif (self::$_instance === null) { try { // Debug log if (self::$log_debug) { self::$log->add('EXIDO_DEBUG_LOG', 'Include controller class: ' . Router::$controller); } // Start validation of the controller include Router::$controller_path; $class = new ReflectionClass(Router::$controller); } catch (Exception_Exido_404 $e) { // Controller does not exist throw new Exception_Exido_404('The requested page %s is not found', array(Router::$controller)); } if ($class->isAbstract() or IN_PRODUCTION and $class->getConstant('ALLOW_PRODUCTION') == false) { // Controller is not allowed to run in production throw new Exception_Exido_403("The controller %s doesn't allowed to run in production", array(Router::$controller)); } // Create a new controller instance self::$_instance = $class->newInstance(); try { // Load the controller method $method = $class->getMethod(Router::$method); // Method exists if (Router::$method[0] === '_') { // Do not allow access to hidden methods throw new Exception_Exido_403("The method %s doesn't allowed to run in production", array(Router::$method)); } if (strstr(Router::$method, 'Controller')) { // Do not allow access to special methods throw new Exception_Exido_403("The method %s doesn't allowed to run directly", array(Router::$method)); } if ($method->isProtected() or $method->isPrivate()) { // Do not attempt to invoke protected methods throw new Exception_Exido_403("The method %s doesn't allowed to run in production as it is protected or private", array(Router::$method)); } // Default arguments $arguments = Router::$arguments; } catch (Exception $e) { // Use __call instead $method = $class->getMethod('__call'); // Use arguments in __call format $arguments = array(Router::$method, Router::$arguments); } $is_before_fails = false; // Execute the "before action" method // If the "before action" returns FALSE controller method not executed if ($class->getMethod('beforeController')->invoke(self::$_instance) === false) { $is_before_fails = true; } else { // Otherwise execute the controller method $method->invokeArgs(self::$_instance, $arguments); } if ($class->getProperty('preventAfterController')->getValue() == null) { // Execute the "after action" method $class->getMethod('afterController')->invoke(self::$_instance); } if ($is_before_fails == false) { // Execute the "pushLayout" method $class->getMethod('pushLayoutController')->invoke(self::$_instance); } } return self::$_instance; }