PageRenderTime 51ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/A/Controller/Helper/Load.php

http://skeleton.googlecode.com/
PHP | 296 lines | 227 code | 18 blank | 51 comment | 55 complexity | c9d0999d954e5705f8030e566dd73d8b MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1
  1. <?php
  2. /**
  3. * Load.php
  4. *
  5. * @license http://www.opensource.org/licenses/bsd-license.php BSD
  6. * @link http://skeletonframework.com/
  7. */
  8. /**
  9. * A_Controller_Helper_Load
  10. *
  11. * Provides class loading and instantiation within the application directory
  12. *
  13. * @package A_Controller
  14. */
  15. class A_Controller_Helper_Load
  16. {
  17. protected $locator;
  18. protected $parent;
  19. protected $paths = array(
  20. 'app'=>'',
  21. 'module'=>'',
  22. 'controller'=>'',
  23. 'action'=>'',
  24. );
  25. protected $dirs = array(
  26. 'controller'=>'controllers/',
  27. 'event'=>'events/',
  28. 'helper'=>'helpers/',
  29. 'model'=>'models/',
  30. 'template'=>'templates/',
  31. 'view'=>'views/',
  32. 'class'=>'',
  33. );
  34. protected $action = null;
  35. protected $method = null;
  36. protected $suffix = array(
  37. 'controller'=>'',
  38. 'model'=>'Model',
  39. 'view'=>'View',
  40. 'helper'=>'Helper',
  41. 'class'=>'',
  42. );
  43. protected $rendererTypes = array('view', 'template');
  44. protected $scope;
  45. protected $scopePath;
  46. protected $responseName = '';
  47. protected $renderClasses = array(
  48. 'php' => 'A_Template_Include',
  49. 'xml' => 'A_Template_Include',
  50. 'json' => 'A_Template_Include',
  51. 'js' => 'A_Template_Include',
  52. 'html' => 'A_Template_Strreplace',
  53. 'txt' => 'A_Template_Strreplace',
  54. );
  55. protected $renderClass = 'A_Template_Include';
  56. protected $renderExtension = 'php';
  57. protected $responseSet = false;
  58. protected $errorMsg = array();
  59. public function __construct($locator, $parent, $scope=null)
  60. {
  61. $this->locator = $locator;
  62. if ($locator) {
  63. $mapper = $locator->get('Mapper');
  64. if ($mapper) {
  65. $this->setMapper($mapper);
  66. } else {
  67. $this->errorMsg[] = "No Mapper to provide paths. ";
  68. }
  69. } else {
  70. $this->errorMsg[] = "No Locator: Action Controller constructor may not be calling self::__construct($locator). ";
  71. }
  72. $this->parent = $parent;
  73. $this->load($scope);
  74. }
  75. /**
  76. * Scopes are:
  77. * global /app/
  78. * module /app/$module/
  79. * controller /app/$module/$type/$controller/
  80. * action /app/$module/$type/$controller/$action/
  81. *
  82. * @param A_Controller_Mapper
  83. * @return $this
  84. */
  85. public function setMapper($mapper)
  86. {
  87. if ($mapper) {
  88. $this->action = $mapper->getClass();
  89. $this->method = $mapper->getMethod();
  90. $this->paths = $mapper->getPaths('%s'); // get paths array with sprintf placeholder
  91. }
  92. return $this;
  93. }
  94. public function setPath($name, $path, $relative_name='')
  95. {
  96. $path = $path ? (rtrim($path, '/') . '/') : ''; // add trailing dir separator
  97. if ($relative_name) {
  98. $this->paths[$name] = $this->paths[$relative_name] . $path;
  99. } else {
  100. $this->paths[$name] = $path;
  101. }
  102. return $this;
  103. }
  104. public function setDir($name, $dir)
  105. {
  106. $this->dirs[$name] = $dir ? (rtrim($dir, '/') . '/') : '';
  107. return $this;
  108. }
  109. public function setRenderClass($name, $ext='php')
  110. {
  111. $ext = ltrim($ext, '.');
  112. $this->renderClasses[$ext] = $name;
  113. return $this;
  114. }
  115. public function setSuffix($name, $suffix)
  116. {
  117. $this->suffix[$name] = $suffix;
  118. return $this;
  119. }
  120. /**
  121. * Get error messages
  122. *
  123. * @param string $separator Delimiter to place between error messages. If empty, an array of error messages is returned.
  124. * @return string|array
  125. */
  126. public function getErrorMsg($separator="\n")
  127. {
  128. if ($separator) {
  129. return implode($separator, $this->errorMsg);
  130. }
  131. return $this->errorMsg;
  132. }
  133. public function response($name='')
  134. {
  135. $this->responseSet = true;
  136. $this->responseName = $name;
  137. return $this;
  138. }
  139. public function load($scope=null, $target=null)
  140. {
  141. if (is_array($scope)) {
  142. $scope = $scope[0];
  143. }
  144. if (! isset($this->paths[$scope])) {
  145. $scope = 'module'; // the default setting e.g., "/app/module/models"
  146. }
  147. $this->scope = $scope;
  148. $this->scopePath = $this->paths[$scope];
  149. $this->responseSet = false; // reset response mode to off for each call
  150. return $this;
  151. }
  152. public function __call($type, $args)
  153. {
  154. $obj = null;
  155. // is this a defined type of subdirectory
  156. if (isset($this->dirs[$type])) {
  157. // get class name parameter or use action name or use method name in controller scope for $type/$controller/$action.php
  158. $class = isset($args[0]) && $args[0] ? $args[0] : ($this->scope == 'controller' && $this->method ? $this->method : $this->action);
  159. // has a . in name is extension so remove for class name and use ext
  160. $length = strpos($class, '.');
  161. if ($length) {
  162. // get extension to use below
  163. $ext = substr($class, $length + 1);
  164. $class = substr($class, 0, $length);
  165. } else { // no extension
  166. $ext = $type == 'template' ? $this->renderExtension : '.php';
  167. if (isset($this->suffix[$type])) {
  168. $length = strlen($this->suffix[$type]);
  169. // if a suffix is defined and the end of the action name does not contain it -- append it
  170. if ($length && (substr($class, -$length) != $this->suffix[$type])) {
  171. $class .= $this->suffix[$type];
  172. }
  173. }
  174. }
  175. // insert type path into scope path
  176. if ($this->scopePath) {
  177. $path = str_replace('%s', $this->dirs[$type], $this->scopePath);
  178. } else {
  179. $path = $this->dirs[$type]; // just in case no scopePath
  180. }
  181. // helpers take a parent instance as the parameter
  182. if ($type == 'helper') {
  183. $args[1] = $this->parent;
  184. }
  185. // templates are a template filename, not a class name -- need to load/create template class
  186. if ($type == 'template') {
  187. // lookup the renderer by extension, if given
  188. $path_parts = pathinfo($class);
  189. // if dir in name the add to path
  190. if ($path_parts['dirname'] != '.') {
  191. $path .= trim($path_parts['dirname'], '/') . '/';
  192. }
  193. }
  194. // templates are a template filename, not a class name -- need to load/create template class
  195. if ($type == 'class') {
  196. // lookup the renderer by extension, if given
  197. $path_parts = pathinfo($class);
  198. // if dir in name the add to path
  199. if ($path_parts['dirname'] != '.') {
  200. $path .= trim($path_parts['dirname'], '/') . '/';
  201. }
  202. $class = $path_parts['basename'];
  203. }
  204. if ($type == 'template') {
  205. // fix by thinsoldier for NT servers that do not return filename
  206. $class = isset($path_parts['filename']) ? $path_parts['filename'] : $path_parts['basename'];
  207. // add in path separators
  208. $class = str_replace(array('_','-'), array('/','_'), $class);
  209. $obj = new $this->renderClasses[$ext]("$path$class.$ext");
  210. // if 2nd param is array then use it to set template values
  211. if (isset($args[1]) && is_array($args[1])) {
  212. foreach ($args[1] as $key => $val) {
  213. $obj->set($key, $val);
  214. }
  215. }
  216. } elseif ($this->locator) {
  217. if ($this->locator->loadClass($class, $path)) { // load class if necessary
  218. $obj = new $class(isset($args[1]) ? $args[1] : $this->locator);
  219. } else {
  220. $this->errorMsg[] = "\$this->_load('{$this->scope}')->$type(" . (isset($args[0]) ? "'{$args[0]}'" : '') . ") call to Locator->loadClass('$class', '$path') failed. Check scope, path and class name. ";
  221. }
  222. } elseif (file_exists("$path$class.php")) {
  223. if (class_exists($class)) {
  224. $obj = new $class(isset($args[1]) ? $args[1] : $this->locator);
  225. }
  226. } else {
  227. $this->errorMsg[] = "Could not load $path$class.php. ";
  228. }
  229. // initialize object
  230. if ($obj) {
  231. if (method_exists($obj, 'setLocator') && $this->locator) {
  232. // set directly so constructor not needed
  233. $obj->setLocator($this->locator);
  234. }
  235. // template and view need passed values set
  236. switch ($type) {
  237. case 'template':
  238. case 'view':
  239. if (isset($args[1]) && is_array($args[1])) {
  240. // if 2nd param is array then use it to set template values
  241. foreach ($args[1] as $key => $val) {
  242. $obj->set($key, $val);
  243. }
  244. }
  245. break;
  246. case 'helper':
  247. $this->parent->_helper($args[0], $obj);
  248. break;
  249. }
  250. // this is the section for when response() has been called
  251. if ($this->responseSet) {
  252. if ($this->locator) {
  253. $response = $this->locator->get('Response');
  254. if ($response && $obj) {
  255. if ($this->responseName) {
  256. $response->set($this->responseName, $obj); // if name then set data in response
  257. } elseif (in_array($type, $this->rendererTypes)) { // if renderer set as renderer
  258. $response->setRenderer($obj);
  259. } else {
  260. $response->set($class, $obj); // otherwise set by class name
  261. }
  262. } else {
  263. echo $obj->render(); // do we really want this option? or should the action do this?
  264. }
  265. return $this; // if response set then allow chained
  266. }
  267. }
  268. } else {
  269. $this->errorMsg[] = "Did not create $class object. ";
  270. }
  271. //reset scope and response
  272. $this->scope = null;
  273. $this->scopePath = null;
  274. $this->responseSet = false;
  275. return $obj;
  276. }
  277. }
  278. }