/** * Loads the controller and initializes it. Runs the pre_controller, * post_controller_constructor, and post_controller events. Triggers * a system.404 event when the route cannot be mapped to a controller. * * This method is benchmarked as controller_setup and controller_execution. * * @return object instance of controller */ public static function &instance() { if (self::$instance === NULL) { Benchmark::start(SYSTEM_BENCHMARK . '_controller_setup'); if (Router::$method[0] === '_') { // Do not allow access to hidden methods Event::run('system.404'); } // Include the Controller file require Router::$controller_path; try { // Start validation of the controller $class = new ReflectionClass(ucfirst(Router::$controller) . '_Controller'); } catch (ReflectionException $e) { // Controller does not exist Event::run('system.404'); } if ($class->isAbstract() or IN_PRODUCTION and $class->getConstant('ALLOW_PRODUCTION') == FALSE) { // Controller is not allowed to run in production Event::run('system.404'); } // Run system.pre_controller Event::run('system.pre_controller'); // Begin benchmark for the controller Benchmark::f_start(ucfirst(Router::$controller) . '_Controller'); // Create a new controller instance $controller = $class->newInstance(); // End benchmark for the controller Benchmark::f_stop(ucfirst(Router::$controller) . '_Controller'); // Controller constructor has been executed Event::run('system.post_controller_constructor'); try { // Load the controller method $method = $class->getMethod(Router::$method); if ($method->isProtected() or $method->isPrivate()) { // Do not attempt to invoke protected methods throw new ReflectionException('protected controller method'); } // Default arguments $arguments = Router::$arguments; } catch (ReflectionException $e) { // Use __call instead $method = $class->getMethod('__call'); // Use arguments in __call format $arguments = array(Router::$method, Router::$arguments); } // Stop the controller setup benchmark Benchmark::stop(SYSTEM_BENCHMARK . '_controller_setup'); // Start the controller execution benchmark Benchmark::start(SYSTEM_BENCHMARK . '_controller_execution'); // Execute the controller method $method->invokeArgs($controller, $arguments); // Controller method has been executed Event::run('system.post_controller'); // Stop the controller execution benchmark Benchmark::stop(SYSTEM_BENCHMARK . '_controller_execution'); } return self::$instance; }