PageRenderTime 59ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/xe/classes/module/ModuleHandler.class.php

https://bitbucket.org/pipoket/hanu_xe
PHP | 779 lines | 556 code | 107 blank | 116 comment | 186 complexity | a5b139c9d5fdeb06bff8524e34c7ec1d MD5 | raw file
Possible License(s): LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @class ModuleHandler
  4. * @author NHN (developers@xpressengine.com)
  5. * @brief Handling modules
  6. *
  7. * @remarks This class is to excute actions of modules.
  8. * Constructing an instance without any parameterconstructor, it finds the target module based on Context.
  9. * If there is no act on the found module, excute an action referencing action_forward.
  10. **/
  11. class ModuleHandler extends Handler {
  12. var $module = NULL; ///< Module
  13. var $act = NULL; ///< action
  14. var $mid = NULL; ///< Module ID
  15. var $document_srl = NULL; ///< Document Number
  16. var $module_srl = NULL; ///< Module Number
  17. var $module_info = NULL; ///< Module Info. Object
  18. var $error = NULL; ///< an error code.
  19. var $httpStatusCode = NULL; ///< http status code.
  20. /**
  21. * @brief constructor
  22. * @remarks it prepares variables to use in moduleHandler
  23. **/
  24. function ModuleHandler($module = '', $act = '', $mid = '', $document_srl = '', $module_srl = '') {
  25. // If XE has not installed yet, set module as install
  26. if(!Context::isInstalled()) {
  27. $this->module = 'install';
  28. $this->act = Context::get('act');
  29. return;
  30. }
  31. // Set variables from request arguments
  32. $this->module = $module?$module:Context::get('module');
  33. $this->act = $act?$act:Context::get('act');
  34. $this->mid = $mid?$mid:Context::get('mid');
  35. $this->document_srl = $document_srl?(int)$document_srl:(int)Context::get('document_srl');
  36. $this->module_srl = $module_srl?(int)$module_srl:(int)Context::get('module_srl');
  37. $this->entry = Context::convertEncodingStr(Context::get('entry'));
  38. // Validate variables to prevent XSS
  39. $isInvalid = null;
  40. if($this->module && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->module)) $isInvalid = true;
  41. if($this->mid && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->mid)) $isInvalid = true;
  42. if($this->act && !preg_match("/^([a-z0-9\_\-]+)$/i",$this->act)) $isInvalid = true;
  43. if ($isInvalid)
  44. {
  45. htmlHeader();
  46. echo Context::getLang("msg_invalid_request");
  47. htmlFooter();
  48. Context::close();
  49. exit;
  50. }
  51. // execute addon (before module initialization)
  52. $called_position = 'before_module_init';
  53. $oAddonController = &getController('addon');
  54. $addon_file = $oAddonController->getCacheFilePath(Mobile::isFromMobilePhone()?'mobile':'pc');
  55. @include($addon_file);
  56. }
  57. /**
  58. * @brief Initialization. It finds the target module based on module, mid, document_srl, and prepares to execute an action
  59. * @return true: OK, false: redirected
  60. **/
  61. function init() {
  62. $oModuleModel = &getModel('module');
  63. $site_module_info = Context::get('site_module_info');
  64. if(!$this->document_srl && $this->mid && $this->entry) {
  65. $oDocumentModel = &getModel('document');
  66. $this->document_srl = $oDocumentModel->getDocumentSrlByAlias($this->mid, $this->entry);
  67. if($this->document_srl) Context::set('document_srl', $this->document_srl);
  68. }
  69. // Get module's information based on document_srl, if it's specified
  70. if($this->document_srl && !$this->module) {
  71. $module_info = $oModuleModel->getModuleInfoByDocumentSrl($this->document_srl);
  72. // If the document does not exist, remove document_srl
  73. if(!$module_info) {
  74. unset($this->document_srl);
  75. } else {
  76. // If it exists, compare mid based on the module information
  77. // if mids are not matching, set it as the document's mid
  78. if($this->mid != $module_info->mid) {
  79. $this->mid = $module_info->mid;
  80. Context::set('mid', $module_info->mid, true);
  81. }
  82. }
  83. // if requested module is different from one of the document, remove the module information retrieved based on the document number
  84. if($this->module && $module_info->module != $this->module) unset($module_info);
  85. }
  86. // If module_info is not set yet, and there exists mid information, get module information based on the mid
  87. if(!$module_info && $this->mid) {
  88. $module_info = $oModuleModel->getModuleInfoByMid($this->mid, $site_module_info->site_srl);
  89. //if($this->module && $module_info->module != $this->module) unset($module_info);
  90. }
  91. // redirect, if module_site_srl and site_srl are different
  92. if(!$this->module && !$module_info && $site_module_info->site_srl == 0 && $site_module_info->module_site_srl > 0) {
  93. $site_info = $oModuleModel->getSiteInfo($site_module_info->module_site_srl);
  94. header("location:".getNotEncodedSiteUrl($site_info->domain,'mid',$site_module_info->mid));
  95. return false;
  96. }
  97. // If module_info is not set still, and $module does not exist, find the default module
  98. if(!$module_info && !$this->module && !$this->mid) $module_info = $site_module_info;
  99. if(!$module_info && !$this->module && $site_module_info->module_site_srl) $module_info = $site_module_info;
  100. // redirect, if site_srl of module_info is different from one of site's module_info
  101. if($module_info && $module_info->site_srl != $site_module_info->site_srl && !isCrawler()) {
  102. // If the module is of virtual site
  103. if($module_info->site_srl) {
  104. $site_info = $oModuleModel->getSiteInfo($module_info->site_srl);
  105. $redirect_url = getNotEncodedSiteUrl($site_info->domain, 'mid',Context::get('mid'),'document_srl',Context::get('document_srl'),'module_srl',Context::get('module_srl'),'entry',Context::get('entry'));
  106. // If it's called from a virtual site, though it's not a module of the virtual site
  107. } else {
  108. $db_info = Context::getDBInfo();
  109. if(!$db_info->default_url) return Context::getLang('msg_default_url_is_not_defined');
  110. else $redirect_url = getNotEncodedSiteUrl($db_info->default_url, 'mid',Context::get('mid'),'document_srl',Context::get('document_srl'),'module_srl',Context::get('module_srl'),'entry',Context::get('entry'));
  111. }
  112. header("location:".$redirect_url);
  113. return false;
  114. }
  115. // If module info was set, retrieve variables from the module information
  116. if($module_info) {
  117. $this->module = $module_info->module;
  118. $this->mid = $module_info->mid;
  119. $this->module_info = $module_info;
  120. Context::setBrowserTitle($module_info->browser_title);
  121. $part_config= $oModuleModel->getModulePartConfig('layout',$module_info->layout_srl);
  122. Context::addHtmlHeader($part_config->header_script);
  123. }
  124. // Set module and mid into module_info
  125. $this->module_info->module = $this->module;
  126. $this->module_info->mid = $this->mid;
  127. // Set site_srl add 2011 08 09
  128. $this->module_info->site_srl = $site_module_info->site_srl;
  129. // Still no module? it's an error
  130. if(!$this->module)
  131. {
  132. $this->error = 'msg_module_is_not_exists';
  133. $this->httpStatusCode = '404';
  134. }
  135. // If mid exists, set mid into context
  136. if($this->mid) Context::set('mid', $this->mid, true);
  137. // Call a trigger after moduleHandler init
  138. $output = ModuleHandler::triggerCall('moduleHandler.init', 'after', $this->module_info);
  139. if(!$output->toBool()) {
  140. $this->error = $output->getMessage();
  141. return false;
  142. }
  143. // Set current module info into context
  144. Context::set('current_module_info', $this->module_info);
  145. return true;
  146. }
  147. /**
  148. * @brief get a module instance and execute an action
  149. * @return executed module instance
  150. **/
  151. function procModule() {
  152. $oModuleModel = &getModel('module');
  153. // If error occurred while preparation, return a message instance
  154. if($this->error) {
  155. $type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
  156. $oMessageObject = &ModuleHandler::getModuleInstance('message',$type);
  157. $oMessageObject->setError(-1);
  158. $oMessageObject->setMessage($this->error);
  159. $oMessageObject->dispMessage();
  160. if($this->httpStatusCode)
  161. {
  162. $oMessageObject->setHttpStatusCode($this->httpStatusCode);
  163. }
  164. return $oMessageObject;
  165. }
  166. // Get action information with conf/module.xml
  167. $xml_info = $oModuleModel->getModuleActionXml($this->module);
  168. // If not installed yet, modify act
  169. if($this->module=="install") {
  170. if(!$this->act || !$xml_info->action->{$this->act}) $this->act = $xml_info->default_index_act;
  171. }
  172. // if act exists, find type of the action, if not use default index act
  173. if(!$this->act) $this->act = $xml_info->default_index_act;
  174. // still no act means error
  175. if(!$this->act) {
  176. $this->error = 'msg_module_is_not_exists';
  177. $this->httpStatusCode = '404';
  178. return;
  179. }
  180. // get type, kind
  181. $type = $xml_info->action->{$this->act}->type;
  182. $ruleset = $xml_info->action->{$this->act}->ruleset;
  183. $kind = strpos(strtolower($this->act),'admin')!==false?'admin':'';
  184. if(!$kind && $this->module == 'admin') $kind = 'admin';
  185. if($this->module_info->use_mobile != "Y") Mobile::setMobile(false);
  186. // admin menu check
  187. if(Context::isInstalled())
  188. {
  189. $oMenuAdminModel = &getAdminModel('menu');
  190. $output = $oMenuAdminModel->getMenuByTitle('__XE_ADMIN__');
  191. if(!$output->menu_srl)
  192. {
  193. $oAdminClass = &getClass('admin');
  194. $oAdminClass->createXeAdminMenu();
  195. }
  196. else if(!is_readable($output->php_file))
  197. {
  198. $oMenuAdminController = &getAdminController('menu');
  199. $oMenuAdminController->makeXmlFile($output->menu_srl);
  200. }
  201. }
  202. // Admin ip
  203. $logged_info = Context::get('logged_info');
  204. if($kind == 'admin' && $_SESSION['denied_admin'] == 'Y'){
  205. $this->error = "msg_not_permitted_act";
  206. $oMessageObject = &ModuleHandler::getModuleInstance('message',$type);
  207. $oMessageObject->setError(-1);
  208. $oMessageObject->setMessage($this->error);
  209. $oMessageObject->dispMessage();
  210. return $oMessageObject;
  211. }
  212. // if(type == view, and case for using mobilephone)
  213. if($type == "view" && Mobile::isFromMobilePhone() && Context::isInstalled())
  214. {
  215. $orig_type = "view";
  216. $type = "mobile";
  217. // create a module instance
  218. $oModule = &$this->getModuleInstance($this->module, $type, $kind);
  219. if(!is_object($oModule) || !method_exists($oModule, $this->act)) {
  220. $type = $orig_type;
  221. Mobile::setMobile(false);
  222. $oModule = &$this->getModuleInstance($this->module, $type, $kind);
  223. }
  224. }
  225. else
  226. {
  227. // create a module instance
  228. $oModule = &$this->getModuleInstance($this->module, $type, $kind);
  229. }
  230. if(!is_object($oModule)) {
  231. $this->error = 'msg_module_is_not_exists';
  232. $this->httpStatusCode = '404';
  233. return;
  234. }
  235. // If there is no such action in the module object
  236. if(!isset($xml_info->action->{$this->act}) || !method_exists($oModule, $this->act))
  237. {
  238. if(!Context::isInstalled())
  239. {
  240. $this->error = 'msg_invalid_request';
  241. return;
  242. }
  243. $forward = null;
  244. // 1. Look for the module with action name
  245. if(preg_match('/^([a-z]+)([A-Z])([a-z0-9\_]+)(.*)$/', $this->act, $matches)) {
  246. $module = strtolower($matches[2].$matches[3]);
  247. $xml_info = $oModuleModel->getModuleActionXml($module);
  248. if($xml_info->action->{$this->act}) {
  249. $forward->module = $module;
  250. $forward->type = $xml_info->action->{$this->act}->type;
  251. $forward->ruleset = $xml_info->action->{$this->act}->ruleset;
  252. $forward->act = $this->act;
  253. }
  254. }
  255. if(!$forward)
  256. {
  257. $forward = $oModuleModel->getActionForward($this->act);
  258. }
  259. if($forward->module && $forward->type && $forward->act && $forward->act == $this->act) {
  260. $kind = strpos(strtolower($forward->act),'admin')!==false?'admin':'';
  261. $type = $forward->type;
  262. $ruleset = $forward->ruleset;
  263. $tpl_path = $oModule->getTemplatePath();
  264. $orig_module = $oModule;
  265. if($type == "view" && Mobile::isFromMobilePhone())
  266. {
  267. $orig_type = "view";
  268. $type = "mobile";
  269. // create a module instance
  270. $oModule = &$this->getModuleInstance($forward->module, $type, $kind);
  271. if(!is_object($oModule) || !method_exists($oModule, $this->act)) {
  272. $type = $orig_type;
  273. Mobile::setMobile(false);
  274. $oModule = &$this->getModuleInstance($forward->module, $type, $kind);
  275. }
  276. }
  277. else
  278. {
  279. $oModule = &$this->getModuleInstance($forward->module, $type, $kind);
  280. }
  281. $xml_info = $oModuleModel->getModuleActionXml($forward->module);
  282. $oMemberModel = &getModel('member');
  283. if($this->module == "admin" && $type == "view")
  284. {
  285. if($logged_info->is_admin=='Y'){
  286. if ($this->act != 'dispLayoutAdminLayoutModify')
  287. {
  288. $oAdminView = &getAdminView('admin');
  289. $oAdminView->makeGnbUrl($forward->module);
  290. $oModule->setLayoutPath("./modules/admin/tpl");
  291. $oModule->setLayoutFile("layout.html");
  292. }
  293. }else{
  294. $this->error = 'msg_is_not_administrator';
  295. $oMessageObject = &ModuleHandler::getModuleInstance('message',$type);
  296. $oMessageObject->setError(-1);
  297. $oMessageObject->setMessage($this->error);
  298. $oMessageObject->dispMessage();
  299. return $oMessageObject;
  300. }
  301. }
  302. if ($kind == 'admin'){
  303. $grant = $oModuleModel->getGrant($this->module_info, $logged_info);
  304. if(!$grant->is_admin && !$grant->manager) {
  305. $this->error = 'msg_is_not_manager';
  306. $oMessageObject = &ModuleHandler::getModuleInstance('message','view');
  307. $oMessageObject->setError(-1);
  308. $oMessageObject->setMessage($this->error);
  309. $oMessageObject->dispMessage();
  310. return $oMessageObject;
  311. }
  312. }
  313. }
  314. else if($xml_info->default_index_act && method_exists($oModule, $xml_info->default_index_act))
  315. {
  316. $this->act = $xml_info->default_index_act;
  317. }
  318. else
  319. {
  320. $this->error = 'msg_invalid_request';
  321. return;
  322. }
  323. }
  324. // ruleset check...
  325. if(!empty($ruleset))
  326. {
  327. $rulesetModule = $forward->module ? $forward->module : $this->module;
  328. $rulesetFile = $oModuleModel->getValidatorFilePath($rulesetModule, $ruleset);
  329. if(!empty($rulesetFile))
  330. {
  331. $Validator = new Validator($rulesetFile);
  332. $result = $Validator->validate();
  333. if(!$result)
  334. {
  335. $lastError = $Validator->getLastError();
  336. $returnUrl = Context::get('error_return_url');
  337. $errorMsg = $lastError['msg'] ? $lastError['msg'] : 'validation error';
  338. //for xml response
  339. $oModule->setError(-1);
  340. $oModule->setMessage($errorMsg);
  341. //for html redirect
  342. $this->error = $errorMsg;
  343. $_SESSION['XE_VALIDATOR_ERROR'] = -1;
  344. $_SESSION['XE_VALIDATOR_MESSAGE'] = $this->error;
  345. $_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = 'error';
  346. $_SESSION['XE_VALIDATOR_RETURN_URL'] = $returnUrl;
  347. $this->_setInputValueToSession();
  348. return $oModule;
  349. }
  350. }
  351. }
  352. $oModule->setAct($this->act);
  353. $this->module_info->module_type = $type;
  354. $oModule->setModuleInfo($this->module_info, $xml_info);
  355. if($type == "view" && $this->module_info->use_mobile == "Y" && Mobile::isMobileCheckByAgent())
  356. {
  357. global $lang;
  358. $footer = '<div style="margin:1em 0;padding:.5em;background:#333;border:1px solid #666;border-left:0;border-right:0"><p style="text-align:center;margin:1em 0"><a href="'.getUrl('m', '1').'" style="color:#ff0; font-weight:bold">'.$lang->msg_pc_to_mobile.'</a></p></div>';
  359. Context::addHtmlFooter($footer);
  360. }
  361. if($type == "view" && $kind != 'admin'){
  362. $module_config= $oModuleModel->getModuleConfig('module');
  363. if($module_config->htmlFooter){
  364. Context::addHtmlFooter($module_config->htmlFooter);
  365. }
  366. }
  367. // if failed message exists in session, set context
  368. $this->_setInputErrorToContext();
  369. $procResult = $oModule->proc();
  370. if(!in_array(Context::getRequestMethod(),array('XMLRPC','JSON')))
  371. {
  372. $error = $oModule->getError();
  373. $message = $oModule->getMessage();
  374. $messageType = $oModule->getMessageType();
  375. $redirectUrl = $oModule->getRedirectUrl();
  376. if (!$procResult)
  377. {
  378. $this->error = $message;
  379. if (!$redirectUrl && Context::get('error_return_url')) $redirectUrl = Context::get('error_return_url');
  380. $this->_setInputValueToSession();
  381. }
  382. else
  383. {
  384. if(count($_SESSION['INPUT_ERROR']))
  385. {
  386. Context::set('INPUT_ERROR', $_SESSION['INPUT_ERROR']);
  387. $_SESSION['INPUT_ERROR'] = '';
  388. }
  389. }
  390. $_SESSION['XE_VALIDATOR_ERROR'] = $error;
  391. if ($message != 'success') $_SESSION['XE_VALIDATOR_MESSAGE'] = $message;
  392. $_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = $messageType;
  393. $_SESSION['XE_VALIDATOR_RETURN_URL'] = $redirectUrl;
  394. }
  395. unset($logged_info);
  396. return $oModule;
  397. }
  398. function _setInputErrorToContext()
  399. {
  400. if($_SESSION['XE_VALIDATOR_ERROR'] && !Context::get('XE_VALIDATOR_ERROR')) Context::set('XE_VALIDATOR_ERROR', $_SESSION['XE_VALIDATOR_ERROR']);
  401. if($_SESSION['XE_VALIDATOR_MESSAGE'] && !Context::get('XE_VALIDATOR_MESSAGE')) Context::set('XE_VALIDATOR_MESSAGE', $_SESSION['XE_VALIDATOR_MESSAGE']);
  402. if($_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] && !Context::get('XE_VALIDATOR_MESSAGE_TYPE')) Context::set('XE_VALIDATOR_MESSAGE_TYPE', $_SESSION['XE_VALIDATOR_MESSAGE_TYPE']);
  403. if($_SESSION['XE_VALIDATOR_RETURN_URL'] && !Context::get('XE_VALIDATOR_RETURN_URL')) Context::set('XE_VALIDATOR_RETURN_URL', $_SESSION['XE_VALIDATOR_RETURN_URL']);
  404. $this->_clearErrorSession();
  405. }
  406. function _clearErrorSession()
  407. {
  408. $_SESSION['XE_VALIDATOR_ERROR'] = '';
  409. $_SESSION['XE_VALIDATOR_MESSAGE'] = '';
  410. $_SESSION['XE_VALIDATOR_MESSAGE_TYPE'] = '';
  411. $_SESSION['XE_VALIDATOR_RETURN_URL'] = '';
  412. }
  413. function _setInputValueToSession()
  414. {
  415. $requestVars = Context::getRequestVars();
  416. unset($requestVars->act, $requestVars->mid, $requestVars->vid, $requestVars->success_return_url, $requestVars->error_return_url);
  417. foreach($requestVars AS $key=>$value) $_SESSION['INPUT_ERROR'][$key] = $value;
  418. }
  419. /**
  420. * @brief display contents from executed module
  421. * @param[in] $oModule module instance
  422. * @return none
  423. **/
  424. function displayContent($oModule = NULL) {
  425. // If the module is not set or not an object, set error
  426. if(!$oModule || !is_object($oModule)) {
  427. $this->error = 'msg_module_is_not_exists';
  428. $this->httpStatusCode = '404';
  429. }
  430. // If connection to DB has a problem even though it's not install module, set error
  431. if($this->module != 'install' && $GLOBALS['__DB__'][Context::getDBType()]->isConnected() == false) {
  432. $this->error = 'msg_dbconnect_failed';
  433. }
  434. // Call trigger after moduleHandler proc
  435. $output = ModuleHandler::triggerCall('moduleHandler.proc', 'after', $oModule);
  436. if(!$output->toBool()) $this->error = $output->getMessage();
  437. // Use message view object, if HTML call
  438. if(!in_array(Context::getRequestMethod(),array('XMLRPC','JSON'))) {
  439. if($_SESSION['XE_VALIDATOR_RETURN_URL'])
  440. {
  441. header('location:'.$_SESSION['XE_VALIDATOR_RETURN_URL']);
  442. return;
  443. }
  444. // If error occurred, handle it
  445. if($this->error) {
  446. // display content with message module instance
  447. $type = Mobile::isFromMobilePhone() ? 'mobile' : 'view';
  448. $oMessageObject = &ModuleHandler::getModuleInstance('message',$type);
  449. $oMessageObject->setError(-1);
  450. $oMessageObject->setMessage($this->error);
  451. $oMessageObject->dispMessage();
  452. if($oMessageObject->getHttpStatusCode() && $oMessageObject->getHttpStatusCode() != '200')
  453. {
  454. $this->_setHttpStatusMessage($oMessageObject->getHttpStatusCode());
  455. $oMessageObject->setTemplateFile('http_status_code');
  456. }
  457. // If module was called normally, change the templates of the module into ones of the message view module
  458. if($oModule) {
  459. $oModule->setTemplatePath($oMessageObject->getTemplatePath());
  460. $oModule->setTemplateFile($oMessageObject->getTemplateFile());
  461. // Otherwise, set message instance as the target module
  462. } else {
  463. $oModule = $oMessageObject;
  464. }
  465. $this->_clearErrorSession();
  466. }
  467. // Check if layout_srl exists for the module
  468. if(Mobile::isFromMobilePhone())
  469. {
  470. $layout_srl = $oModule->module_info->mlayout_srl;
  471. }
  472. else
  473. {
  474. $layout_srl = $oModule->module_info->layout_srl;
  475. }
  476. if($layout_srl && !$oModule->getLayoutFile()) {
  477. // If layout_srl exists, get information of the layout, and set the location of layout_path/ layout_file
  478. $oLayoutModel = &getModel('layout');
  479. $layout_info = $oLayoutModel->getLayout($layout_srl);
  480. if($layout_info) {
  481. // Input extra_vars into $layout_info
  482. if($layout_info->extra_var_count) {
  483. foreach($layout_info->extra_var as $var_id => $val) {
  484. if($val->type == 'image') {
  485. if(preg_match('/^\.\/files\/attach\/images\/(.+)/i',$val->value)) $val->value = Context::getRequestUri().substr($val->value,2);
  486. }
  487. $layout_info->{$var_id} = $val->value;
  488. }
  489. }
  490. // Set menus into context
  491. if($layout_info->menu_count) {
  492. foreach($layout_info->menu as $menu_id => $menu) {
  493. if(file_exists($menu->php_file)) @include($menu->php_file);
  494. Context::set($menu_id, $menu);
  495. }
  496. }
  497. // Set layout information into context
  498. Context::set('layout_info', $layout_info);
  499. $oModule->setLayoutPath($layout_info->path);
  500. $oModule->setLayoutFile('layout');
  501. // If layout was modified, use the modified version
  502. $edited_layout = $oLayoutModel->getUserLayoutHtml($layout_info->layout_srl);
  503. if(file_exists($edited_layout)) $oModule->setEditedLayoutFile($edited_layout);
  504. }
  505. }
  506. }
  507. // Display contents
  508. $oDisplayHandler = new DisplayHandler();
  509. $oDisplayHandler->printContent($oModule);
  510. }
  511. /**
  512. * @brief returns module's path
  513. * @param[in] $module module name
  514. * @return path of the module
  515. **/
  516. function getModulePath($module) {
  517. return sprintf('./modules/%s/', $module);
  518. }
  519. /**
  520. * @brief It creates a module instance
  521. * @param[in] $module module name
  522. * @param[in] $type instance type, (e.g., view, controller, model)
  523. * @param[in] $kind admin or svc
  524. * @return module instance (if failed it returns null)
  525. * @remarks if there exists a module instance created before, returns it.
  526. **/
  527. function &getModuleInstance($module, $type = 'view', $kind = '') {
  528. if(__DEBUG__==3) $start_time = getMicroTime();
  529. $kind = strtolower($kind);
  530. $type = strtolower($type);
  531. $kinds = explode(' ', 'svc admin');
  532. if(!in_array($kind, $kinds)) $kind = $kinds[0];
  533. $key = $module.'.'.($kind!='admin'?'':'admin').'.'.$type;
  534. if(is_array($GLOBALS['__MODULE_EXTEND__']) && array_key_exists($key, $GLOBALS['__MODULE_EXTEND__'])) {
  535. $module = $extend_module = $GLOBALS['__MODULE_EXTEND__'][$key];
  536. }else{
  537. unset($parent_module);
  538. }
  539. // if there is no instance of the module in global variable, create a new one
  540. if(!$GLOBALS['_loaded_module'][$module][$type][$kind]) {
  541. $parent_module = $module;
  542. $class_path = ModuleHandler::getModulePath($module);
  543. if(!is_dir(FileHandler::getRealPath($class_path))) return NULL;
  544. // Get base class name and load the file contains it
  545. if(!class_exists($module)) {
  546. $high_class_file = sprintf('%s%s%s.class.php', _XE_PATH_,$class_path, $module);
  547. if(!file_exists($high_class_file)) return NULL;
  548. require_once($high_class_file);
  549. }
  550. // Get the object's name
  551. $types = explode(' ', 'view controller model api wap mobile class');
  552. if(!in_array($type, $types)) $type = $types[0];
  553. if($type == 'class') {
  554. $instance_name = '%s';
  555. $class_file = '%s%s.%s.php';
  556. } elseif($kind == 'admin' && array_search($type, $types) < 3) {
  557. $instance_name = '%sAdmin%s';
  558. $class_file = '%s%s.admin.%s.php';
  559. } else{
  560. $instance_name = '%s%s';
  561. $class_file = '%s%s.%s.php';
  562. }
  563. $instance_name = sprintf($instance_name, $module, ucfirst($type));
  564. $class_file = sprintf($class_file, $class_path, $module, $type);
  565. $class_file = FileHandler::getRealPath($class_file);
  566. // Get the name of the class file
  567. if(!is_readable($class_file)) return NULL;
  568. // Create an instance with eval function
  569. require_once($class_file);
  570. if(!class_exists($instance_name)) return NULL;
  571. $tmp_fn = create_function('', "return new {$instance_name}();");
  572. $oModule = $tmp_fn();
  573. if(!is_object($oModule)) return NULL;
  574. // Load language files for the class
  575. Context::loadLang($class_path.'lang');
  576. if($extend_module) {
  577. Context::loadLang(ModuleHandler::getModulePath($parent_module).'lang');
  578. }
  579. // Set variables to the instance
  580. $oModule->setModule($module);
  581. $oModule->setModulePath($class_path);
  582. // If the module has a constructor, run it.
  583. if(!isset($GLOBALS['_called_constructor'][$instance_name])) {
  584. $GLOBALS['_called_constructor'][$instance_name] = true;
  585. if(@method_exists($oModule, $instance_name)) $oModule->{$instance_name}();
  586. }
  587. // Store the created instance into GLOBALS variable
  588. $GLOBALS['_loaded_module'][$module][$type][$kind] = $oModule;
  589. }
  590. if(__DEBUG__==3) $GLOBALS['__elapsed_class_load__'] += getMicroTime() - $start_time;
  591. // return the instance
  592. return $GLOBALS['_loaded_module'][$module][$type][$kind];
  593. }
  594. /**
  595. * @brief call a trigger
  596. * @param[in] $trigger_name trigger's name to call
  597. * @param[in] $called_position called position
  598. * @param[in] $obj an object as a parameter to trigger
  599. * @return Object
  600. **/
  601. function triggerCall($trigger_name, $called_position, &$obj) {
  602. // skip if not installed
  603. if(!Context::isInstalled()) return new Object();
  604. $oModuleModel = &getModel('module');
  605. $triggers = $oModuleModel->getTriggers($trigger_name, $called_position);
  606. if(!$triggers || !count($triggers)) return new Object();
  607. foreach($triggers as $item) {
  608. $module = $item->module;
  609. $type = $item->type;
  610. $called_method = $item->called_method;
  611. $oModule = null;
  612. $oModule = &getModule($module, $type);
  613. if(!$oModule || !method_exists($oModule, $called_method)) continue;
  614. $output = $oModule->{$called_method}($obj);
  615. if(is_object($output) && method_exists($output, 'toBool') && !$output->toBool()) return $output;
  616. unset($oModule);
  617. }
  618. return new Object();
  619. }
  620. /**
  621. * @brief get http status message by http status code
  622. **/
  623. function _setHttpStatusMessage($code) {
  624. $statusMessageList = array(
  625. '100'=>'Continue',
  626. '101'=>'Switching Protocols',
  627. '201'=>'OK',
  628. '201'=>'Created',
  629. '202'=>'Accepted',
  630. '203'=>'Non-Authoritative Information',
  631. '204'=>'No Content',
  632. '205'=>'Reset Content',
  633. '206'=>'Partial Content',
  634. '300'=>'Multiple Choices',
  635. '301'=>'Moved Permanently',
  636. '302'=>'Found',
  637. '303'=>'See Other',
  638. '304'=>'Not Modified',
  639. '305'=>'Use Proxy',
  640. '307'=>'Temporary Redirect',
  641. '400'=>'Bad Request',
  642. '401'=>'Unauthorized',
  643. '402'=>'Payment Required',
  644. '403'=>'Forbidden',
  645. '404'=>'Not Found',
  646. '405'=>'Method Not Allowed',
  647. '406'=>'Not Acceptable',
  648. '407'=>'Proxy Authentication Required',
  649. '408'=>'Request Timeout',
  650. '409'=>'Conflict',
  651. '410'=>'Gone',
  652. '411'=>'Length Required',
  653. '412'=>'Precondition Failed',
  654. '413'=>'Request Entity Too Large',
  655. '414'=>'Request-URI Too Long',
  656. '415'=>'Unsupported Media Type',
  657. '416'=>'Requested Range Not Satisfiable',
  658. '417'=>'Expectation Failed',
  659. '500'=>'Internal Server Error',
  660. '501'=>'Not Implemented',
  661. '502'=>'Bad Gateway',
  662. '503'=>'Service Unavailable',
  663. '504'=>'Gateway Timeout',
  664. '505'=>'HTTP Version Not Supported',
  665. );
  666. $statusMessage = $statusMessageList[$code];
  667. if(!$statusMessage) $statusMessage = 'OK';
  668. Context::set('http_status_code', $code);
  669. Context::set('http_status_message', $statusMessage);
  670. }
  671. }
  672. ?>