[ Index ]
 

Code source de Symfony 1.0.0

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/controller/ -> sfController.class.php (source)

   1  <?php
   2  
   3  /*
   4   * This file is part of the symfony package.
   5   * (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
   6   * (c) 2004-2006 Sean Kerr.
   7   *
   8   * For the full copyright and license information, please view the LICENSE
   9   * file that was distributed with this source code.
  10   */
  11  
  12  /**
  13   * sfController directs application flow.
  14   *
  15   * @package    symfony
  16   * @subpackage controller
  17   * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
  18   * @author     Sean Kerr <skerr@mojavi.org>
  19   * @version    SVN: $Id: sfController.class.php 3221 2007-01-11 07:33:23Z fabien $
  20   */
  21  abstract class sfController
  22  {
  23    protected
  24      $context                  = null,
  25      $controllerClasses        = array(),
  26      $maxForwards              = 5,
  27      $renderMode               = sfView::RENDER_CLIENT,
  28      $viewCacheClassName       = null;
  29  
  30    /**
  31     * Indicates whether or not a module has a specific component.
  32     *
  33     * @param string A module name
  34     * @param string An component name
  35     *
  36     * @return bool true, if the component exists, otherwise false
  37     */
  38    public function componentExists($moduleName, $componentName)
  39    {
  40      return $this->controllerExists($moduleName, $componentName, 'component', false);
  41    }
  42  
  43    /**
  44     * Indicates whether or not a module has a specific action.
  45     *
  46     * @param string A module name
  47     * @param string An action name
  48     *
  49     * @return bool true, if the action exists, otherwise false
  50     */
  51    public function actionExists($moduleName, $actionName)
  52    {
  53      return $this->controllerExists($moduleName, $actionName, 'action', false);
  54    }
  55  
  56    /**
  57     * Looks for a controller and optionally throw exceptions if existence is required (i.e.
  58     * in the case of {@link getController()}).
  59     *
  60     * @param string  The name of the module
  61     * @param string  The name of the controller within the module
  62     * @param string  Either 'action' or 'component' depending on the type of controller to look for
  63     * @param boolean Whether to throw exceptions if the controller doesn't exist
  64     *
  65     * @throws sfConfigurationException thrown if the module is not enabled
  66     * @throws sfControllerException thrown if the controller doesn't exist and the $throwExceptions parameter is set to true
  67     *
  68     * @return boolean true if the controller exists, false otherwise
  69     */
  70    protected function controllerExists($moduleName, $controllerName, $extension, $throwExceptions)
  71    {
  72      $dirs = sfLoader::getControllerDirs($moduleName);
  73      foreach ($dirs as $dir => $checkEnabled)
  74      {
  75        // plugin module enabled?
  76        if ($checkEnabled && !in_array($moduleName, sfConfig::get('sf_enabled_modules')) && is_readable($dir))
  77        {
  78          $error = 'The module "%s" is not enabled.';
  79          $error = sprintf($error, $moduleName);
  80  
  81          throw new sfConfigurationException($error);
  82        }
  83  
  84        // one action per file or one file for all actions
  85        $classFile   = strtolower($extension);
  86        $classSuffix = ucfirst(strtolower($extension));
  87        $file        = $dir.'/'.$controllerName.$classSuffix.'.class.php';
  88        if (is_readable($file))
  89        {
  90          // action class exists
  91          require_once($file);
  92  
  93          $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $controllerName.$classSuffix;
  94  
  95          return true;
  96        }
  97  
  98        $module_file = $dir.'/'.$classFile.'s.class.php';
  99        if (is_readable($module_file))
 100        {
 101          // module class exists
 102          require_once($module_file);
 103  
 104          if (!class_exists($moduleName.$classSuffix.'s', false))
 105          {
 106            if ($throwExceptions)
 107            {
 108              throw new sfControllerException(sprintf('There is no "%s" class in your action file "%s".', $moduleName.$classSuffix.'s', $module_file));
 109            }
 110  
 111            return false;
 112          }
 113  
 114          // action is defined in this class?
 115          if (!in_array('execute'.ucfirst($controllerName), get_class_methods($moduleName.$classSuffix.'s')))
 116          {
 117            if ($throwExceptions)
 118            {
 119              throw new sfControllerException(sprintf('There is no "%s" method in your action class "%s"', 'execute'.ucfirst($controllerName), $moduleName.$classSuffix.'s'));
 120            }
 121  
 122            return false;
 123          }
 124  
 125          $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix] = $moduleName.$classSuffix.'s';
 126          return true;
 127        }
 128      }
 129  
 130      // send an exception if debug
 131      if ($throwExceptions && sfConfig::get('sf_debug'))
 132      {
 133        $dirs = array_keys($dirs);
 134  
 135        // remove sf_root_dir from dirs
 136        foreach ($dirs as &$dir)
 137        {
 138          $dir = str_replace(sfConfig::get('sf_root_dir'), '%SF_ROOT_DIR%', $dir);
 139        }
 140  
 141        throw new sfControllerException(sprintf('{sfController} controller "%s/%s" does not exist in: %s', $moduleName, $controllerName, implode(', ', $dirs)));
 142      }
 143  
 144      return false;
 145    }
 146  
 147    /**
 148     * Forwards the request to another action.
 149     *
 150     * @param string  A module name
 151     * @param string  An action name
 152     *
 153     * @throws <b>sfConfigurationException</b> If an invalid configuration setting has been found
 154     * @throws <b>sfForwardException</b> If an error occurs while forwarding the request
 155     * @throws <b>sfInitializationException</b> If the action could not be initialized
 156     * @throws <b>sfSecurityException</b> If the action requires security but the user implementation is not of type sfSecurityUser
 157     */
 158    public function forward($moduleName, $actionName)
 159    {
 160      // replace unwanted characters
 161      $moduleName = preg_replace('/[^a-z0-9\-_]+/i', '', $moduleName);
 162      $actionName = preg_replace('/[^a-z0-9\-_]+/i', '', $actionName);
 163  
 164      if ($this->getActionStack()->getSize() >= $this->maxForwards)
 165      {
 166        // let's kill this party before it turns into cpu cycle hell
 167        $error = 'Too many forwards have been detected for this request (> %d)';
 168        $error = sprintf($error, $this->maxForwards);
 169  
 170        throw new sfForwardException($error);
 171      }
 172  
 173      $rootDir = sfConfig::get('sf_root_dir');
 174      $app     = sfConfig::get('sf_app');
 175      $env     = sfConfig::get('sf_environment');
 176  
 177      if (!sfConfig::get('sf_available') || sfToolkit::hasLockFile($rootDir.'/'.$app.'_'.$env.'.clilock'))
 178      {
 179        // application is unavailable
 180        $moduleName = sfConfig::get('sf_unavailable_module');
 181        $actionName = sfConfig::get('sf_unavailable_action');
 182  
 183        if (!$this->actionExists($moduleName, $actionName))
 184        {
 185          // cannot find unavailable module/action
 186          $error = 'Invalid configuration settings: [sf_unavailable_module] "%s", [sf_unavailable_action] "%s"';
 187          $error = sprintf($error, $moduleName, $actionName);
 188  
 189          throw new sfConfigurationException($error);
 190        }
 191      }
 192  
 193      // check for a module generator config file
 194      sfConfigCache::getInstance()->import(sfConfig::get('sf_app_module_dir_name').'/'.$moduleName.'/'.sfConfig::get('sf_app_module_config_dir_name').'/generator.yml', true, true);
 195  
 196      if (!$this->actionExists($moduleName, $actionName))
 197      {
 198        // the requested action doesn't exist
 199        if (sfConfig::get('sf_logging_enabled'))
 200        {
 201          $this->getContext()->getLogger()->info('{sfController} action does not exist');
 202        }
 203  
 204        // track the requested module so we have access to the data in the error 404 page
 205        $this->context->getRequest()->setAttribute('requested_action', $actionName);
 206        $this->context->getRequest()->setAttribute('requested_module', $moduleName);
 207  
 208        // switch to error 404 action
 209        $moduleName = sfConfig::get('sf_error_404_module');
 210        $actionName = sfConfig::get('sf_error_404_action');
 211  
 212        if (!$this->actionExists($moduleName, $actionName))
 213        {
 214          // cannot find unavailable module/action
 215          $error = 'Invalid configuration settings: [sf_error_404_module] "%s", [sf_error_404_action] "%s"';
 216          $error = sprintf($error, $moduleName, $actionName);
 217  
 218          throw new sfConfigurationException($error);
 219        }
 220      }
 221  
 222      // create an instance of the action
 223      $actionInstance = $this->getAction($moduleName, $actionName);
 224  
 225      // add a new action stack entry
 226      $this->getActionStack()->addEntry($moduleName, $actionName, $actionInstance);
 227  
 228      // include module configuration
 229      require(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$moduleName.'/'.sfConfig::get('sf_app_module_config_dir_name').'/module.yml'));
 230  
 231      // check if this module is internal
 232      if ($this->getActionStack()->getSize() == 1 && sfConfig::get('mod_'.strtolower($moduleName).'_is_internal') && !sfConfig::get('sf_test'))
 233      {
 234        $error = 'Action "%s" from module "%s" cannot be called directly';
 235        $error = sprintf($error, $actionName, $moduleName);
 236  
 237        throw new sfConfigurationException($error);
 238      }
 239  
 240      if (sfConfig::get('mod_'.strtolower($moduleName).'_enabled'))
 241      {
 242        // module is enabled
 243  
 244        // check for a module config.php
 245        $moduleConfig = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/'.sfConfig::get('sf_app_module_config_dir_name').'/config.php';
 246        if (is_readable($moduleConfig))
 247        {
 248          require_once($moduleConfig);
 249        }
 250  
 251        // initialize the action
 252        if ($actionInstance->initialize($this->context))
 253        {
 254          // create a new filter chain
 255          $filterChain = new sfFilterChain();
 256          $this->loadFilters($filterChain, $actionInstance);
 257  
 258          if ($moduleName == sfConfig::get('sf_error_404_module') && $actionName == sfConfig::get('sf_error_404_action'))
 259          {
 260            $this->getContext()->getResponse()->setStatusCode(404);
 261            $this->getContext()->getResponse()->setHttpHeader('Status', '404 Not Found');
 262  
 263            foreach (sfMixer::getCallables('sfController:forward:error404') as $callable)
 264            {
 265              call_user_func($callable, $this, $moduleName, $actionName);
 266            }
 267          }
 268  
 269          // change i18n message source directory to our module
 270          if (sfConfig::get('sf_i18n'))
 271          {
 272            $this->context->getI18N()->setMessageSourceDir(sfLoader::getI18NDir($moduleName), $this->context->getUser()->getCulture());
 273          }
 274  
 275          // process the filter chain
 276          $filterChain->execute();
 277        }
 278        else
 279        {
 280          // action failed to initialize
 281          $error = 'Action initialization failed for module "%s", action "%s"';
 282          $error = sprintf($error, $moduleName, $actionName);
 283  
 284          throw new sfInitializationException($error);
 285        }
 286      }
 287      else
 288      {
 289        // module is disabled
 290        $moduleName = sfConfig::get('sf_module_disabled_module');
 291        $actionName = sfConfig::get('sf_module_disabled_action');
 292  
 293        if (!$this->actionExists($moduleName, $actionName))
 294        {
 295          // cannot find mod disabled module/action
 296          $error = 'Invalid configuration settings: [sf_module_disabled_module] "%s", [sf_module_disabled_action] "%s"';
 297          $error = sprintf($error, $moduleName, $actionName);
 298  
 299          throw new sfConfigurationException($error);
 300        }
 301  
 302        $this->forward($moduleName, $actionName);
 303      }
 304    }
 305  
 306    /**
 307     * Retrieves an sfAction implementation instance.
 308     *
 309     * @param  string A module name
 310     * @param  string An action name
 311     *
 312     * @return sfAction An sfAction implementation instance, if the action exists, otherwise null
 313     */
 314    public function getAction($moduleName, $actionName)
 315    {
 316      return $this->getController($moduleName, $actionName, 'action');
 317    }
 318  
 319    /**
 320     * Retrieves a sfComponent implementation instance.
 321     *
 322     * @param  string A module name
 323     * @param  string A component name
 324     *
 325     * @return sfComponent A sfComponent implementation instance, if the component exists, otherwise null
 326     */
 327    public function getComponent($moduleName, $componentName)
 328    {
 329      return $this->getController($moduleName, $componentName, 'component');
 330    }
 331  
 332    /**
 333     * Retrieves a controller implementation instance.
 334     *
 335     * @param  string A module name
 336     * @param  string A component name
 337     * @param  string  Either 'action' or 'component' depending on the type of controller to look for
 338     *
 339     * @return object A controller implementation instance, if the controller exists, otherwise null
 340     *
 341     * @see getComponent(), getAction()
 342     */
 343    protected function getController($moduleName, $controllerName, $extension)
 344    {
 345      $classSuffix = ucfirst(strtolower($extension));
 346      if (!isset($this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix]))
 347      {
 348        $this->controllerExists($moduleName, $controllerName, $extension, true);
 349      }
 350  
 351      $class = $this->controllerClasses[$moduleName.'_'.$controllerName.'_'.$classSuffix];
 352  
 353      // fix for same name classes
 354      $moduleClass = $moduleName.'_'.$class;
 355  
 356      if (class_exists($moduleClass, false))
 357      {
 358        $class = $moduleClass;
 359      }
 360  
 361      return new $class();
 362    }
 363  
 364    /**
 365     * Retrieves the action stack.
 366     *
 367     * @return sfActionStack An sfActionStack instance, if the action stack is enabled, otherwise null
 368     */
 369    public function getActionStack()
 370    {
 371      return $this->context->getActionStack();
 372    }
 373  
 374    /**
 375     * Retrieves the current application context.
 376     *
 377     * @return sfContext A sfContext instance
 378     */
 379    public function getContext()
 380    {
 381      return $this->context;
 382    }
 383  
 384    /**
 385     * Retrieves the presentation rendering mode.
 386     *
 387     * @return int One of the following:
 388     *             - sfView::RENDER_CLIENT
 389     *             - sfView::RENDER_VAR
 390     */
 391    public function getRenderMode()
 392    {
 393      return $this->renderMode;
 394    }
 395  
 396    /**
 397     * Retrieves a sfView implementation instance.
 398     *
 399     * @param string A module name
 400     * @param string An action name
 401     * @param string A view name
 402     *
 403     * @return sfView A sfView implementation instance, if the view exists, otherwise null
 404     */
 405    public function getView($moduleName, $actionName, $viewName)
 406    {
 407      // user view exists?
 408      $file = sfConfig::get('sf_app_module_dir').'/'.$moduleName.'/'.sfConfig::get('sf_app_module_view_dir_name').'/'.$actionName.$viewName.'View.class.php';
 409  
 410      if (is_readable($file))
 411      {
 412        require_once($file);
 413  
 414        $class = $actionName.$viewName.'View';
 415  
 416        // fix for same name classes
 417        $moduleClass = $moduleName.'_'.$class;
 418  
 419        if (class_exists($moduleClass, false))
 420        {
 421          $class = $moduleClass;
 422        }
 423      }
 424      else
 425      {
 426        // view class (as configured in module.yml or defined in action)
 427        $viewName = $this->getContext()->getRequest()->getAttribute($moduleName.'_'.$actionName.'_view_name', sfConfig::get('mod_'.strtolower($moduleName).'_view_class'), 'symfony/action/view');
 428        $class    = sfCore::getClassPath($viewName.'View') ? $viewName.'View' : 'sfPHPView';
 429      }
 430  
 431      return new $class();
 432    }
 433  
 434    /**
 435     * Initializes this controller.
 436     *
 437     * @param sfContext A sfContext implementation instance
 438     */
 439    public function initialize($context)
 440    {
 441      $this->context = $context;
 442  
 443      if (sfConfig::get('sf_logging_enabled'))
 444      {
 445        $this->context->getLogger()->info('{sfController} initialization');
 446      }
 447  
 448      // set max forwards
 449      $this->maxForwards = sfConfig::get('sf_max_forwards');
 450    }
 451  
 452    /**
 453     * Retrieves a new sfController implementation instance.
 454     *
 455     * @param string A sfController class name
 456     *
 457     * @return sfController A sfController implementation instance
 458     *
 459     * @throws sfFactoryException If a new controller implementation instance cannot be created
 460     */
 461    public static function newInstance($class)
 462    {
 463      try
 464      {
 465        // the class exists
 466        $object = new $class();
 467  
 468        if (!($object instanceof sfController))
 469        {
 470            // the class name is of the wrong type
 471            $error = 'Class "%s" is not of the type sfController';
 472            $error = sprintf($error, $class);
 473  
 474            throw new sfFactoryException($error);
 475        }
 476  
 477        return $object;
 478      }
 479      catch (sfException $e)
 480      {
 481        $e->printStackTrace();
 482      }
 483    }
 484  
 485    /**
 486     * Sends and email from the current action.
 487     *
 488     * This methods calls a module/action with the sfMailView class.
 489     *
 490     * @param  string A module name
 491     * @param  string An action name
 492     *
 493     * @return string The generated mail content
 494     *
 495     * @see sfMailView, getPresentationFor(), sfController
 496     */
 497    public function sendEmail($module, $action)
 498    {
 499      return $this->getPresentationFor($module, $action, 'sfMail');
 500    }
 501  
 502    /**
 503     * Returns the rendered view presentation of a given module/action.
 504     *
 505     * @param  string A module name
 506     * @param  string An action name
 507     * @param  string A View class name
 508     *
 509     * @return string The generated content
 510     */
 511    public function getPresentationFor($module, $action, $viewName = null)
 512    {
 513      if (sfConfig::get('sf_logging_enabled'))
 514      {
 515        $this->getContext()->getLogger()->info('{sfController} get presentation for action "'.$module.'/'.$action.'" (view class: "'.$viewName.'")');
 516      }
 517  
 518      // get original render mode
 519      $renderMode = $this->getRenderMode();
 520  
 521      // set render mode to var
 522      $this->setRenderMode(sfView::RENDER_VAR);
 523  
 524      // grab the action stack
 525      $actionStack = $this->getActionStack();
 526  
 527      // grab this next forward's action stack index
 528      $index = $actionStack->getSize();
 529  
 530      // set viewName if needed
 531      if ($viewName)
 532      {
 533        $this->getContext()->getRequest()->setAttribute($module.'_'.$action.'_view_name', $viewName, 'symfony/action/view');
 534      }
 535  
 536      // forward to the mail action
 537      $this->forward($module, $action);
 538  
 539      // grab the action entry from this forward
 540      $actionEntry = $actionStack->getEntry($index);
 541  
 542      // get raw email content
 543      $presentation =& $actionEntry->getPresentation();
 544  
 545      // put render mode back
 546      $this->setRenderMode($renderMode);
 547  
 548      // remove the action entry
 549      $nb = $actionStack->getSize() - $index;
 550      while ($nb-- > 0)
 551      {
 552        $actionEntry = $actionStack->popEntry();
 553  
 554        if ($actionEntry->getModuleName() == sfConfig::get('sf_login_module') && $actionEntry->getActionName() == sfConfig::get('sf_login_action'))
 555        {
 556          $error = 'Your mail action is secured but the user is not authenticated.';
 557  
 558          throw new sfException($error);
 559        }
 560        else if ($actionEntry->getModuleName() == sfConfig::get('sf_secure_module') && $actionEntry->getActionName() == sfConfig::get('sf_secure_action'))
 561        {
 562          $error = 'Your mail action is secured but the user does not have access.';
 563  
 564          throw new sfException($error);
 565        }
 566      }
 567  
 568      // remove viewName
 569      if ($viewName)
 570      {
 571        $this->getContext()->getRequest()->getAttributeHolder()->remove($module.'_'.$action.'_view_name', 'symfony/action/view');
 572      }
 573  
 574      return $presentation;
 575    }
 576  
 577    /**
 578     * Sets the presentation rendering mode.
 579     *
 580     * @param int A rendering mode
 581     *
 582     * @throws sfRenderException If an invalid render mode has been set
 583     */
 584    public function setRenderMode($mode)
 585    {
 586      if ($mode == sfView::RENDER_CLIENT || $mode == sfView::RENDER_VAR || $mode == sfView::RENDER_NONE)
 587      {
 588        $this->renderMode = $mode;
 589  
 590        return;
 591      }
 592  
 593      // invalid rendering mode type
 594      $error = 'Invalid rendering mode: %s';
 595      $error = sprintf($error, $mode);
 596  
 597      throw new sfRenderException($error);
 598    }
 599  
 600    /**
 601     * Indicates whether or not we were called using the CLI version of PHP.
 602     *
 603     * @return bool true, if using cli, otherwise false.
 604     */
 605    public function inCLI()
 606    {
 607      return 0 == strncasecmp(PHP_SAPI, 'cli', 3);
 608    }
 609  
 610    /**
 611     * Loads application nad module filters.
 612     *
 613     * @param sfFilterChain A sfFilterChain instance
 614     * @param sfAction      A sfAction instance
 615     */
 616    public function loadFilters($filterChain, $actionInstance)
 617    {
 618      $moduleName = $this->context->getModuleName();
 619  
 620      require(sfConfigCache::getInstance()->checkConfig(sfConfig::get('sf_app_module_dir_name').'/'.$moduleName.'/'.sfConfig::get('sf_app_module_config_dir_name').'/filters.yml'));
 621    }
 622  
 623    /**
 624     * Calls methods defined via the sfMixer class.
 625     *
 626     * @param string The method name
 627     * @param array  The method arguments
 628     *
 629     * @return mixed The returned value of the called method
 630     *
 631     * @see sfMixer
 632     */
 633    public function __call($method, $arguments)
 634    {
 635      if (!$callable = sfMixer::getCallable('sfController:'.$method))
 636      {
 637        throw new sfException(sprintf('Call to undefined method sfController::%s', $method));
 638      }
 639  
 640      array_unshift($arguments, $this);
 641  
 642      return call_user_func_array($callable, $arguments);
 643    }
 644  }


Généré le : Fri Mar 16 22:42:14 2007 par Balluche grâce à PHPXref 0.7