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

/core/controllers/Controller.class.php

http://plant.googlecode.com/
PHP | 856 lines | 481 code | 94 blank | 281 comment | 48 complexity | 92e2fa4ea0875ff367de094392e5e78e MD5 | raw file
Possible License(s): GPL-3.0
  1. <?php
  2. /**
  3. * Controller.class.php
  4. *
  5. * @package plant_core
  6. * @subpackage controllers
  7. */
  8. /**
  9. * Controller Wrapper Class
  10. *
  11. * Provides many methods for easy manipulation of pages and headers. Keeps track of
  12. * and manipulates template variables. Every action controller must extend this class.
  13. *
  14. * For any Controller extension, actionMain() is automatically inherited.
  15. * To add additional actions and create sub URLs, add appropriate action methods to enable said URL.
  16. *
  17. * Example: Controller section URL is http://mydomain.com/toys/
  18. * To add static URLs such as http://mydomain.com/toys/cars/, create the actionCars() {} method
  19. * in the controller controlling "toys".
  20. * To add dynamic URLs such as http://mydomain.com/toys/dynamic-toy-name/, add arguments to the action method
  21. * controlling the base URL. In this case that would be actionMain($toyName) {} where
  22. * $toyName would get the value "dynamic-toy-name" on call of the URL.
  23. *
  24. * @author Ivo Janssen <ivo@codedealers.com>
  25. * @copyright Copyright (c) 2009, Ivo Janssen
  26. * @license http://opensource.org/licenses/gpl-3.0.html GNU General Public License, version 3
  27. * @package plant_core
  28. * @subpackage controllers
  29. * @version 3.9
  30. * @uses ACTION_METHOD_PREFIX Prefix prepended to every action method (usually 'action')
  31. * @uses APP_ROOT Application root path
  32. * @uses DEFAULT_ACTION_NAME Name for the default action of a controller (usually 'main')
  33. * @uses FRAMEWORK_NAME Name of framework
  34. * @uses FRAMEWORK_ROOT Automatically set root of framework
  35. * @uses FRAMEWORK_VERSION Current version of framework
  36. * @uses GUIDE_EXTENSION File extension of guide files
  37. * @uses SITE_TITLE_SEPARATOR String used to seperate calls to setTitle()
  38. * @uses TEMPLATE_DEFAULT_FORMAT Default template file format
  39. * @uses TEMPLATE_DIR Directory in which templates are stored
  40. * @uses TEMPLATE_EXTENSION Extension for template files
  41. * @uses TEMPLATE_GUIDE Filename of empty template guide
  42. */
  43. abstract class Controller extends Messenger {
  44. /**
  45. * Currently active action
  46. * @var string
  47. */
  48. protected $action;
  49. /**
  50. * Access to local FormController
  51. * @var FormController
  52. */
  53. protected $form;
  54. /**
  55. * Access to current User
  56. * @var UserModel
  57. */
  58. protected $user;
  59. /**
  60. * Stack of action tokens derived from the called URL
  61. * @var array
  62. */
  63. private $actionTokens;
  64. /**
  65. * URL Path governed by current Controller instance
  66. * @var string
  67. */
  68. private $path;
  69. /**
  70. * Path Model linked to current Controller instance
  71. * @var PathModel
  72. */
  73. private $pathModel;
  74. /**
  75. * Template stack with templates to be loaded in order
  76. * @var array
  77. */
  78. private $templateList;
  79. /**
  80. * All variables available to the loaded templates
  81. * @var array
  82. */
  83. private $templateVars;
  84. /**
  85. * Default (Main) Action
  86. *
  87. * Placeholder that enables the main action for a controller to function
  88. * right off the bat.
  89. *
  90. * Should be overridden in child Controllers to addextra functionality.
  91. *
  92. * @return void
  93. */
  94. public function actionMain() {}
  95. /**
  96. * Action creation method
  97. *
  98. * Adds an action method to a Controller, and optionally creates a template file as well.
  99. *
  100. * WARNING: This method actively opens and modifies the file containing the Controller
  101. * it's run on!
  102. *
  103. * @param string $actionName Name of the action to add
  104. * @param bool $createTemplate Whether to create a supporting template or not
  105. * @return bool TRUE on successful addition of action
  106. * @uses config()
  107. * @uses Controller::$action
  108. */
  109. public function addAction($actionName, $createTemplate = true) {
  110. // Check args
  111. if (!preg_match("|^[a-z0-9-]+$|", $actionName)) throw new Exception("Action name can only consist of letters, numbers and hyphens!");
  112. $methodName = config("ACTION_METHOD_PREFIX") . ucfirst(strtolower(str_replace("-", "_", $actionName)));
  113. // Make sure this action doesn't exist and if not, where it needs to be inserted
  114. $controllerReflection = new ReflectionClass(get_class($this));
  115. $newMethodLine = $controllerReflection->getStartLine() + 1;
  116. foreach($controllerReflection->getMethods() as $methodReflection) {
  117. // Only check public actions
  118. if ($methodReflection->getDeclaringClass()->getName() != $controllerReflection->getName() || !$methodReflection->isPublic() || !preg_match("|^" . config("ACTION_METHOD_PREFIX") . "|", $methodReflection->getName())) continue;
  119. // Make sure action doesn't already exist
  120. if (strcmp($methodReflection->getName(), $methodName) == 0) throw new Exception("Action " . $methodName . " already exists in " . get_class($this) . "!");
  121. // Update line to insert at if the name of this method is lower in the alphabet
  122. else if (strcmp($methodReflection->getName(), $methodName) < 0) $newMethodLine = $methodReflection->getEndLine() + 1;
  123. else break;
  124. }
  125. // Check if the controller can be written to
  126. $controllerFile = autoFind($controllerReflection->getName(), "class");
  127. if (!is_writable($controllerFile)) throw new Exception("Can't write to " . $controllerFile . "! Check the permissions!");
  128. // Append new action to controller
  129. $actionCode = "\t\t/**
  130. * Auto-generated action by Plant on " . date("M j, Y \a\\t H:i:s") . "
  131. *
  132. * @return void
  133. */
  134. public function " . $methodName . "() {
  135. }
  136. ";
  137. $controllerCodeLines = explode("\n", file_get_contents($controllerFile));
  138. $controllerCode = array_merge(array_slice($controllerCodeLines, 0, $newMethodLine), array($actionCode), array_slice($controllerCodeLines, $newMethodLine));
  139. if (!file_put_contents($controllerFile, implode("\n", $controllerCode))) throw new Exception("Can't write to " . $controllerFile . "! Check the permissions!");
  140. // Create template if required
  141. if ($createTemplate) {
  142. $this->action = $actionName;
  143. $this->createTemplate();
  144. }
  145. return true;
  146. }
  147. /**
  148. * Controller Creation
  149. *
  150. * Gets called on creation of a Controller child. Creates a template for
  151. * the default action.
  152. *
  153. * @return bool TRUE on successful creation
  154. */
  155. public function create() {
  156. // Set action
  157. $this->action = config("DEFAULT_ACTION_NAME");
  158. // Create main template
  159. $this->createTemplate();
  160. return true;
  161. }
  162. /**
  163. * Action Execution
  164. *
  165. * Fires up a controller and sets actions in motion. Checks correct
  166. * authentication for the current path, and checks if the action tokens from
  167. * the URL are valid and can be executed. If so, the actions get executed.
  168. *
  169. * @return bool TRUE on successful execution
  170. * @uses AuthenticationRequiredException
  171. * @uses PathNotFoundException
  172. * @uses UserModel
  173. */
  174. public function executeAction() {
  175. // Load previous status and error messages from the session
  176. $this->loadMessages();
  177. // Make sure user is authorized
  178. if ($this->getPathModel()->authenticationRequired()) {
  179. // If not logged in, throw them to the login form
  180. if (!$this->user->isLoggedIn()) throw new AuthenticationRequiredException("User needs to be logged in to view this page.");
  181. // If they ARE logged in and not an admin, check the access groups
  182. if (!$this->user->is("admin") && !$this->user->inGroup($this->getPathModel()->getAccessGroups())) throw new PathNotFoundException("You're not allowed to view that page!");
  183. }
  184. // Find the method which belongs to the current action (if applicable)
  185. if (isset($this->actionTokens[0]) && !empty($this->actionTokens[0]) && $actionMethod = $this->findMethod($this->actionTokens[0], array_slice($this->actionTokens,1))) {
  186. // Set the action
  187. $this->action = $this->actionTokens[0];
  188. $this->actionTokens = array_slice($this->actionTokens, 1);
  189. // Fire up this method
  190. return $actionMethod->invokeArgs($this, $this->actionTokens);
  191. }
  192. // Otherwise the default method will be called
  193. else if ($actionMethod = $this->findMethod(config("DEFAULT_ACTION_NAME"), $this->actionTokens)) {
  194. // Default action taken
  195. $this->action = config("DEFAULT_ACTION_NAME");
  196. // Fire up the default method
  197. return $actionMethod->invokeArgs($this, $this->actionTokens);
  198. }
  199. // If the default method couldn't be found, then something must be wrong
  200. else throw new PathNotFoundException("Couldn't find any suitable action method to execute with action tokens: " . implode("/", $this->actionTokens));
  201. return false;
  202. }
  203. /**
  204. * Template list accessor
  205. *
  206. * @return array Current template list
  207. * @uses Controller::$templateList
  208. */
  209. public function getTemplateList() {
  210. if (!isset($this->templateList)) return false;
  211. return $this->templateList;
  212. }
  213. /**
  214. * Template variables accessor
  215. *
  216. * @param string|bool $specific Specific name of variable to retrieve, FALSE for entire array
  217. * @return array Current template variables
  218. * @uses Controller::$templateVars
  219. */
  220. public function getTemplateVars($specific = false) {
  221. if (!$specific) {
  222. if (!isset($this->templateVars)) return false;
  223. return $this->templateVars;
  224. }
  225. if (!isset($this->templateVars[$specific])) return false;
  226. return $this->templateVars[$specific];
  227. }
  228. /**
  229. * Initialization Method
  230. *
  231. * Sets action tokens, executes inheritance and setProperties()
  232. *
  233. * @param string|array|bool $actionTokens Array of action tokens or string of single token, FALSE if there are no more
  234. * @param PathModel $parentPath Parent path of current
  235. * @param Controller|null $parentController Parent controller of current
  236. * @return bool TRUE on successful initialization
  237. * @uses PathModel
  238. */
  239. public function init($actionTokens = false, PathModel $parentPath, Controller $parentController = NULL) {
  240. // Set the tokens
  241. if (!is_array($actionTokens)) $actionTokens = array($actionTokens);
  242. $this->actionTokens = $actionTokens;
  243. // Inherit properties from a parent & path
  244. $this->inheritFrom($parentPath, $parentController);
  245. // Set section URL
  246. $this->templateVars["sectionURL"][$this->getControllerName()] = "/" . $this->getPath();
  247. // Set (and override) new properties
  248. $this->setProperties();
  249. return true;
  250. }
  251. /**
  252. * Rendering Method
  253. *
  254. * Constructs current path information, sets some ominous template variables and starts
  255. * template processing.
  256. *
  257. * @return bool TRUE on successful render
  258. * @uses TemplateController
  259. */
  260. public function render() {
  261. // Constructs current path information
  262. $pageURL = $this->getPath();
  263. if ($this->action != config("DEFAULT_ACTION_NAME")) $pageURL .= $this->action . "/";
  264. $pageURL .= implode("/", $this->actionTokens) . "/";
  265. // Set values only available to template at render
  266. $this->set("device", $this->device);
  267. $this->set("form", $this->form);
  268. $this->set("pageURL", trim($pageURL,"/") . "/");
  269. $this->set("user", $this->user);
  270. $this->set("sectionToken", $this->getControllerName() . " " . $this->action);
  271. // Globals
  272. global $currentUser;
  273. $currentUser =& $this->user;
  274. // Load the templates from the template controller
  275. $templates = new TemplateController($this->templateVars);
  276. foreach($this->getTemplates() as $templateName) {
  277. $templates->load($this->convertTemplateName($templateName), $this->device);
  278. }
  279. return true;
  280. }
  281. /**
  282. * Template variable set
  283. *
  284. * Sets a variable name for availability in the templates
  285. *
  286. * @param string $key Name of variable to set
  287. * @param mixed $value Value of the variable to set
  288. * @return boolean TRUE on successful set
  289. * @uses Controller::$templateVars
  290. */
  291. public function set($key, $value = false) {
  292. // Check arguments
  293. if (!$key || !is_string($key)) throw new Exception("Can't set a variable in the template without a valid key!");
  294. // Set it in the template vars
  295. $this->templateVars[$key] = $value;
  296. return true;
  297. }
  298. /**
  299. * Get a REQUEST or FILE variable
  300. *
  301. * Checks $_REQUEST and $_FILES arrays to retrieve set values sent to the
  302. * page via GET or POST, if exists.
  303. *
  304. * @param string $key Name of variable to retrieve
  305. * @return mixed Cleaned value from $_REQUEST or $_FILES array
  306. */
  307. protected function get($key) {
  308. // Check arguments
  309. if (!is_string($key) || empty($key)) throw new Exception("Key to request needs to be a valid non-empty string!");
  310. // Check $_REQUEST
  311. if (isset($_REQUEST[$key])) {
  312. $variable = $_REQUEST[$key];
  313. // Deal with magic quotes
  314. if (get_magic_quotes_gpc()) $variable = stripslashes($variable);
  315. return $variable;
  316. }
  317. // Check $_FILES
  318. if (isset($_FILES[$key])) return $_FILES[$key];
  319. return false;
  320. }
  321. /**
  322. * Path accessor
  323. *
  324. * @return string Path governed by this controller
  325. * @uses Controller::$path
  326. */
  327. protected function getPath() {
  328. if (!isset($this->path) || empty($this->path)) return "";
  329. return $this->path;
  330. }
  331. /**
  332. * Linked PathModel accessor
  333. *
  334. * @return PathModel PathModel linked to this controller
  335. * @uses Controller::$pathModel
  336. */
  337. protected function getPathModel() {
  338. if (!isset($this->pathModel)) throw new Exception("No path attached to controller!");
  339. return $this->pathModel;
  340. }
  341. /**
  342. * Token accessor
  343. *
  344. * @return string URL token related to this controller's path
  345. */
  346. protected function getToken() {
  347. // Check if the path token exists
  348. return $this->getPathModel()->getPath();
  349. }
  350. /**
  351. * Inheritance method
  352. *
  353. * Inherits set template variables, template list, path and title from
  354. * parent Controller and path
  355. *
  356. * @param PathModel $parentPath Path to inherit from
  357. * @param Controller|null $parent Parent Controller to inherit from
  358. * @return bool TRUE on successful inheritance
  359. * @uses Controller::$device
  360. * @uses Controller::$form
  361. * @uses Controller::$templateVars
  362. * @uses Controller::$path
  363. * @uses Controller::$pathModel
  364. * @uses Controller::$user
  365. * @uses FormController
  366. * @uses UserAgent
  367. * @uses UserModel::authenticate()
  368. */
  369. protected function inheritFrom(PathModel $parentPath, Controller $parent = NULL) {
  370. if ($parent != NULL) {
  371. // Inherit template vars
  372. $this->templateVars = $parent->getTemplateVars();
  373. // Inherit template list
  374. $this->setTemplates($parent->getTemplateList());
  375. // Inherit path
  376. $this->path = $parent->getPath() . $parentPath->getPath() . "/";
  377. // Inherit other globals
  378. $this->device =& $parent->device;
  379. $this->form =& $parent->form;
  380. $this->user =& $parent->user;
  381. }
  382. else {
  383. // Set user
  384. $this->user =& UserModel::authenticate();
  385. // Set device
  386. $this->device = new UserAgent();
  387. // Setup helpers
  388. $this->form = new FormController();
  389. }
  390. // Inherit title
  391. $this->setTitle($parentPath->getTitle());
  392. // Inherit path
  393. $this->pathModel = $parentPath;
  394. return true;
  395. }
  396. /**
  397. * Easy pagination method
  398. *
  399. * Given a ModelSet, sets <em>page</em>, <em>totalPages</em> and
  400. * <em>totalSize</em> variables for availability in template.
  401. *
  402. * @param ModelSet $set ModelSet to paginate on
  403. * @return array Items for the current page of the ModelSet
  404. * @uses ModelSet
  405. */
  406. protected function paginate(ModelSet $set) {
  407. // Kick out if page number doesn't exist
  408. if (!$set->getNumber()) throw new PathNotFoundException("Invalid page number!");
  409. // Set template vars
  410. $this->set("page", $set->getNumber());
  411. $this->set("totalPages", $set->getTotalSetAmount());
  412. $this->set("totalSize", $set->getTotalSize());
  413. // Return the subset
  414. return $set->getItems();
  415. }
  416. /**
  417. * Remove all set Javascript script calls (inherited or otherwise)
  418. *
  419. * @return void
  420. * @uses Controller::$templateVars
  421. */
  422. protected function removeJavascripts() {
  423. unset($this->templateVars["headerVars"]["js"]);
  424. unset($this->templateVars["headerVars"]["jsVars"]);
  425. }
  426. /**
  427. * Remove one or more set meta tag settings (inherited or otherwise)
  428. *
  429. * @param string|bool $key Meta key to remove or FALSE for all
  430. * @return void
  431. * @uses Controller::$templateVars
  432. */
  433. protected function removeMeta($key = false) {
  434. // If no key is set, remove all the meta vars
  435. if (!$key || !is_string($key)) unset($this->templateVars["headerVars"]["meta"]);
  436. // Otherwise just remove the key using setMeta
  437. else $this->setMeta($key);
  438. return true;
  439. }
  440. /**
  441. * Remove all set Stylesheets (inherited or otherwise)
  442. *
  443. * @return void
  444. * @uses Controller::$templateVars
  445. */
  446. protected function removeStyleSheets() {
  447. unset($this->templateVars["headerVars"]["css"]);
  448. return true;
  449. }
  450. /**
  451. * Add an external Javascript script reference to the current page
  452. *
  453. * @param string $filename Filename of javascript to add, extension or directory not necessary if placed in standard app/scripts directory
  454. * @param bool $defer Enables the XHTML DEFER property on this reference (defers execution of script until after content is loaded)
  455. * @param string $condition Wrap the Javascript script reference in conditional comments (example "IE 6" or "lt IE 6")
  456. * @return void
  457. * @uses Controller::$templateVars
  458. * @uses SITE_VERSION
  459. */
  460. protected function setJavascript($filename, $defer = false, $condition = false) {
  461. // Autofind javascript if not full path given
  462. if (strpos($filename, "http://") !== false) $foundFile = $filename;
  463. else $foundFile = autoFind($filename, "script", "remote") . "?v" . config("SITE_VERSION");
  464. // Create javascript array with script path
  465. $jScript = array(
  466. "file" => $foundFile,
  467. );
  468. // Set a condition if necessary
  469. if ($condition) $jScript["condition"] = $condition;
  470. // Set a defer if necessary
  471. if ($defer) $jScript["defer"] = true;
  472. // Set it in the template Vars
  473. $this->templateVars["headerVars"]["js"][] = $jScript;
  474. }
  475. /**
  476. * Add an javascript variable to the current page
  477. *
  478. * @param string $key Variable name to set
  479. * @param string $value Javascript code to set the variable to
  480. * @return void
  481. * @uses Controller::$templateVars
  482. */
  483. protected function setJavascriptVar($key, $value = "") {
  484. // Check arguments
  485. if (!$key || !is_string($key)) throw new Exception("Can't set a JS variable without a valid name!");
  486. // Set it in the template Vars
  487. $this->templateVars["headerVars"]["jsVars"][$key] = $value;
  488. }
  489. /**
  490. * Add a META tag to the current page
  491. *
  492. * @param string $key Meta name to set
  493. * @param string $value Meta value to set
  494. * @return void
  495. * @uses Controller::$templateVars
  496. */
  497. protected function setMeta($key, $value = "") {
  498. // Check arguments
  499. if (!$key || !is_string($key)) throw new Exception("Can't set a META tag without a valid 'name' key!");
  500. // If the value is empty, delete the meta key from the headers
  501. if (empty($value)) unset($this->templateVars["headerVars"]["meta"][$key]);
  502. // Else set it in the template vars
  503. else $this->templateVars["headerVars"]["meta"][$key] = $value;
  504. }
  505. /**
  506. * Default Properties Method
  507. *
  508. * Placeholder that enables child controllers to function without requiring it
  509. *
  510. * Should be overridden in child Controllers to control section-wide properties.
  511. *
  512. * @return void
  513. */
  514. protected function setProperties() {}
  515. /**
  516. * Add an RSS feed reference to the current page
  517. *
  518. * @param string $feed Path to the RSS feed
  519. * @param string $title Title of the feed
  520. * @return void
  521. * @uses Controller::$templateVars
  522. */
  523. protected function setRSSFeed($feed, $title) {
  524. // Check arguments
  525. if (!$feed || !is_string($feed)) throw new Exception("Can't load a RSS feed with an invalid filename!");
  526. if (!$title || !is_string($title)) throw new Exception("RSS feed title must be a string!");
  527. // Set it in the template Vars
  528. $this->templateVars["headerVars"]["rss"][$title] = $feed;
  529. }
  530. /**
  531. * Add a Stylesheet reference to the current page
  532. *
  533. * @param string $filename Filename of the CSS file (extension and path not necessary if files placed in app/css/)
  534. * @param string $forMedia CSS media target (defaults to "all")
  535. * @param string $condition Wrap the CSS reference in conditional comments (example "IE 6" or "lt IE 6")
  536. * @return void
  537. * @uses Controller::$templateVars
  538. * @uses SITE_VERSION
  539. */
  540. protected function setStyleSheet($filename, $forMedia = "all", $condition = false) {
  541. // Create stylesheet array
  542. $styleSheet = array(
  543. "file" => autoFind($filename, "stylesheet", "remote") . "?v" . config("SITE_VERSION"),
  544. "media" => $forMedia,
  545. );
  546. // Set a condition if necessary
  547. if ($condition) $styleSheet["condition"] = $condition;
  548. // Set it in the template Vars
  549. $this->templateVars["headerVars"]["css"][] = $styleSheet;
  550. return true;
  551. }
  552. /**
  553. * Set the list of templates to be loaded
  554. *
  555. * @param string|array $templateList Array or comma-seperated string of templates
  556. * @return void
  557. * @uses Controller::$templateList
  558. */
  559. protected function setTemplates($templateList) {
  560. // Check arguments
  561. if (!is_string($templateList) && !is_array($templateList)) throw new Exception("Template list needs to be a string or array!");
  562. // Convert to an array if the list is a string
  563. if (!is_array($templateList)) $templateList = explode(",", $templateList);
  564. // Set it in the controller
  565. $this->templateList = $templateList;
  566. }
  567. /**
  568. * Add a TITLE (addition) to the current page
  569. *
  570. * @param string $title Title to set
  571. * Value automatically gets added on to the inherited TITLE using SITE_TITLE_SEPARATOR
  572. * Prefix value with <kbd>$</kbd> to ignore inherited TITLE
  573. * @return void
  574. * @uses Controller::$templateVars
  575. */
  576. protected function setTitle($title = "") {
  577. // Check arguments
  578. if (!is_string($title)) throw new Exception("Title needs to be a valid string!");
  579. // Check for non-inheritance character
  580. if (substr($title, 0, 1) == "$") {
  581. $title = substr($title, 1);
  582. $inherit = false;
  583. }
  584. else $inherit = true;
  585. // If already set, propagate it
  586. if ($inherit && isset($this->templateVars["headerVars"]["title"]) && !empty($this->templateVars["headerVars"]["title"])) {
  587. if (!empty($title)) $title .= config("SITE_TITLE_SEPARATOR") . $this->templateVars["headerVars"]["title"];
  588. else $title = $this->templateVars["headerVars"]["title"];
  589. }
  590. // Set it in the template Vars
  591. $this->templateVars["headerVars"]["title"] = $title;
  592. }
  593. /**
  594. * Convert variables in a template name
  595. *
  596. * Variables that can be used in a template name are %controller% and %action%, these will be
  597. * replaced with their current value on load.
  598. *
  599. * @param string $templateName Name of the template
  600. * @return string Replaced template name
  601. * @uses Controller::$action
  602. */
  603. private function convertTemplateName($templateName) {
  604. // Check arguments
  605. if (!$templateName || !is_string($templateName)) throw new Exception("Template name is empty or invalid!");
  606. // Make sure action is set
  607. if (!$this->action || empty($this->action)) throw new Exception("Action is empty but needed for a template name!");
  608. // Create controller abbreviation
  609. $controllerAbbrev = $this->getControllerName();
  610. // Check if the action is the default, and return the short hand version then
  611. if ($this->action == config("DEFAULT_ACTION_NAME") && stripos($templateName, "%action%") !== false) return $controllerAbbrev;
  612. $conversions = array(
  613. "%controller%" => $controllerAbbrev,
  614. "%action%" => $this->action,
  615. );
  616. // Return the hyphen-glued string
  617. return strtolower(str_replace(array_keys($conversions), array_values($conversions), $templateName));
  618. }
  619. /**
  620. * Create a template file
  621. *
  622. * Uses the current action and the template guide (template.guide) to create
  623. * an empty template and store it in the templates directory.
  624. *
  625. * @return bool TRUE on successful creation of template
  626. */
  627. private function createTemplate() {
  628. // Load the template guide
  629. $templateGuideFile = config("FRAMEWORK_ROOT") . config("TEMPLATE_DIR") . config("TEMPLATE_GUIDE") . "." . config("GUIDE_EXTENSION");
  630. if (!file_exists($templateGuideFile)) throw new Exception("Template guide not found at '" . $templateGuideFile . "'!");
  631. $templateGuide = file_get_contents($templateGuideFile);
  632. // Replace important stuff
  633. $replace = Array("%controllername%", "%generatorname%", "%date%", "%action%");
  634. $with = Array($this->getControllerName(), config("FRAMEWORK_NAME") . " " . config("FRAMEWORK_VERSION"), date("F jS, Y"), $this->action);
  635. $templateGuide = str_replace($replace, $with, $templateGuide);
  636. // Write it to the template directory
  637. $templateFilename = config("APP_ROOT") . config("TEMPLATE_DIR") . $this->convertTemplateName(config("TEMPLATE_DEFAULT_FORMAT")) . "." . config("TEMPLATE_EXTENSION");
  638. if (@file_put_contents($templateFilename, $templateGuide) === false) throw new Exception("New template could not be created! Be sure that the permissions are set correctly for the directory containing the templates.");
  639. // CHMOD it so regular users have access too
  640. chmod($templateFilename, 0664);
  641. return true;
  642. }
  643. /**
  644. * Find action method with correct name and arguments
  645. *
  646. * Checks if a certain method exists in a class and if it has the correct arguments.
  647. * Returns if found.
  648. *
  649. * @param string $actionName Name of action to search for
  650. * @param array $actionArguments Arguments available for the action
  651. * @return ReflectionMethod|bool Returns method if found, otherwise FALSE
  652. */
  653. private function findMethod($actionName, $actionArguments) {
  654. // Check arguments
  655. if (!is_array($actionArguments)) $actionArguments = Array();
  656. if (!is_string($actionName)) throw new Exception("Need to have a string as the action!");
  657. // Load all the methods in this class
  658. $controllerReflection = new ReflectionClass(get_class($this));
  659. // Check every method to find the right one
  660. foreach($controllerReflection->getMethods() as $controllerMethod) {
  661. // Check if the name corresponds with what we're looking for
  662. if ($controllerMethod->getName() == config("ACTION_METHOD_PREFIX") . ucfirst(str_replace("-", "_", $actionName)) && $controllerMethod->getNumberOfRequiredParameters() <= count($actionArguments) && $controllerMethod->isPublic()) {
  663. return $controllerMethod;
  664. }
  665. }
  666. return false;
  667. }
  668. /**
  669. * Get controller name
  670. *
  671. * Returns the short name of this controller (without the Controller suffix)
  672. *
  673. * @return string Short name of controller
  674. */
  675. private function getControllerName() {
  676. return strtolower(preg_replace("|Controller$|i", "", get_class($this)));
  677. }
  678. /**
  679. * Template list accessor
  680. *
  681. * @return array List of templates to be loaded
  682. * @uses Controller::$templateList
  683. */
  684. private function getTemplates() {
  685. if (!isset($this->templateList)) throw new Exception("No templates set to be loaded!");
  686. if (!is_array($this->templateList)) $this->templateList = array($this->templateList);
  687. return $this->templateList;
  688. }
  689. }
  690. ?>