/frontend/core/engine/block.php

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