Changeset 3202

Show
Ignore:
Timestamp:
07/23/08 17:58:11 (5 weeks 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