PageRenderTime 30ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/jelix/core/jCoordinator.class.php

https://github.com/foxmask/Booster
PHP | 418 lines | 228 code | 53 blank | 137 comment | 45 complexity | ec658e8e9221376e6f45bcf0e1828e8c MD5 | raw file
  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-2011 laurent Jouanneau
  8. * @copyright 2007 Thibault Piront
  9. * @copyright 2008 Julien Issler
  10. * @copyright 2008-2010 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. * the main class of the jelix core
  16. *
  17. * this is the "chief orchestra" of the framework. Its goal is
  18. * to load the configuration, to get the request parameters
  19. * used to instancie the correspondant controllers and to run the right method.
  20. * @package jelix
  21. * @subpackage core
  22. */
  23. class jCoordinator {
  24. /**
  25. * plugin list
  26. * @var array
  27. */
  28. public $plugins = array();
  29. /**
  30. * current response object
  31. * @var jResponse
  32. */
  33. public $response = null;
  34. /**
  35. * current request object
  36. * @var jRequest
  37. */
  38. public $request = null;
  39. /**
  40. * the selector of the current action
  41. * @var jSelectorAct
  42. */
  43. public $action = null;
  44. /**
  45. * the current module name
  46. * @var string
  47. */
  48. public $moduleName;
  49. /**
  50. * the current action name
  51. * @var string
  52. */
  53. public $actionName;
  54. /**
  55. * List of all errors appears during the initialisation
  56. * @var array array of jLogErrorMessage
  57. */
  58. protected $initErrorMessages=array();
  59. /**
  60. * the current error message
  61. * @var jLogErrorMessage
  62. */
  63. protected $errorMessage = null;
  64. /**
  65. * @param string $configFile name of the ini file to configure the framework
  66. * @param boolean $enableErrorHandler enable the error handler of jelix.
  67. * keep it to true, unless you have something to debug
  68. * and really have to use the default handler or an other handler
  69. */
  70. function __construct ($configFile, $enableErrorHandler=true) {
  71. global $gJCoord, $gJConfig;
  72. // temporary init. Remove this line when JELIX_APP_* support will be removed completely from Jelix
  73. jApp::initLegacy();
  74. $gJCoord = $this;
  75. if ($enableErrorHandler) {
  76. set_error_handler('jErrorHandler');
  77. set_exception_handler('JExceptionHandler');
  78. }
  79. // load configuration data
  80. $gJConfig = jConfig::load($configFile);
  81. date_default_timezone_set($gJConfig->timeZone);
  82. $this->_loadPlugins();
  83. }
  84. /**
  85. * load the plugins and their configuration file
  86. */
  87. private function _loadPlugins(){
  88. global $gJConfig;
  89. foreach ($gJConfig->coordplugins as $name=>$conf) {
  90. // the config compiler has removed all deactivated plugins
  91. // so we don't have to check if the value $conf is empty or not
  92. if ($conf == '1') {
  93. $confname = 'coordplugin_'.$name;
  94. if (isset($gJConfig->confname))
  95. $conf = $gJConfig->confname;
  96. else
  97. $conf = array();
  98. }
  99. else {
  100. $conff = jApp::configPath($conf);
  101. if (false === ($conf = parse_ini_file($conff,true)))
  102. throw new Exception("Error in the configuration file of plugin $name ($conff)!", 13);
  103. }
  104. include( $gJConfig->_pluginsPathList_coord[$name].$name.'.coord.php');
  105. $class= $name.'CoordPlugin';
  106. $this->plugins[strtolower($name)] = new $class($conf);
  107. }
  108. }
  109. /**
  110. * main method : launch the execution of the action.
  111. *
  112. * This method should be called in a entry point.
  113. * @param jRequest $request the request object
  114. */
  115. public function process ($request){
  116. global $gJConfig;
  117. $this->request = $request;
  118. // let's log messages appeared during init
  119. foreach($this->initErrorMessages as $msg) {
  120. jLog::log($msg, $msg->getCategory());
  121. }
  122. $this->request->init();
  123. jSession::start();
  124. $this->moduleName = $request->getParam('module');
  125. $this->actionName = $request->getParam('action');
  126. if(empty($this->moduleName)){
  127. $this->moduleName = $gJConfig->startModule;
  128. }
  129. if(empty($this->actionName)){
  130. if($this->moduleName == $gJConfig->startModule)
  131. $this->actionName = $gJConfig->startAction;
  132. else {
  133. $this->actionName = 'default:index';
  134. }
  135. }
  136. jContext::push ($this->moduleName);
  137. try{
  138. $this->action = new jSelectorActFast($this->request->type, $this->moduleName, $this->actionName);
  139. if($gJConfig->modules[$this->moduleName.'.access'] < 2){
  140. throw new jException('jelix~errors.module.untrusted',$this->moduleName);
  141. }
  142. $ctrl = $this->getController($this->action);
  143. }catch(jException $e){
  144. if ($gJConfig->urlengine['notfoundAct'] =='') {
  145. throw $e;
  146. }
  147. try {
  148. $this->action = new jSelectorAct($gJConfig->urlengine['notfoundAct']);
  149. $ctrl = $this->getController($this->action);
  150. }catch(jException $e2){
  151. throw $e;
  152. }
  153. }
  154. if (count($this->plugins)) {
  155. $pluginparams = array();
  156. if(isset($ctrl->pluginParams['*'])){
  157. $pluginparams = $ctrl->pluginParams['*'];
  158. }
  159. if(isset($ctrl->pluginParams[$this->action->method])){
  160. $pluginparams = array_merge($pluginparams, $ctrl->pluginParams[$this->action->method]);
  161. }
  162. foreach ($this->plugins as $name => $obj){
  163. $result = $this->plugins[$name]->beforeAction ($pluginparams);
  164. if($result){
  165. $this->action = $result;
  166. jContext::pop();
  167. jContext::push($result->module);
  168. $this->moduleName = $result->module;
  169. $this->actionName = $result->resource;
  170. $ctrl = $this->getController($this->action);
  171. break;
  172. }
  173. }
  174. }
  175. $this->response = $ctrl->{$this->action->method}();
  176. if($this->response == null){
  177. throw new jException('jelix~errors.response.missing',$this->action->toString());
  178. }
  179. foreach ($this->plugins as $name => $obj){
  180. $this->plugins[$name]->beforeOutput ();
  181. }
  182. $this->response->output();
  183. foreach ($this->plugins as $name => $obj){
  184. $this->plugins[$name]->afterProcess ();
  185. }
  186. jContext::pop();
  187. jSession::end();
  188. }
  189. /**
  190. * get the controller corresponding to the selector
  191. * @param jSelectorAct $selector
  192. */
  193. private function getController($selector){
  194. $ctrlpath = $selector->getPath();
  195. if(!file_exists($ctrlpath)){
  196. throw new jException('jelix~errors.ad.controller.file.unknown',array($this->actionName,$ctrlpath));
  197. }
  198. require_once($ctrlpath);
  199. $class = $selector->getClass();
  200. if(!class_exists($class,false)){
  201. throw new jException('jelix~errors.ad.controller.class.unknown',array($this->actionName,$class, $ctrlpath));
  202. }
  203. $ctrl = new $class($this->request);
  204. if($ctrl instanceof jIRestController){
  205. $method = $selector->method = strtolower($_SERVER['REQUEST_METHOD']);
  206. }elseif(!method_exists($ctrl, $selector->method)){
  207. throw new jException('jelix~errors.ad.controller.method.unknown',array($this->actionName, $selector->method, $class, $ctrlpath));
  208. }
  209. return $ctrl;
  210. }
  211. /**
  212. * instancy a response object corresponding to the default response type
  213. * of the current resquest.
  214. * Deprecated. use $request->getResponse() instead.
  215. * @param boolean $originalResponse TRUE to get the original, non overloaded response
  216. * @deprecated since 1.3
  217. */
  218. public function initDefaultResponseOfRequest($originalResponse = false){
  219. try {
  220. $this->request->getResponse('', $originalResponse);
  221. }
  222. catch (Exception $e) {
  223. if (!$originalResponse)
  224. $this->initDefaultResponseOfRequest(true);
  225. else
  226. throw $e;
  227. }
  228. }
  229. /**
  230. * Handle an error event. Called by error handler and exception handler.
  231. * @param string $type error type : 'error', 'warning', 'notice'
  232. * @param integer $code error code
  233. * @param string $message error message
  234. * @param string $file the file name where the error appear
  235. * @param integer $line the line number where the error appear
  236. * @param array $trace the stack trace
  237. * @since 1.1
  238. */
  239. public function handleError($type, $code, $message, $file, $line, $trace){
  240. global $gJConfig;
  241. $errorLog = new jLogErrorMessage($type, $code, $message, $file, $line, $trace);
  242. if ($this->request) {
  243. // we have config, so we can process "normally"
  244. $errorLog->setFormat($gJConfig->error_handling['messageLogFormat']);
  245. jLog::log($errorLog, $type);
  246. // if non fatal error, it is finished
  247. if ($type != 'error')
  248. return;
  249. $this->errorMessage = $errorLog;
  250. while (ob_get_level() && @ob_end_clean());
  251. $resp = $this->request->getErrorResponse($this->response);
  252. $resp->outputErrors();
  253. jSession::end();
  254. }
  255. // for non fatal error appeared during init, let's just store it for loggers later
  256. elseif ($type != 'error') {
  257. $this->initErrorMessages[] = $errorLog;
  258. return;
  259. }
  260. else {
  261. // fatal error appeared during init, let's display an HTML page
  262. // since we don't know the request, we cannot return a response
  263. // corresponding to the expected protocol
  264. while (ob_get_level() && @ob_end_clean());
  265. // log into file
  266. @error_log($errorLog->getFormatedMessage(),3, jApp::logPath('errors.log'));
  267. // if accept text/html
  268. if (isset($_SERVER['HTTP_ACCEPT']) && strstr($_SERVER['HTTP_ACCEPT'],'text/html')) {
  269. if (file_exists(jApp::appPath('responses/error.en_US.php')))
  270. $file = jApp::appPath('responses/error.en_US.php');
  271. else
  272. $file = JELIX_LIB_CORE_PATH.'response/error.en_US.php';
  273. $HEADBOTTOM = '';
  274. $BODYTOP = '';
  275. $BODYBOTTOM = '';
  276. $basePath = '';
  277. header("HTTP/1.1 500 Internal jelix error");
  278. header('Content-type: text/html');
  279. include($file);
  280. }
  281. else {
  282. // output text response
  283. header("HTTP/1.1 500 Internal jelix error");
  284. header('Content-type: text/plain');
  285. echo 'Error during initialization.';
  286. }
  287. }
  288. exit(1);
  289. }
  290. /**
  291. * return the generic error message (errorMessage in the configuration).
  292. * Replaced the %code% pattern in the message by the current error code
  293. * @return string
  294. */
  295. public function getGenericErrorMessage() {
  296. $msg = $GLOBALS['gJConfig']->error_handling['errorMessage'];
  297. if ($this->errorMessage)
  298. $code = $this->errorMessage->getCode();
  299. else $code = '';
  300. return str_replace('%code%', $code, $msg);
  301. }
  302. /**
  303. * @return jLogErrorMessage the current error
  304. * @since 1.3a1
  305. */
  306. public function getErrorMessage() {
  307. return $this->errorMessage;
  308. }
  309. /**
  310. * gets a given coordinator plugin if registered
  311. * @param string $pluginName the name of the plugin
  312. * @param boolean $required says if the plugin is required or not. If true, will generate an exception if the plugin is not registered.
  313. * @return jICoordPlugin
  314. */
  315. public function getPlugin ($pluginName, $required = true){
  316. $pluginName = strtolower ($pluginName);
  317. if (isset ($this->plugins[$pluginName])){
  318. $plugin = $this->plugins[$pluginName];
  319. }else{
  320. if ($required){
  321. throw new jException('jelix~errors.plugin.unregister', $pluginName);
  322. }
  323. $plugin = null;
  324. }
  325. return $plugin;
  326. }
  327. /**
  328. * Says if the given coordinator plugin $name is enabled
  329. * @param string $pluginName
  330. * @return boolean true : plugin is ok
  331. */
  332. public function isPluginEnabled ($pluginName){
  333. return isset ($this->plugins[strtolower ($pluginName)]);
  334. }
  335. /**
  336. * Says if the given module $name is enabled
  337. * @param string $moduleName
  338. * @param boolean $includingExternal true if we want to know if the module
  339. * is also an external module, e.g. in an other entry point
  340. * @return boolean true : module is ok
  341. */
  342. public function isModuleEnabled ($moduleName, $includingExternal = false) {
  343. if ($includingExternal && isset($GLOBALS['gJConfig']->_externalModulesPathList[$moduleName])) {
  344. return true;
  345. }
  346. return isset($GLOBALS['gJConfig']->_modulesPathList[$moduleName]);
  347. }
  348. /**
  349. * return the real path of a module
  350. * @param string $module a module name
  351. * @param boolean $includingExternal true if we want to know if the module
  352. * is also an external module, e.g. in an other entry point
  353. * @return string the corresponding path
  354. */
  355. public function getModulePath($module, $includingExternal = false){
  356. global $gJConfig;
  357. if (!isset($gJConfig->_modulesPathList[$module])) {
  358. if ($includingExternal && isset($gJConfig->_externalModulesPathList[$module])) {
  359. return $gJConfig->_externalModulesPathList[$module];
  360. }
  361. throw new Exception('getModulePath : invalid module name');
  362. }
  363. return $gJConfig->_modulesPathList[$module];
  364. }
  365. }