Show
Ignore:
Timestamp:
07/23/2008 05:58:11 PM (4 months ago)
Author:
Shadowhand
Message:

Changed Kohana::instance() to use Reflection, for cleaner code and more OOP style. Speed is very slightly slower, but the additional robustness makes it worthwhile.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • trunk/system/core/Kohana.php

    r3197 r3202  
    239239                        require Router::$controller_path; 
    240240 
    241                         // Set controller class name 
    242                         $controller = ucfirst(Router::$controller).'_Controller'; 
    243  
    244                         // Make sure the controller class exists 
    245                         class_exists($controller, FALSE) or Event::run('system.404'); 
    246  
    247                         // Production enviroment protection, based on the IN_PRODUCTION flag 
    248                         (IN_PRODUCTION AND constant($controller.'::ALLOW_PRODUCTION') === FALSE) and Event::run('system.404'); 
     241                        try 
     242                        { 
     243                                // Start validation of the controller 
     244                                $class = new ReflectionClass(ucfirst(Router::$controller).'_Controller'); 
     245                        } 
     246                        catch (ReflectionException $e) 
     247                        { 
     248                                // Controller does not exist 
     249                                Event::run('system.404'); 
     250                        } 
     251 
     252                        if (IN_PRODUCTION AND $class->getConstant('ALLOW_PRODUCTION') == FALSE) 
     253                        { 
     254                                // Controller is not allowed to run in production 
     255                                Event::run('system.404'); 
     256                        } 
    249257 
    250258                        // Run system.pre_controller 
    251259                        Event::run('system.pre_controller'); 
    252260 
    253                         // Get the controller methods 
    254                         $methods = array_flip(get_class_methods($controller)); 
    255  
    256                         if (isset($methods['_remap'])) 
     261                        if ($class->hasMethod('_remap')) 
    257262                        { 
    258263                                // Make the arguments routed 
     
    265270                                Router::$method = '_remap'; 
    266271                        } 
    267                         elseif (isset($methods[Router::$method]) AND Router::$method[0] !== '_') 
     272                        elseif (Router::$method[0] != '_') 
    268273                        { 
    269274                                // Use the arguments normally 
    270275                                $arguments = Router::$arguments; 
    271276                        } 
    272                         elseif (isset($methods['_default'])) 
    273                         { 
    274                                 // Make the arguments routed 
    275                                 $arguments = array(Router::$method, Router::$arguments); 
    276  
    277                                 // The method becomes part of the arguments 
    278                                 array_unshift(Router::$arguments, Router::$method); 
    279  
    280                                 // Set the method to _default 
    281                                 Router::$method = '_default'; 
    282                         } 
    283                         else 
    284                         { 
    285                                 // Method was not found, run the system.404 event 
    286                                 Event::run('system.404'); 
    287                         } 
    288  
    289                         // Initialize the controller 
    290                         $controller = new $controller; 
     277 
     278                        if ($class->hasMethod(Router::$method)) 
     279                        { 
     280                                // Start validation of method 
     281                                $method = $class->getMethod(Router::$method); 
     282 
     283                                if ($method->isPrivate() OR $method->isProtected()) 
     284                                { 
     285                                        // Method is invalid 
     286                                        unset($method); 
     287                                } 
     288                        } 
     289 
     290                        if ( ! isset($method)) 
     291                        { 
     292                                if ($class->hasMethod('_default')) 
     293                                { 
     294                                        // Make the arguments routed 
     295                                        $arguments = array(Router::$method, Router::$arguments); 
     296 
     297                                        // The method becomes part of the arguments 
     298                                        array_unshift(Router::$arguments, Router::$method); 
     299 
     300                                        // Set the method to _default 
     301                                        Router::$method = '_default'; 
     302                                } 
     303                                else 
     304                                { 
     305                                        // Method was not found, run the system.404 event 
     306                                        Event::run('system.404'); 
     307                                } 
     308                        } 
     309 
     310                        // Create a new controller instance 
     311                        $controller = $class->newInstance(); 
    291312 
    292313                        // Run system.post_controller_constructor 
    293314                        Event::run('system.post_controller_constructor'); 
    294315 
    295                         // Controller method name, used for calling 
    296                         $method = Router::$method; 
    297  
    298316                        // Stop the controller setup benchmark 
    299317                        Benchmark::stop(SYSTEM_BENCHMARK.'_controller_setup'); 
     
    302320                        Benchmark::start(SYSTEM_BENCHMARK.'_controller_execution'); 
    303321 
    304                         if (empty($arguments)) 
    305                         { 
    306                                 // Call the controller method with no arguments 
    307                                 $controller->$method(); 
    308                         } 
    309                         else 
    310                         { 
    311                                 // Manually call the controller for up to 4 arguments, to increase performance 
    312                                 switch (count($arguments)) 
    313                                 { 
    314                                         case 1: 
    315                                                 $controller->$method($arguments[0]); 
    316                                         break; 
    317                                         case 2: 
    318                                                 $controller->$method($arguments[0], $arguments[1]); 
    319                                         break; 
    320                                         case 3: 
    321                                                 $controller->$method($arguments[0], $arguments[1], $arguments[2]); 
    322                                         break; 
    323                                         case 4: 
    324                                                 $controller->$method($arguments[0], $arguments[1], $arguments[2], $arguments[3]); 
    325                                         break; 
    326                                         default: 
    327                                                 // Resort to using call_user_func_array for many segments 
    328                                                 call_user_func_array(array($controller, $method), $arguments); 
    329                                         break; 
    330                                 } 
    331                         } 
     322                        // Execute the controller 
     323                        $method->invokeArgs($controller, $arguments); 
    332324 
    333325                        // Run system.post_controller