dispatcher.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: dispatcher_8php-source.html 675 2008-12-26 00:27:14Z gwoo $ */
00003 /**
00004  * Dispatcher takes the URL information, parses it for paramters and
00005  * tells the involved controllers what to do.
00006  *
00007  * This is the heart of Cake's operation.
00008  *
00009  * PHP versions 4 and 5
00010  *
00011  * CakePHP(tm) : Rapid Development Framework <http://www.cakephp.org/>
00012  * Copyright 2005-2008, Cake Software Foundation, Inc.
00013  *                              1785 E. Sahara Avenue, Suite 490-204
00014  *                              Las Vegas, Nevada 89104
00015  *
00016  * Licensed under The MIT License
00017  * Redistributions of files must retain the above copyright notice.
00018  *
00019  * @filesource
00020  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00021  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00022  * @package         cake
00023  * @subpackage      cake.cake
00024  * @since           CakePHP(tm) v 0.2.9
00025  * @version         $Revision: 675 $
00026  * @modifiedby      $LastChangedBy: gwoo $
00027  * @lastmodified    $Date: 2008-12-25 16:27:14 -0800 (Thu, 25 Dec 2008) $
00028  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00029  */
00030 /**
00031  * List of helpers to include
00032  */
00033     uses('router', DS.'controller'.DS.'controller');
00034 /**
00035  * Dispatcher translates URLs to controller-action-paramter triads.
00036  *
00037  * Dispatches the request, creating appropriate models and controllers.
00038  *
00039  * @package     cake
00040  * @subpackage  cake.cake
00041  */
00042 class Dispatcher extends Object {
00043 /**
00044  * Base URL
00045  * @var string
00046  */
00047     var $base = false;
00048 /**
00049  * @var string
00050  */
00051     var $admin = false;
00052 /**
00053  * @var string
00054  */
00055     var $webservices = null;
00056 /**
00057  * @var string
00058  */
00059     var $plugin = null;
00060 /**
00061  * Constructor.
00062  */
00063     function __construct() {
00064         parent::__construct();
00065     }
00066 /**
00067  * Dispatches and invokes given URL, handing over control to the involved controllers, and then renders the results (if autoRender is set).
00068  *
00069  * If no controller of given name can be found, invoke() shows error messages in
00070  * the form of Missing Controllers information. It does the same with Actions (methods of Controllers are called
00071  * Actions).
00072  *
00073  * @param string $url   URL information to work on.
00074  * @param array $additionalParams   Settings array ("bare", "return"),
00075  * which is melded with the GET and POST params.
00076  * @return boolean      Success
00077  */
00078     function dispatch($url, $additionalParams=array()) {
00079         $params = array_merge($this->parseParams($url), $additionalParams);
00080         $missingController = false;
00081         $missingAction = false;
00082         $missingView = false;
00083         $privateAction = false;
00084         $this->base = $this->baseUrl();
00085 
00086         if (empty($params['controller'])) {
00087             $missingController = true;
00088         } else {
00089             $ctrlName = Inflector::camelize($params['controller']);
00090             $ctrlClass = $ctrlName.'Controller';
00091 
00092             if (!loadController($ctrlName)) {
00093                 $pluginName = Inflector::camelize($params['action']);
00094                 if (!loadPluginController(Inflector::underscore($ctrlName), $pluginName)) {
00095                     if (preg_match('/([\\.]+)/', $ctrlName)) {
00096                         return $this->cakeError('error404', array(
00097                                                         array('url' => strtolower($ctrlName),
00098                                                                 'message' => 'Was not found on this server',
00099                                                                 'base' => $this->base)));
00100                     } elseif (!class_exists($ctrlClass)) {
00101                         $missingController = true;
00102                     } else {
00103                         $params['plugin'] = null;
00104                         $this->plugin = null;
00105                     }
00106                 } else {
00107                     $params['plugin'] = Inflector::underscore($ctrlName);
00108                 }
00109             } else {
00110                 $params['plugin'] = null;
00111                 $this->plugin = null;
00112             }
00113         }
00114 
00115         if (isset($params['plugin'])) {
00116             $plugin = $params['plugin'];
00117             $pluginName = Inflector::camelize($params['action']);
00118             $pluginClass = $pluginName.'Controller';
00119             $ctrlClass = $pluginClass;
00120             $oldAction = $params['action'];
00121             $params = $this->_restructureParams($params);
00122             $this->plugin = $plugin;
00123             loadPluginModels($plugin);
00124             $this->base = $this->base.'/'.Inflector::underscore($ctrlName);
00125 
00126             if (empty($params['controller']) || !class_exists($pluginClass)) {
00127                 $params['controller'] = Inflector::underscore($ctrlName);
00128                 $ctrlClass = $ctrlName.'Controller';
00129                 if (!is_null($params['action'])) {
00130                     array_unshift($params['pass'], $params['action']);
00131                 }
00132                 $params['action'] = $oldAction;
00133             }
00134         }
00135 
00136         if (empty($params['action'])) {
00137             $params['action'] = 'index';
00138         }
00139 
00140         if (defined('CAKE_ADMIN')) {
00141             if (isset($params[CAKE_ADMIN])) {
00142                 $this->admin = '/'.CAKE_ADMIN ;
00143                 $url = preg_replace('/'.CAKE_ADMIN.'(\/|$)/', '', $url);
00144                 $params['action'] = CAKE_ADMIN.'_'.$params['action'];
00145             } elseif (strpos($params['action'], CAKE_ADMIN) === 0) {
00146                     $privateAction = true;
00147             }
00148         }
00149 
00150         if ($missingController) {
00151             return $this->cakeError('missingController', array(
00152                                             array('className' => Inflector::camelize($params['controller']."Controller"),
00153                                                     'webroot' => $this->webroot,
00154                                                     'url' => $url,
00155                                                     'base' => $this->base)));
00156         } else {
00157             $controller =& new $ctrlClass();
00158         }
00159 
00160         $classMethods = get_class_methods($controller);
00161         $classVars = get_object_vars($controller);
00162 
00163         if ((in_array($params['action'], $classMethods) || in_array(strtolower($params['action']), $classMethods)) && strpos($params['action'], '_', 0) === 0) {
00164             $privateAction = true;
00165         }
00166 
00167         if (!in_array($params['action'], $classMethods) && !in_array(strtolower($params['action']), $classMethods)) {
00168             $missingAction = true;
00169         }
00170 
00171         if (in_array(strtolower($params['action']), array('object', 'tostring', 'requestaction', 'log',
00172                                                                             'cakeerror', 'constructclasses', 'redirect',
00173                                                                             'set', 'setaction', 'validate', 'validateerrors',
00174                                                                             'render', 'referer', 'flash', 'flashout',
00175                                                                             'generatefieldnames', 'postconditions', 'cleanupfields',
00176                                                                             'beforefilter', 'beforerender', 'afterfilter'))) {
00177             $missingAction = true;
00178         }
00179 
00180         if (in_array('return', array_keys($params)) && $params['return'] == 1) {
00181             $controller->autoRender = false;
00182         }
00183 
00184         $controller->base = $this->base;
00185         $base = strip_plugin($this->base, $this->plugin);
00186         if (defined("BASE_URL")) {
00187             $controller->here = $base . $this->admin . $url;
00188         } else {
00189             $controller->here = $base . $this->admin . '/' . $url;
00190         }
00191         $controller->webroot = $this->webroot;
00192         $controller->params = $params;
00193         $controller->action = $params['action'];
00194 
00195         if (!empty($controller->params['data'])) {
00196             $controller->data =& $controller->params['data'];
00197         } else {
00198             $controller->data = null;
00199         }
00200 
00201         if (!empty($controller->params['pass'])) {
00202             $controller->passed_args =& $controller->params['pass'];
00203             $controller->passedArgs =&  $controller->params['pass'];
00204         } else {
00205             $controller->passed_args = null;
00206             $controller->passedArgs = null;
00207         }
00208 
00209         if (!empty($params['bare'])) {
00210             $controller->autoLayout = !$params['bare'];
00211         } else {
00212             $controller->autoLayout = $controller->autoLayout;
00213         }
00214 
00215         $controller->webservices = $params['webservices'];
00216         $controller->plugin = $this->plugin;
00217 
00218         if (!is_null($controller->webservices)) {
00219             array_push($controller->components, $controller->webservices);
00220             array_push($controller->helpers, $controller->webservices);
00221             $component =& new Component($controller);
00222         }
00223         $controller->_initComponents();
00224         $controller->constructClasses();
00225 
00226         if ($missingAction && !in_array('scaffold', array_keys($classVars))) {
00227             $this->start($controller);
00228             return $this->cakeError('missingAction', array(
00229                                             array('className' => Inflector::camelize($params['controller']."Controller"),
00230                                                     'action' => $params['action'],
00231                                                     'webroot' => $this->webroot,
00232                                                     'url' => $url,
00233                                                     'base' => $this->base)));
00234         }
00235 
00236         if ($privateAction) {
00237             $this->start($controller);
00238             return $this->cakeError('privateAction', array(
00239                                             array('className' => Inflector::camelize($params['controller']."Controller"),
00240                                                     'action' => $params['action'],
00241                                                     'webroot' => $this->webroot,
00242                                                     'url' => $url,
00243                                                     'base' => $this->base)));
00244         }
00245         return $this->_invoke($controller, $params, $missingAction);
00246     }
00247 /**
00248  * Invokes given controller's render action if autoRender option is set. Otherwise the contents of the operation are returned as a string.
00249  *
00250  * @param object $controller
00251  * @param array $params
00252  * @param boolean $missingAction
00253  * @return string
00254  */
00255     function _invoke (&$controller, $params, $missingAction = false) {
00256         $this->start($controller);
00257         $classVars = get_object_vars($controller);
00258 
00259         if ($missingAction && in_array('scaffold', array_keys($classVars))) {
00260             uses(DS.'controller'.DS.'scaffold');
00261             return new Scaffold($controller, $params);
00262         } else {
00263             $output = call_user_func_array(array(&$controller, $params['action']), empty($params['pass'])? array(): $params['pass']);
00264         }
00265         if ($controller->autoRender) {
00266             $output = $controller->render();
00267         }
00268         $controller->output =& $output;
00269         $controller->afterFilter();
00270         return $controller->output;
00271     }
00272 /**
00273  * Starts up a controller
00274  *
00275  * @param object $controller
00276  */
00277     function start(&$controller) {
00278         if (!empty($controller->beforeFilter)) {
00279             if (is_array($controller->beforeFilter)) {
00280 
00281                 foreach ($controller->beforeFilter as $filter) {
00282                     if (is_callable(array($controller,$filter)) && $filter != 'beforeFilter') {
00283                         $controller->$filter();
00284                     }
00285                 }
00286             } else {
00287                 if (is_callable(array($controller, $controller->beforeFilter)) && $controller->beforeFilter != 'beforeFilter') {
00288                     $controller->{$controller->beforeFilter}();
00289                 }
00290             }
00291         }
00292         $controller->beforeFilter();
00293 
00294         foreach ($controller->components as $c) {
00295             $path = preg_split('/\/|\./', $c);
00296             $c = $path[count($path) - 1];
00297             if (isset($controller->{$c}) && is_object($controller->{$c}) && is_callable(array($controller->{$c}, 'startup'))) {
00298                 $controller->{$c}->startup($controller);
00299             }
00300         }
00301     }
00302 
00303 /**
00304  * Returns array of GET and POST parameters. GET parameters are taken from given URL.
00305  *
00306  * @param string $from_url  URL to mine for parameter information.
00307  * @return array Parameters found in POST and GET.
00308  */
00309     function parseParams($from_url) {
00310         $Route = new Router();
00311         include CONFIGS.'routes.php';
00312         $params = $Route->parse ($from_url);
00313 
00314         if (ini_get('magic_quotes_gpc') == 1) {
00315             if (!empty($_POST)) {
00316                 $params['form'] = stripslashes_deep($_POST);
00317             }
00318         } else {
00319             $params['form'] = $_POST;
00320         }
00321 
00322         if (isset($params['form']['data'])) {
00323             $params['data'] = $Route->stripEscape($params['form']['data']);
00324         }
00325 
00326         if (isset($_GET)) {
00327             if (ini_get('magic_quotes_gpc') == 1) {
00328                 $params['url'] = stripslashes_deep($_GET);
00329             } else {
00330                 $params['url'] = $_GET;
00331             }
00332         }
00333 
00334         foreach ($_FILES as $name => $data) {
00335             if ($name != 'data') {
00336                 $params['form'][$name] = $data;
00337             }
00338         }
00339 
00340         if (isset($_FILES['data'])) {
00341             foreach ($_FILES['data'] as $key => $data) {
00342 
00343                 foreach ($data as $model => $fields) {
00344 
00345                     foreach ($fields as $field => $value) {
00346                         $params['data'][$model][$field][$key] = $value;
00347                     }
00348                 }
00349             }
00350         }
00351         $params['bare'] = empty($params['ajax'])? (empty($params['bare'])? 0: 1): 1;
00352         $params['webservices'] = empty($params['webservices']) ? null : $params['webservices'];
00353         return $params;
00354     }
00355 /**
00356  * Returns a base URL.
00357  *
00358  * @return string   Base URL
00359  */
00360     function baseUrl() {
00361         $htaccess = null;
00362         $base = $this->admin;
00363         $this->webroot = '';
00364 
00365         if (defined('BASE_URL')) {
00366             $base = BASE_URL.$this->admin;
00367         }
00368 
00369         $docRoot = env('DOCUMENT_ROOT');
00370         $scriptName = env('PHP_SELF');
00371         $r = null;
00372         $appDirName = str_replace('/', '\/', preg_quote(APP_DIR));
00373         $webrootDirName = str_replace('/', '\/', preg_quote(WEBROOT_DIR));
00374 
00375         if (preg_match('/'.$appDirName.'\\'.DS.$webrootDirName.'/', $docRoot)) {
00376             $this->webroot = '/';
00377 
00378             if (preg_match('/^(.*)\/index\.php$/', $scriptName, $r)) {
00379 
00380                 if (!empty($r[1])) {
00381                     return  $base.$r[1];
00382                 }
00383             }
00384         } else {
00385             if (defined('BASE_URL')) {
00386                 $webroot = setUri();
00387                 $htaccess = preg_replace('/(?:'.APP_DIR.'\\/(.*)|index\\.php(.*))/i', '', $webroot).APP_DIR.'/'.$webrootDirName.'/';
00388             }
00389 
00390             if (preg_match('/^(.*)\\/'.$appDirName.'\\/'.$webrootDirName.'\\/index\\.php$/', $scriptName, $regs)) {
00391 
00392                 if (APP_DIR === 'app') {
00393                     $appDir = null;
00394                 } else {
00395                     $appDir = '/'.APP_DIR;
00396                 }
00397                 !empty($htaccess)? $this->webroot = $htaccess : $this->webroot = $regs[1].$appDir.'/';
00398                 return  $base.$regs[1].$appDir;
00399 
00400             } elseif (preg_match('/^(.*)\\/'.$webrootDirName.'([^\/i]*)|index\\\.php$/', $scriptName, $regs)) {
00401                 !empty($htaccess)? $this->webroot = $htaccess : $this->webroot = $regs[0].'/';
00402                 return  $base.$regs[0];
00403 
00404             } else {
00405                 !empty($htaccess)? $this->webroot = $htaccess : $this->webroot = '/';
00406                 return $base;
00407             }
00408         }
00409         return $base;
00410     }
00411 /**
00412  * Enter description here...
00413  *
00414  * @param unknown_type $params
00415  * @return unknown
00416  */
00417     function _restructureParams($params) {
00418         $params['controller'] = $params['action'];
00419 
00420         if (isset($params['pass'][0])) {
00421             $params['action'] = $params['pass'][0];
00422             array_shift($params['pass']);
00423         } else {
00424             $params['action'] = null;
00425         }
00426         return $params;
00427     }
00428 }
00429 ?>