/frontend/core/engine/block.php

https://github.com/jasonweng/forkcms · PHP · 537 lines · 183 code · 79 blank · 275 comment · 27 complexity · 76b550f4a123aa05aee227e5c321fa22 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of Fork CMS.
  4. *
  5. * For the full copyright and license information, please view the license
  6. * file that was distributed with this source code.
  7. */
  8. /**
  9. * This class will handle all stuff related to blocks
  10. *
  11. * @author Tijs Verkoyen <tijs@sumocoders.be>
  12. * @author Dieter Vanden Eynde <dieter@dieterve.be>
  13. * @author Matthias Mullie <matthias@mullie.eu>
  14. */
  15. class FrontendBlockExtra extends FrontendBaseObject
  16. {
  17. /**
  18. * The current action
  19. *
  20. * @var string
  21. */
  22. private $action;
  23. /**
  24. * The configfile
  25. *
  26. * @var FrontendBaseConfig
  27. */
  28. private $config;
  29. /**
  30. * The data that was passed by the extra
  31. *
  32. * @var mixed
  33. */
  34. private $data;
  35. /**
  36. * The current module
  37. *
  38. * @var string
  39. */
  40. private $module;
  41. /**
  42. * The extra object
  43. *
  44. * @var FrontendBaseBlock
  45. */
  46. private $object;
  47. /**
  48. * The block's output
  49. *
  50. * @var string
  51. */
  52. private $output;
  53. /**
  54. * Should the template overwrite the current one
  55. *
  56. * @var bool
  57. */
  58. protected $overwrite = false;
  59. /**
  60. * The path for the template
  61. *
  62. * @var string
  63. */
  64. protected $templatePath = '';
  65. /**
  66. * @param string $module The module to load.
  67. * @param string $action The action to load.
  68. * @param mixed[optional] $data The data that was passed from the database.
  69. */
  70. public function __construct($module, $action, $data = null)
  71. {
  72. parent::__construct();
  73. // set properties
  74. $this->setModule($module);
  75. $this->setAction($action);
  76. if($data !== null) $this->setData($data);
  77. // load the configfile for the required module
  78. $this->loadConfig();
  79. // is the requested action possible? If not we throw an exception. We don't redirect because that could trigger a redirect loop
  80. if(!in_array($this->getAction(), $this->config->getPossibleActions())) $this->setAction($this->config->getDefaultAction());
  81. }
  82. /**
  83. * Execute the action
  84. * We will build the classname, require the class and call the execute method.
  85. */
  86. public function execute()
  87. {
  88. // build action-class-name
  89. $actionClassName = 'Frontend' . SpoonFilter::toCamelCase($this->getModule() . '_' . $this->getAction());
  90. // require the config file, we know it is there because we validated it before (possible actions are defined by existance off the file).
  91. require_once FRONTEND_MODULES_PATH . '/' . $this->getModule() . '/actions/' . $this->getAction() . '.php';
  92. // validate if class exists (aka has correct name)
  93. if(!class_exists($actionClassName)) throw new FrontendException('The actionfile is present, but the classname should be: ' . $actionClassName . '.');
  94. // create action-object
  95. $this->object = new $actionClassName($this->getModule(), $this->getAction(), $this->getData());
  96. // validate if the execute-method is callable
  97. if(!is_callable(array($this->object, 'execute'))) throw new FrontendException('The actionfile should contain a callable method "execute".');
  98. // call the execute method of the real action (defined in the module)
  99. $this->object->execute();
  100. // set some properties
  101. $this->setOverwrite($this->object->getOverwrite());
  102. if($this->object->getTemplatePath() !== null) $this->setTemplatePath($this->object->getTemplatePath());
  103. }
  104. /**
  105. * Get the current action
  106. * REMARK: You should not use this method from your code, but it has to be public so we can access it later on in the core-code
  107. *
  108. * @return string
  109. */
  110. public function getAction()
  111. {
  112. // no action specified?
  113. if($this->action === null)
  114. {
  115. // get first parameter
  116. $actionParameter = $this->URL->getParameter(0);
  117. // unknown action and not provided in URL
  118. if($actionParameter === null) $this->setAction($this->config->getDefaultAction());
  119. // action provided in the URL
  120. else
  121. {
  122. // loop possible actions
  123. foreach($this->config->getPossibleActions() as $actionName)
  124. {
  125. // get action that should be passed as parameter
  126. $actionURL = urlencode(FL::act(SpoonFilter::toCamelCase($actionName)));
  127. // the action is the requested one
  128. if($actionURL == $actionParameter)
  129. {
  130. // set action
  131. $this->setAction($actionName);
  132. // stop the loop
  133. break;
  134. }
  135. }
  136. }
  137. }
  138. return $this->action;
  139. }
  140. /**
  141. * Get the block content
  142. *
  143. * @return string
  144. */
  145. public function getContent()
  146. {
  147. // set path to template if the widget didnt return any data
  148. if($this->output === null) $this->output = $this->object->getContent();
  149. // return possible output
  150. return $this->output;
  151. }
  152. /**
  153. * Get the data
  154. *
  155. * @return mixed
  156. */
  157. public function getData()
  158. {
  159. return $this->data;
  160. }
  161. /**
  162. * Get the current module
  163. * REMARK: You should not use this method from your code, but it has to be public so we can access it later on in the core-code
  164. *
  165. * @return string
  166. */
  167. public function getModule()
  168. {
  169. return $this->module;
  170. }
  171. /**
  172. * Get overwrite mode
  173. *
  174. * @return bool
  175. */
  176. public function getOverwrite()
  177. {
  178. return $this->overwrite;
  179. }
  180. /**
  181. * Get the assigned template.
  182. *
  183. * @return array
  184. */
  185. public function getTemplate()
  186. {
  187. return $this->object->getTemplate();
  188. }
  189. /**
  190. * Get path for the template
  191. *
  192. * @return string
  193. */
  194. public function getTemplatePath()
  195. {
  196. return $this->templatePath;
  197. }
  198. /**
  199. * Get the assigned variables for this block.
  200. *
  201. * @return array
  202. */
  203. public function getVariables()
  204. {
  205. return (array) $this->tpl->getAssignedVariables();
  206. }
  207. /**
  208. * Load the config file for the requested block.
  209. * In the config file we have to find dissabled actions, the constructor will read the folder and set possible actions
  210. * Other configurations will also be stored in it.
  211. */
  212. public function loadConfig()
  213. {
  214. // build path for core
  215. if($this->getModule() == 'core') $frontendModulePath = FRONTEND_PATH . '/' . $this->getModule();
  216. // build path to the module and define it. This is a constant because we can use this in templates.
  217. else $frontendModulePath = FRONTEND_MODULES_PATH . '/' . $this->getModule();
  218. // check if the config is present? If it isn't present there is a huge problem, so we will stop our code by throwing an error
  219. if(!SpoonFile::exists($frontendModulePath . '/config.php')) throw new FrontendException('The configfile for the module (' . $this->getModule() . ') can\'t be found.');
  220. // build config-object-name
  221. $configClassName = 'Frontend' . SpoonFilter::toCamelCase($this->getModule() . '_config');
  222. // require the config file, we validated before for existence.
  223. require_once $frontendModulePath . '/config.php';
  224. // validate if class exists (aka has correct name)
  225. if(!class_exists($configClassName)) throw new FrontendException('The config file is present, but the classname should be: ' . $configClassName . '.');
  226. // create config-object, the constructor will do some magic
  227. $this->config = new $configClassName($this->getModule());
  228. }
  229. /**
  230. * Set the action
  231. *
  232. * @param string[optional] $action The action to load.
  233. */
  234. private function setAction($action = null)
  235. {
  236. if($action !== null) $this->action = (string) $action;
  237. }
  238. /**
  239. * Set the data
  240. *
  241. * @param mixed $data The data that should be set.
  242. */
  243. private function setData($data)
  244. {
  245. $this->data = $data;
  246. }
  247. /**
  248. * Set the module
  249. *
  250. * @param string $module The module to load.
  251. */
  252. private function setModule($module)
  253. {
  254. $this->module = (string) $module;
  255. }
  256. /**
  257. * Set overwrite mode
  258. *
  259. * @param bool $overwrite Should the template overwrite the already loaded template.
  260. */
  261. private function setOverwrite($overwrite)
  262. {
  263. $this->overwrite = (bool) $overwrite;
  264. }
  265. /**
  266. * Set the path for the template
  267. *
  268. * @param string $path The path to set.
  269. */
  270. private function setTemplatePath($path)
  271. {
  272. $this->templatePath = FrontendTheme::getPath($path);
  273. }
  274. }
  275. /**
  276. * This class will handle all stuff related to widgets
  277. *
  278. * @author Tijs Verkoyen <tijs@sumocoders.be>
  279. * @author Dieter Vanden Eynde <dieter@dieterve.be>
  280. * @author Matthias Mullie <matthias@mullie.eu>
  281. */
  282. class FrontendBlockWidget extends FrontendBaseObject
  283. {
  284. /**
  285. * The current action
  286. *
  287. * @var string
  288. */
  289. private $action;
  290. /**
  291. * The configfile
  292. *
  293. * @var FrontendBaseConfig
  294. */
  295. private $config;
  296. /**
  297. * The data that was passed by the extra
  298. *
  299. * @var mixed
  300. */
  301. private $data;
  302. /**
  303. * The current module
  304. *
  305. * @var string
  306. */
  307. private $module;
  308. /**
  309. * The extra object
  310. *
  311. * @var FrontendBaseWidget
  312. */
  313. private $object;
  314. /**
  315. * The block's output
  316. *
  317. * @var string
  318. */
  319. private $output;
  320. /**
  321. * @param string $module The module to load.
  322. * @param string $action The action to load.
  323. * @param mixed[optional] $data The data that was passed from the database.
  324. */
  325. public function __construct($module, $action, $data = null)
  326. {
  327. parent::__construct();
  328. // set properties
  329. $this->setModule($module);
  330. $this->setAction($action);
  331. if($data !== null) $this->setData($data);
  332. // load the configfile for the required module
  333. $this->loadConfig();
  334. }
  335. /**
  336. * Execute the action
  337. * We will build the classname, require the class and call the execute method.
  338. */
  339. public function execute()
  340. {
  341. // build action-class-name
  342. $actionClassName = 'Frontend' . SpoonFilter::toCamelCase($this->getModule() . '_widget_' . $this->getAction());
  343. // build path to the module
  344. $frontendModulePath = FRONTEND_MODULES_PATH . '/' . $this->getModule();
  345. // require the config file, we know it is there because we validated it before (possible actions are defined by existance off the file).
  346. require_once $frontendModulePath . '/widgets/' . $this->getAction() . '.php';
  347. // validate if class exists (aka has correct name)
  348. if(!class_exists($actionClassName)) throw new FrontendException('The actionfile is present, but the classname should be: ' . $actionClassName . '.');
  349. // create action-object
  350. $this->object = new $actionClassName($this->getModule(), $this->getAction(), $this->getData());
  351. // validate if the execute-method is callable
  352. if(!is_callable(array($this->object, 'execute'))) throw new FrontendException('The actionfile should contain a callable method "execute".');
  353. // call the execute method of the real action (defined in the module)
  354. $this->output = $this->object->execute();
  355. }
  356. /**
  357. * Get the current action
  358. * REMARK: You should not use this method from your code, but it has to be public so we can access it later on in the core-code
  359. *
  360. * @return string
  361. */
  362. public function getAction()
  363. {
  364. // no action specified?
  365. if($this->action === null) $this->setAction($this->config->getDefaultAction());
  366. // return action
  367. return $this->action;
  368. }
  369. /**
  370. * Get the block content
  371. *
  372. * @return string
  373. */
  374. public function getContent()
  375. {
  376. // set path to template if the widget didnt return any data
  377. if($this->output === null) $this->output = $this->object->getContent();
  378. // return possible output
  379. return $this->output;
  380. }
  381. /**
  382. * Get the data
  383. *
  384. * @return mixed
  385. */
  386. public function getData()
  387. {
  388. return $this->data;
  389. }
  390. /**
  391. * Get the current module
  392. * REMARK: You should not use this method from your code, but it has to be public so we can access it later on in the core-code
  393. *
  394. * @return string
  395. */
  396. public function getModule()
  397. {
  398. return $this->module;
  399. }
  400. /**
  401. * Get the assigned template.
  402. *
  403. * @return array
  404. */
  405. public function getTemplate()
  406. {
  407. return $this->object->getTemplate();
  408. }
  409. /**
  410. * Load the config file for the requested block.
  411. * In the config file we have to find dissabled actions, the constructor will read the folder and set possible actions
  412. * Other configurations will be stored in it also.
  413. */
  414. public function loadConfig()
  415. {
  416. // build path for core
  417. if($this->getModule() == 'core') $frontendModulePath = FRONTEND_PATH . '/' . $this->getModule();
  418. // build path to the module and define it. This is a constant because we can use this in templates.
  419. else $frontendModulePath = FRONTEND_MODULES_PATH . '/' . $this->getModule();
  420. // check if the config is present? If it isn't present there is a huge problem, so we will stop our code by throwing an error
  421. if(!SpoonFile::exists($frontendModulePath . '/config.php')) throw new FrontendException('The configfile for the module (' . $this->getModule() . ') can\'t be found.');
  422. // build config-object-name
  423. $configClassName = 'Frontend' . SpoonFilter::toCamelCase($this->getModule() . '_config');
  424. // require the config file, we validated before for existence.
  425. require_once $frontendModulePath . '/config.php';
  426. // validate if class exists (aka has correct name)
  427. if(!class_exists($configClassName)) throw new FrontendException('The config file is present, but the classname should be: ' . $configClassName . '.');
  428. // create config-object, the constructor will do some magic
  429. $this->config = new $configClassName($this->getModule());
  430. }
  431. /**
  432. * Set the action
  433. *
  434. * @param string[optional] $action The action to load.
  435. */
  436. private function setAction($action = null)
  437. {
  438. if($action !== null) $this->action = (string) $action;
  439. }
  440. /**
  441. * Set the data
  442. *
  443. * @param mixed $data The data that should be set.
  444. */
  445. private function setData($data)
  446. {
  447. $this->data = $data;
  448. }
  449. /**
  450. * Set the module
  451. *
  452. * @param string $module The module to load.
  453. */
  454. private function setModule($module)
  455. {
  456. $this->module = (string) $module;
  457. }
  458. }