Source for file jCoordinator.class.php

Documentation is available at jCoordinator.class.php

  1. <?php
  2. /**
  3. @package      jelix
  4. @subpackage   core
  5. @author       Laurent Jouanneau
  6. @contributor  Thibault PIRONT < nuKs >, Julien Issler, Dominique Papin
  7. @copyright    2005-2008 laurent Jouanneau
  8. @copyright    2007 Thibault PIRONT
  9. @copyright    2008 Julien Issler
  10. @copyright    2008 Dominique Papin
  11. @link         http://www.jelix.org
  12. @licence      GNU Lesser General Public Licence see LICENCE file or http://www.gnu.org/licenses/lgpl.html
  13. */
  14.  
  15. /**
  16.  * the main class of the jelix core
  17.  *
  18.  * this is the "chief orchestra" of the framework. Its goal is
  19.  * to load the configuration, to get the request parameters
  20.  * used to instancie the correspondant controllers and to run the right method.
  21.  * @package  jelix
  22.  * @subpackage core
  23.  */
  24. class jCoordinator {
  25.  
  26.     /**
  27.      * plugin list
  28.      * @var  array 
  29.      */
  30.     public $plugins = array();
  31.  
  32.     /**
  33.      * current response object
  34.      * @var jResponse 
  35.      */
  36.     public $response = null;
  37.  
  38.     /**
  39.      * current request object
  40.      * @var jRequest 
  41.      */
  42.     public $request = null;
  43.  
  44.     /**
  45.      * the selector of the current action
  46.      * @var jSelectorAct 
  47.      */
  48.     public $action = null;
  49.  
  50.     /**
  51.      * the current module name
  52.      * @var string 
  53.      */
  54.     public $moduleName;
  55.  
  56.     /**
  57.      * the current action name
  58.      * @var string 
  59.      */
  60.     public $actionName;
  61.  
  62.     /**
  63.      * List of all errors
  64.      * @var array 
  65.      */
  66.     public $errorMessages=array();
  67.  
  68.     /**
  69.      * List of all log messages
  70.      * @var array 
  71.      * @since 1.0
  72.      */
  73.     public $logMessages=array();
  74.  
  75.     /**
  76.      * @param  string $configFile name of the ini file to configure the framework
  77.      */
  78.     function __construct ($configFile{
  79.         global $gJCoord$gJConfig;
  80.  
  81.         $gJCoord =  $this;
  82.  
  83.         // load configuration data
  84.         $gJConfig jConfig::load($configFile);
  85.  
  86.         // set Error and exception handler
  87.         // ne devrait être désactivé que lors de certains tests de jelix
  88.         if($gJConfig->use_error_handler){
  89.             set_error_handler('jErrorHandler');
  90.             set_exception_handler('JExceptionHandler');
  91.         }
  92.         date_default_timezone_set($gJConfig->timeZone);
  93.         $this->_loadPlugins();
  94.     }
  95.  
  96.     /**
  97.      * load the plugins and their configuration file
  98.      */
  99.     private function _loadPlugins(){
  100.         global $gJConfig;
  101.  
  102.         foreach($gJConfig->coordplugins as $name=>$conf){
  103.             if($conf && isset($gJConfig->_pluginsPathList_coord[$name])){
  104.                 if($conf=='1'){
  105.                     $conf array();
  106.                 }else{
  107.                    $conff $conf;
  108.                    if(!file_exists(JELIX_APP_CONFIG_PATH.$conff))
  109.                         die("Jelix Error: Error in the main configuration. Configuration file '$conff' for coord plugin $name doesn't exist!");
  110.                    iffalse === ($conf parse_ini_file(JELIX_APP_CONFIG_PATH.$conff,true)))
  111.                         die("Jelix Error: Error in the configuration file of plugin $name ($conff)!");
  112.                 }
  113.                 include$gJConfig->_pluginsPathList_coord[$name].$name.'.coord.php');
  114.                 $class$name.'CoordPlugin';
  115.                 $this->plugins[strtolower($name)new $class($conf);
  116.             }
  117.         }
  118.     }
  119.  
  120.     /**
  121.     * main method : launch the execution of the action.
  122.     *
  123.     * This method should be called in a entry point.
  124.     * @param  jRequest  $request the request object
  125.     */
  126.     public function process ($request){
  127.         global $gJConfig;
  128.  
  129.         $this->request = $request;
  130.         $this->request->init();
  131.         jSession::start();
  132.  
  133.         $this->moduleName = $request->getParam('module');
  134.         $this->actionName = $request->getParam('action');
  135.  
  136.         if(empty($this->moduleName)){
  137.             $this->moduleName = $gJConfig->startModule;
  138.         }
  139.         if(empty($this->actionName)){
  140.             if($this->moduleName == $gJConfig->startModule)
  141.                 $this->actionName = $gJConfig->startAction;
  142.             else {
  143.                 $this->actionName = 'default:index';
  144.             }
  145.         }
  146.  
  147.         // module check
  148.         if($gJConfig->checkTrustedModules && !in_array($this->moduleName,$gJConfig->_trustedModules)){
  149.             throw new jException('jelix~errors.module.untrusted',$this->moduleName);
  150.         }
  151.  
  152.         jContext::push ($this->moduleName);
  153.         try{
  154.             $this->action = new jSelectorActFast($this->request->type$this->moduleName$this->actionName);
  155.             $ctrl $this->getController($this->action);
  156.         }catch(jException $e){
  157.             if ($gJConfig->urlengine['notfoundAct'==''{
  158.                 throw $e;
  159.             }
  160.             try {
  161.                 $this->action = new jSelectorAct($gJConfig->urlengine['notfoundAct']);
  162.                 $ctrl $this->getController($this->action);
  163.             }catch(jException $e2){
  164.                 throw $e;
  165.             }
  166.         }
  167.  
  168.         if (count($this->plugins)) {
  169.             $pluginparams array();
  170.             if(isset($ctrl->pluginParams['*'])){
  171.                 $pluginparams $ctrl->pluginParams['*'];
  172.             }
  173.  
  174.             if(isset($ctrl->pluginParams[$this->action->method])){
  175.                 $pluginparams array_merge($pluginparams$ctrl->pluginParams[$this->action->method]);
  176.             }
  177.  
  178.             foreach ($this->plugins as $name => $obj){
  179.                 $result $this->plugins[$name]->beforeAction ($pluginparams);
  180.                 if($result){
  181.                     $this->action = $result;
  182.                     jContext::pop();
  183.                     jContext::push($result->module);
  184.                     $this->moduleName = $result->module;
  185.                     $this->actionName = $result->resource;
  186.                     $ctrl $this->getController($this->action);
  187.                     break;
  188.                 }
  189.             }
  190.         }
  191.         $this->response = $ctrl->{$this->action->method}();
  192.  
  193.         if($this->response == null){
  194.             throw new jException('jelix~errors.response.missing',$this->action->toString());
  195.         }
  196.  
  197.         foreach ($this->plugins as $name => $obj){
  198.             $this->plugins[$name]->beforeOutput ();
  199.         }
  200.  
  201.         // envoi de la réponse
  202.         if(!$this->response->output()){
  203.             $this->response->outputErrors();
  204.         }
  205.  
  206.         foreach ($this->plugins as $name => $obj){
  207.             $this->plugins[$name]->afterProcess ();
  208.         }
  209.  
  210.         jContext::pop();
  211.         jSession::end();
  212.     }
  213.  
  214.     /**
  215.      * get the controller corresponding to the selector
  216.      * @param jSelectorAct $selector 
  217.      */
  218.     private function getController($selector){
  219.  
  220.         $ctrlpath $selector->getPath();
  221.         if(!file_exists($ctrlpath)){
  222.             throw new jException('jelix~errors.ad.controller.file.unknow',array($this->actionName,$ctrlpath));
  223.         }
  224.         require_once($ctrlpath);
  225.         $class $selector->getClass();
  226.         if(!class_exists($class,false)){
  227.             throw new jException('jelix~errors.ad.controller.class.unknow',array($this->actionName,$class$ctrlpath));
  228.         }
  229.         $ctrl new $class($this->request);
  230.         if($ctrl instanceof jIRestController){
  231.             $method $selector->method strtolower($_SERVER['REQUEST_METHOD']);
  232.         }elseif(!method_exists($ctrl$selector->method)){
  233.             throw new jException('jelix~errors.ad.controller.method.unknow',array($this->actionName$selector->method$class$ctrlpath));
  234.         }
  235.         return $ctrl;
  236.     }
  237.  
  238.  
  239.     /**
  240.      * instancy a response object corresponding to the default response type
  241.      * of the current resquest
  242.      * @param boolean $originalResponse TRUE to get the original, non overloaded response
  243.      * @return mixed  error string or false
  244.      */
  245.     public function initDefaultResponseOfRequest($originalResponse false){
  246.         if($originalResponse)
  247.             $responses &$GLOBALS['gJConfig']->_coreResponses;
  248.         else
  249.             $responses &$GLOBALS['gJConfig']->responses;
  250.  
  251.         $type $this->request->defaultResponseType;
  252.  
  253.         if(!isset($responses[$type]))
  254.             return jLocale::get('jelix~errors.default.response.type.unknow',array($this->moduleName.'~'.$this->actionName,$type));
  255.  
  256.         try{
  257.             $respclass $responses[$type];
  258.             require_once ($responses[$type.'.path']);
  259.             $this->response = new $respclass();
  260.             return false;
  261.         }
  262.         catch(Exception $e){
  263.             return $this->initDefaultResponseOfRequest(true);
  264.         }
  265.     }
  266.  
  267.     /**
  268.      * Handle an error event. Called by error handler and exception handler.
  269.      * Responses object should take care of the errorMessages property to display errors.
  270.      * @param string  $toDo    a string which contains keyword indicating what to do with the error
  271.      * @param string  $type    error type : 'error', 'warning', 'notice'
  272.      * @param integer $code    error code
  273.      * @param string  $message error message
  274.      * @param string  $file    the file name where the error appear
  275.      * @param integer $line    the line number where the error appear
  276.      * @param array   $trace   the stack trace
  277.      * @since 1.1
  278.      */
  279.     public function handleError($toDo$type$code$message$file$line$trace){
  280.         global $gJConfig;
  281.         $conf $gJConfig->error_handling;
  282.  
  283.         $doEchoByResponse true;
  284.  
  285.         if($this->request == null){
  286.             $message 'JELIX PANIC ! Error during initialization !! '.$message;
  287.             $doEchoByResponse false;
  288.             $toDo.= ' EXIT';
  289.  
  290.         }elseif($this->response == null){
  291.             $ret $this->initDefaultResponseOfRequest();
  292.             if(is_string($ret)){
  293.                 $message 'Double error ! 1)'$ret.'; 2)'.$message;
  294.                 $doEchoByResponse false;
  295.             }
  296.         }
  297.  
  298.         // When we are in cmdline we need to fix the remoteAddr
  299.         $remoteAddr = isset($_SERVER['REMOTE_ADDR']$_SERVER['REMOTE_ADDR''127.0.0.1';
  300.  
  301.         // url params including module and action
  302.         if ($this->request)
  303.             $url str_replace('array''url'var_export($this->request->paramstrue));
  304.         else $url 'Unknown url';
  305.  
  306.         // formatting message
  307.         $messageLog strtr($conf['messageLogFormat']array(
  308.             '%date%' => date("Y-m-d H:i:s"),
  309.             '%ip%'   => $remoteAddr,
  310.             '%typeerror%'=>$type,
  311.             '%code%' => $code,
  312.             '%msg%'  => $message,
  313.             '%url%'  => $url,
  314.             '%file%' => $file,
  315.             '%line%' => $line,
  316.             '\t' =>"\t",
  317.             '\n' => "\n"
  318.         ));
  319.  
  320.         if(strpos($toDo 'TRACE'!== false){
  321.             $messageLog.="\ttrace:";
  322.             foreach($trace as $k=>$t){
  323.                 $messageLog.="\n\t$k\t".(isset($t['class'])?$t['class'].$t['type']:'').$t['function']."()\t";
  324.                 $messageLog.=(isset($t['file'])?$t['file']:'[php]').' : '.(isset($t['line'])?$t['line']:'');
  325.             }
  326.             $messageLog.="\n";
  327.         }
  328.  
  329.  
  330.         $echoAsked false;
  331.         // traitement du message
  332.         if(strpos($toDo 'ECHOQUIET'!== false){
  333.             $echoAsked true;
  334.             if(!$doEchoByResponse){
  335.                 header("HTTP/1.1 500 Internal jelix error");
  336.                 header('Content-type: text/plain');
  337.                 echo 'JELIX PANIC ! Error during initialization !! ';
  338.             }elseif($this->addErrorMsg($type$code$conf['quietMessage']'''')){
  339.                 $toDo.=' EXIT';
  340.             }
  341.         }elseif(strpos($toDo 'ECHO'!== false){
  342.             $echoAsked true;
  343.             if(!$doEchoByResponse){
  344.                 header("HTTP/1.1 500 Internal jelix error");
  345.                 header('Content-type: text/plain');
  346.                 echo $messageLog;
  347.             }elseif($this->addErrorMsg($type$code$message$file$line)){
  348.                 $toDo.=' EXIT';
  349.             }
  350.         }
  351.  
  352.         if(strpos($toDo 'LOGFILE'!== false){
  353.             @error_log($messageLog,3JELIX_APP_LOG_PATH.$conf['logFile']);
  354.         }
  355.         if(strpos($toDo 'MAIL'!== false){
  356.             error_log(wordwrap($messageLog,70),1$conf['email']str_replace(array('\\r','\\n'),array("\r","\n"),$conf['emailHeaders']));
  357.         }
  358.         if(strpos($toDo 'SYSLOG'!== false){
  359.             error_log($messageLog,0);
  360.         }
  361.  
  362.         if(strpos($toDo 'EXIT'!== false){
  363.             if($doEchoByResponse{
  364.                 if ($this->response)
  365.                     $this->response->outputErrors();
  366.                 else if($echoAsked{
  367.                     header("HTTP/1.1 500 Internal jelix error");
  368.                     header('Content-type: text/plain');
  369.                     foreach($this->errorMessages as $msg)
  370.                         echo $msg."\n";
  371.                 }
  372.             }
  373.             jSession::end();
  374.             exit(1);
  375.         }
  376.     }
  377.  
  378.     /**
  379.      * Store an error/warning/notice message.
  380.      * @param  string $type  error type : 'error', 'warning', 'notice'
  381.      * @param  integer $code  error code
  382.      * @param  string $message error message
  383.      * @param  string $file    the file name where the error appear
  384.      * @param  integer $line  the line number where the error appear
  385.      * @return boolean    true= the process should stop now, false = the error manager do its job
  386.      */
  387.     protected function addErrorMsg($type$code$message$file$line){
  388.         $this->errorMessages[array($type$code$message$file$line);
  389.         return !$this->response->acceptSeveralErrors();
  390.     }
  391.  
  392.     /**
  393.      * Store a log message. Responses object should take care
  394.      * of the logMessages properties to display them.
  395.      * @param  string $message error message
  396.      * @since 1.0
  397.      */
  398.     public function addLogMsg($message$type='default'){
  399.         $this->logMessages[$type][$message;
  400.     }
  401.  
  402.     /**
  403.     * gets a given plugin if registered
  404.     * @param string   $pluginName   the name of the plugin
  405.     * @param boolean  $required  says if the plugin is required or not. If true, will generate an exception if the plugin is not registered.
  406.     * @return jICoordPlugin 
  407.     */
  408.     public function getPlugin ($pluginName$required true){
  409.         $pluginName strtolower ($pluginName);
  410.         if (isset ($this->plugins[$pluginName])){
  411.             $plugin $this->plugins[$pluginName];
  412.         }else{
  413.             if ($required){
  414.                 throw new jException('jelix~errors.plugin.unregister'$pluginName);
  415.             }
  416.             $plugin null;
  417.         }
  418.         return $plugin;
  419.     }
  420.  
  421.     /**
  422.     * Says if the given plugin $name is enabled
  423.     * @param string $pluginName 
  424.     * @return boolean true : plugin is ok
  425.     */
  426.     public function isPluginEnabled ($pluginName){
  427.         return isset ($this->plugins[strtolower ($pluginName)]);
  428.     }
  429.  
  430.     /**
  431.     * Says if the given module $name is enabled
  432.     * @param string $moduleName 
  433.     * @return boolean true : module is ok
  434.     */
  435.     public function isModuleEnabled ($moduleName){
  436.         return in_array($moduleName$GLOBALS['gJConfig']->_trustedModules);
  437.     }
  438.  
  439.     /**
  440.      * return the real path of a module
  441.      * @param string $module a module name
  442.      * @return string the corresponding path
  443.      */
  444.  
  445.     public function getModulePath($module){
  446.         global $gJConfig;
  447.         if(!isset($gJConfig->_modulesPathList[$module])){
  448.             throw new Exception('getModulePath : invalid module name');
  449.         }
  450.         return $gJConfig->_modulesPathList[$module];
  451.     }
  452. }

Documentation generated on Thu, 22 Mar 2012 22:14:31 +0100 by phpDocumentor 1.4.3