[ Index ]
 

Code source de LifeType 1.2.4

Accédez au Source d'autres logiciels libres

Classes | Fonctions | Variables | Constantes | Tables

title

Body

[fermer]

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

   1  <?php
   2  
   3      /**
   4       * \defgroup Controller
   5       *
   6       * The controller is the central piece of the MVC pattern, and the object that takes care of
   7       * transferrign the process flow to the right action class based on a certain value in the 
   8       * incoming request.
   9       *
  10       * This package includes the basic Controller class, as well as the BlogController and
  11       * AdminController ones, which implement a bit of extra logic for loading the maps and so on.
  12       *
  13       * There is also a dynamic class loader (ResourceClassLoader) that takes care of loading action classes 
  14       * from a certain set of folders.
  15       */
  16      
  17      lt_include( PLOG_CLASS_PATH."class/action/action.class.php" );
  18      lt_include( PLOG_CLASS_PATH."class/controller/resourceclassloader.class.php" );
  19  
  20      //
  21      // various constants that will come handy
  22      //
  23      define("DEFAULT_ACTION_PARAM", "op");
  24      define("DEFAULT_ACTION_NAME", "Default");
  25  
  26      //
  27      // global array to hold the mappings between action keys and action classes. It is implemented as a
  28      // global arry because the Controller::registerAction is a static method and PHP4 does not implement
  29      // class-level static methods, and therefore, this is the only way have to accomplish this
  30      // functionality
  31      //
  32      $_plogController_actionMap = array();
  33  
  34      //
  35      // Pretty much the same as above...
  36      //
  37      $_plogController_forwardAction = array();
  38  
  39      /**
  40       * \ingroup Controller
  41       *
  42       * This is how MVC works, using the pattern of the 'Front Controller'. With this pattern, we have
  43       * a single controller class that receives all the requests from the client, identifies the
  44       * action to be taken and the relays the execution of the action to the most suitable Action class.
  45       * The 'Action' class then will use the application business logic (the Model) to carry out the
  46       * operations necessary.
  47       *
  48       * (according to http://java.sun.com/blueprints/guidelines/designing_enterprise_applications_2e/web-tier/web-tier5.html)
  49       *
  50       * # The controller receives a POST from the client.
  51       * # The controller creates an Action corresponding to the requested operation (as described in the previous section).
  52       * # The controller calls the Action's perform method.
  53       * perform calls a model business method.
  54       * # The controller calls the screen flow manager to select the next view to display.
  55       * # The screen flow manager determines the next view and returns its name to the controller.
  56       * # The controller forwards the request to the templating service, which assembles and delivers the selected view to the client.
  57       * 
  58       * The Controller uses an action map file that maps action parameters to action classes. This is file is
  59       * nothing more than an associative PHP array where the key of the array is the value of the action
  60       * parameter and the key is the name of an action class. The default action parameter is "op" and the default
  61       * action is "Default" unless otherwise specified.
  62       *
  63       * This is an example of a map file:
  64       *
  65       * <pre>
  66       * $actions["Default"] = "AdminDefaultAction";
  67       * $actions["Login"] = "AdminLoginAction";
  68       * $actions["blogSelect"] = "AdminMainAction";
  69       * $actions["Dashboard"] = "AdminMainAction";
  70       * $actions["Manage"] = "AdminManageAction";
  71       * </pre>
  72       *
  73       * It is not necesary to specify the full extension of the file, and by default it is considered to be
  74       * ".class.php". In case this is not the case, please the ResourceClassLoader::setClassFileSuffix()
  75       * method.
  76       *
  77       * Classes can be dynamically loaded (meaning that we
  78       * do not need to load all of them via include() or lt_include() at the top of our code), via the 
  79       * ResourceClassLoader class. This class will scan a set of pre-defined folders looking for the action
  80       * class and load it if it's the one we were looking for.
  81       *
  82       * In order to create a Controller object and process a request, we would use something like:
  83       *
  84       * <pre>
  85       *  $controller = new Controller( "myactionmap.properties.php" );
  86       *  $controller->process( $_REQUEST );
  87       * </pre>
  88       *
  89       * It is also possible to register new actions dynamically at run time via the static method
  90       * Controller::registerAction() which takes an action class name and an action id as parameters. This is the
  91       * method used by plugins to register new actions (although via the wrapper PluginBase::registerAction())
  92       *     
  93       * In our particular implementation, each action class should extend the Action class or a child of it
  94       * such as BlogAction, AdminAction, etc. Each one of this action classes should at least implement
  95       * the Action::perform() method and include there its business logic (which can be whatever) Action classes
  96       * are expected to generate a valid View class that the Controller will use to render the contents that
  97       * will be sent back to the client. The Controller will get the right view via the Action::getView() method, and
  98       * views can be set via the Action::_view attribute or the Action::setView() method.
  99       *
 100       * Another method that the controller will call is the validate() method that can be used for basic
 101       * data validation logic. The base Action class already provides some code in this method, which is tied to
 102       * the FormValidator and Validator classes so in case of data validation, it is advisable to use those
 103       * methods. However if required, feel free to reimplement Action::validate(), keeping in mind that if the controller
 104       * receives a positive value, it will continue processing the Action::perform() and if not, it will stop
 105       * processing and call Action::getView() right away.
 106       *
 107       * Actions can also forward the process flow to another action without generating a view by calling
 108       * the static method Controller::setForwardAction(), which takes an action class identifier as a parameter. If
 109       * after processing action the controller detects that there is a forwarding in place, it will <b>not</b>
 110       * call Action::getView() but instead, start the process again and call validate() and process() in the next
 111       * action in line.
 112       *
 113       * @see BlogController
 114       * @see AdminController
 115       * @see Action
 116       * @see BlogAction
 117       * @see AdminAction
 118       * @see FormValidator
 119       * @see Validator
 120       */
 121      class Controller 
 122      {
 123          var $_actionParam;
 124          
 125          /**
 126           * @public
 127           * Determines the base path from where action files can be dynamically loaded
 128           */
 129          var $actionFolderPath;
 130          
 131          /**
 132           * @private
 133           */
 134          var $_cannotPerformAction;
 135          
 136          /**
 137           * @private
 138           */        
 139          var $_forwardAction; 
 140          
 141          /**
 142           * @private
 143           */        
 144          var $_loader;        
 145  
 146          /**
 147           * $ActionsMap is an associative array of the form:
 148           *
 149           * ( $actionName, $actionClassName )
 150           *
 151           * Where for every different possible value of the 'action' parameter in the request,
 152           * there is an object inheriting form the Action class that will take care of
 153           * that requested action.
 154           *
 155           * @param actionMap is the associative array with the mappings
 156           * @param actionParam is the name of the parameter in the request that will be used
 157           * @param loadActionClasses By default set to 'true', enables dynamic loading of the
 158           * action classes from disk. Set it to false if the action classes that are going
 159           * to be needed by the controller have already been loaded and there is no need to
 160           * do it again.
 161           * to identify the action to be taken
 162           */
 163          function Controller( $actionMap, $actionParam = DEFAULT_ACTION_PARAM )
 164          {           
 165              global $_plogController_actionMap;
 166              if( !is_array($_plogController_actionMap))
 167                   $_plogController_actionMap = Array();
 168  
 169              $_plogController_actionMap = $actionMap;
 170  
 171              $this->_actionParam = $actionParam;
 172              $this->_forwardAction = null;
 173              
 174              // default folder where actions are located
 175              $this->actionFolderPath = PLOG_CLASS_PATH.'class/action/';
 176  
 177              // get a resource loader so that we can dynamically load classes if they
 178              // have not been loaded yet!
 179              $this->_loader =& ResourceClassLoader::getLoader( $this->actionFolderPath );
 180              
 181              // no action defined in case we cannot perform
 182              $this->_cannotPerformAction = null;
 183          }
 184          
 185          /**
 186           * sets the folder where action classes can be dynamically loaded
 187           *
 188           * @param newActionFolderPath absolute or relative path to the folder
 189           */
 190  		function setActionFolderPath( $newActionFolderPath )
 191          {
 192              $this->_loader->addSearchFolder( $newActionFolderPath );
 193          }
 194  
 195          /**
 196           * @static
 197           */
 198          function registerAction( $actionKey, $actionClass )
 199          {
 200              global $_plogController_actionMap;
 201              if( !is_array($_plogController_actionMap))   // make sure that we have an array
 202                   $_plogController_actionMap = Array();
 203              $_plogController_actionMap[ $actionKey ] = $actionClass;
 204  
 205              return true;
 206          }
 207  
 208          /**
 209           * Add function info here
 210           *
 211           * @private
 212           */
 213          function _getActionClassName( $actionName )
 214          {
 215              global $_plogController_actionMap;
 216              $actionMap = $_plogController_actionMap;
 217  
 218              if (($actionName == '') || (!empty($actionMap) && !array_key_exists($actionName, $actionMap))) {
 219                  $actionName = DEFAULT_ACTION_NAME;
 220              }
 221  
 222              if (!empty($actionMap)) {
 223                  $actionClassName = $actionMap[$actionName];
 224              }
 225              else {
 226                  $actionClassName = $actionName . 'Action';
 227              }
 228  
 229              return $actionClassName;
 230          }
 231  
 232          /**
 233           * Sets the action to which we will forward the process
 234           *
 235           * @param forwardAction Name of the action to which we will forward the current
 236           * workflow.
 237           * @param previousActionObject
 238           * @static
 239           */
 240          function setForwardAction( $forwardAction, $previousActionObject = null )
 241          {
 242              global $_plogController_forwardAction;
 243              global $_plogController_previousAction;
 244  
 245              $_plogController_forwardAction = $forwardAction;
 246              $_plogController_previousAction = $previousActionObject;
 247          }
 248  
 249          /**
 250           * Loads an action class from disk. I have refactored it and put this little bit in its
 251           * own method because doing so, applications that want to load the action classes from
 252           * somewhere else than PLOG_CLASS_PATH/class/action/, or have a different naming scheme
 253           * can extend this class and reimplement this method at will.
 254           *
 255           * @param actionClass The name of the action class that is to be loaded.
 256           * @return Always true.
 257           */
 258          function loadActionClass( $actionClass )
 259          {
 260              if( !class_exists($actionClass)) {
 261                  $this->_loader->load( $actionClass );
 262              }
 263  
 264              return true;
 265          }
 266          
 267          /** 
 268           * Specific controllers should use this method to set a class that will be used in case
 269           * Action::canPerform() return false. The controller will then load this class and execute
 270           * it as if it was a normal action.
 271           * This feature can be used to display a view with an error message in case our controller 
 272           * and actions are working together to provide permission-based access: each action checks whether
 273           * the credentials of the current user allow him to execute the current action or not in
 274           * the Action::canPeform() method and if it returns true, then the action specified in this method
 275           * call takes over and displays whatever error message needs to be displayed (or does some
 276           * cleanup, etc, whatever needed)
 277           *
 278           * @param actionClass A string with the name of the class that should be loaded when
 279           * Action::canPerform() returns false. Please note that this is the name of the class, not the
 280           * class object itself!
 281           */
 282          function setCannotPerformAction( $actionClass )
 283          {
 284              $this->_cannotPerformAction = $actionClass;   
 285          }
 286  
 287          /**
 288           * Processess the HTTP request sent by the client
 289           *
 290           * @param httpRequest HTTP request sent by the client
 291           */
 292          function process( $httpRequest )
 293          {
 294              lt_include( PLOG_CLASS_PATH."class/net/request.class.php" );
 295  
 296              // get the name of the action
 297              $request = new Request( $httpRequest );
 298  
 299              $i = 0;
 300              $performed = false;
 301  
 302              while( !$performed ) {
 303                  // get the value of this varilable, every loop
 304                  global $_plogController_forwardAction;
 305                  global $_plogController_previousAction;
 306  
 307                      // jondaley: 08/29/2005, what are these here for??
 308                      // perhaps the global statements should be moved
 309                      // inside the elseif loop below?
 310                  $_plogController_forwardAction;
 311                  $_plogController_previousAction;
 312  
 313                  if ($i == 0) {
 314                      // if this is the first iteration, then we have to take this path...
 315                      // since we will use the http request to determine which action to
 316                      // use next
 317                      $actionName = $request->getValue($this->_actionParam );
 318                      $actionClass = $this->_getActionClassName($request->getValue($this->_actionParam));
 319                  }
 320                  elseif (!empty($_plogController_forwardAction)) {
 321                      // if we're forwarding the current execution flow to another action, then
 322                      // we'll go this way
 323                      $actionName = $_plogController_forwardAction;
 324                      $actionClass = $this->_getActionClassName($_plogController_forwardAction);
 325                      $httpRequest = HttpVars::getRequest();
 326                      $_plogController_forwardAction = null;
 327                  }
 328                  else {
 329                      // if there's nothing else to do, finish
 330                      $performed = true;
 331                  }
 332  
 333                  if( !$performed ) {
 334                      lt_include( PLOG_CLASS_PATH."class/action/actioninfo.class.php" );
 335  
 336                      // load the class if it hasn't been loaded yet
 337                      $this->loadActionClass( $actionClass );
 338  
 339                      $actionInfo   = new ActionInfo( $this->_actionParam, $actionName );
 340                      $actionObject = new $actionClass( $actionInfo, $httpRequest );
 341                      $actionObject->setPreviousAction( $_plogController_previousAction );
 342                      
 343                      if( $actionObject->canPerform()) {
 344                          // we can use the validate method to check the values of the form variables. If validate()
 345                          // returns 'true', then we call the 'perform' method. If not, then we won't :)
 346                          if( $actionObject->validate()) {
 347                              if( $actionObject->perform())
 348                                  $actionObject->setSuccess( true );
 349                              else
 350                                  $actionObject->setSuccess( false );
 351                          }
 352                      }
 353                      else {
 354                          // check that we have an action defined for this kind of situations
 355                          if( $this->_cannotPerformAction === null ) {
 356                              throw( new Exception( "Action ".$actionName." was not allowed to execute and there is no fallback action to execute" ));
 357                              die();
 358                          }
 359                          $actionClass = $this->_cannotPerformAction;
 360                          $this->loadActionClass( $actionClass );
 361                          $actionObject = new $actionClass( $actionInfo, $httpRequest );
 362                          $actionObject->perform();
 363                      }
 364                  }
 365  
 366                  $i++;
 367              }
 368  
 369              // once the operation has been carried out, fetch and send the view
 370              // to the client
 371              $view = $actionObject->getView();
 372  
 373              // this is not good...
 374              if( empty( $view )) {
 375                  $e = new Exception( 'The view is empty after calling the perform method.' );
 376                  throw( $e );
 377              }
 378              else
 379                  $view->render();
 380          }
 381      }
 382  ?>


Généré le : Mon Nov 26 21:04:15 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics