/library/Zend/View/Model/ViewModel.php

https://github.com/Thinkscape/zf2 · PHP · 492 lines · 211 code · 55 blank · 226 comment · 16 complexity · 4436164e57a76e9713adcb400f8ec1fb MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework (http://framework.zend.com/)
  4. *
  5. * @link http://github.com/zendframework/zf2 for the canonical source repository
  6. * @copyright Copyright (c) 2005-2014 Zend Technologies USA Inc. (http://www.zend.com)
  7. * @license http://framework.zend.com/license/new-bsd New BSD License
  8. */
  9. namespace Zend\View\Model;
  10. use ArrayAccess;
  11. use ArrayIterator;
  12. use Traversable;
  13. use Zend\Stdlib\ArrayUtils;
  14. use Zend\View\Exception;
  15. use Zend\View\Model;
  16. use Zend\View\Variables as ViewVariables;
  17. class ViewModel implements ModelInterface, ClearableModelInterface, RetrievableChildrenInterface
  18. {
  19. /**
  20. * What variable a parent model should capture this model to
  21. *
  22. * @var string
  23. */
  24. protected $captureTo = 'content';
  25. /**
  26. * Child models
  27. * @var array
  28. */
  29. protected $children = array();
  30. /**
  31. * Renderer options
  32. * @var array
  33. */
  34. protected $options = array();
  35. /**
  36. * Template to use when rendering this model
  37. *
  38. * @var string
  39. */
  40. protected $template = '';
  41. /**
  42. * Is this a standalone, or terminal, model?
  43. *
  44. * @var bool
  45. */
  46. protected $terminate = false;
  47. /**
  48. * View variables
  49. * @var array|ArrayAccess&Traversable
  50. */
  51. protected $variables = array();
  52. /**
  53. * Is this append to child with the same capture?
  54. *
  55. * @var bool
  56. */
  57. protected $append = false;
  58. /**
  59. * Constructor
  60. *
  61. * @param null|array|Traversable $variables
  62. * @param array|Traversable $options
  63. */
  64. public function __construct($variables = null, $options = null)
  65. {
  66. if (null === $variables) {
  67. $variables = new ViewVariables();
  68. }
  69. // Initializing the variables container
  70. $this->setVariables($variables, true);
  71. if (null !== $options) {
  72. $this->setOptions($options);
  73. }
  74. }
  75. /**
  76. * Property overloading: set variable value
  77. *
  78. * @param string $name
  79. * @param mixed $value
  80. * @return void
  81. */
  82. public function __set($name, $value)
  83. {
  84. $this->setVariable($name, $value);
  85. }
  86. /**
  87. * Property overloading: get variable value
  88. *
  89. * @param string $name
  90. * @return mixed
  91. */
  92. public function __get($name)
  93. {
  94. if (!$this->__isset($name)) {
  95. return null;
  96. }
  97. $variables = $this->getVariables();
  98. return $variables[$name];
  99. }
  100. /**
  101. * Property overloading: do we have the requested variable value?
  102. *
  103. * @param string $name
  104. * @return bool
  105. */
  106. public function __isset($name)
  107. {
  108. $variables = $this->getVariables();
  109. return isset($variables[$name]);
  110. }
  111. /**
  112. * Property overloading: unset the requested variable
  113. *
  114. * @param string $name
  115. * @return void
  116. */
  117. public function __unset($name)
  118. {
  119. if (!$this->__isset($name)) {
  120. return null;
  121. }
  122. unset($this->variables[$name]);
  123. }
  124. /**
  125. * Set a single option
  126. *
  127. * @param string $name
  128. * @param mixed $value
  129. * @return ViewModel
  130. */
  131. public function setOption($name, $value)
  132. {
  133. $this->options[(string) $name] = $value;
  134. return $this;
  135. }
  136. /**
  137. * Get a single option
  138. *
  139. * @param string $name The option to get.
  140. * @param mixed|null $default (optional) A default value if the option is not yet set.
  141. * @return mixed
  142. */
  143. public function getOption($name, $default = null)
  144. {
  145. $name = (string) $name;
  146. return array_key_exists($name, $this->options) ? $this->options[$name] : $default;
  147. }
  148. /**
  149. * Set renderer options/hints en masse
  150. *
  151. * @param array|Traversable $options
  152. * @throws \Zend\View\Exception\InvalidArgumentException
  153. * @return ViewModel
  154. */
  155. public function setOptions($options)
  156. {
  157. // Assumption is that lowest common denominator for renderer configuration
  158. // is an array
  159. if ($options instanceof Traversable) {
  160. $options = ArrayUtils::iteratorToArray($options);
  161. }
  162. if (!is_array($options)) {
  163. throw new Exception\InvalidArgumentException(sprintf(
  164. '%s: expects an array, or Traversable argument; received "%s"',
  165. __METHOD__,
  166. (is_object($options) ? get_class($options) : gettype($options))
  167. ));
  168. }
  169. $this->options = $options;
  170. return $this;
  171. }
  172. /**
  173. * Get renderer options/hints
  174. *
  175. * @return array
  176. */
  177. public function getOptions()
  178. {
  179. return $this->options;
  180. }
  181. /**
  182. * Clear any existing renderer options/hints
  183. *
  184. * @return ViewModel
  185. */
  186. public function clearOptions()
  187. {
  188. $this->options = array();
  189. return $this;
  190. }
  191. /**
  192. * Get a single view variable
  193. *
  194. * @param string $name
  195. * @param mixed|null $default (optional) default value if the variable is not present.
  196. * @return mixed
  197. */
  198. public function getVariable($name, $default = null)
  199. {
  200. $name = (string) $name;
  201. if (array_key_exists($name, $this->variables)) {
  202. return $this->variables[$name];
  203. }
  204. return $default;
  205. }
  206. /**
  207. * Set view variable
  208. *
  209. * @param string $name
  210. * @param mixed $value
  211. * @return ViewModel
  212. */
  213. public function setVariable($name, $value)
  214. {
  215. $this->variables[(string) $name] = $value;
  216. return $this;
  217. }
  218. /**
  219. * Set view variables en masse
  220. *
  221. * Can be an array or a Traversable + ArrayAccess object.
  222. *
  223. * @param array|ArrayAccess|Traversable $variables
  224. * @param bool $overwrite Whether or not to overwrite the internal container with $variables
  225. * @throws Exception\InvalidArgumentException
  226. * @return ViewModel
  227. */
  228. public function setVariables($variables, $overwrite = false)
  229. {
  230. if (!is_array($variables) && !$variables instanceof Traversable) {
  231. throw new Exception\InvalidArgumentException(sprintf(
  232. '%s: expects an array, or Traversable argument; received "%s"',
  233. __METHOD__,
  234. (is_object($variables) ? get_class($variables) : gettype($variables))
  235. ));
  236. }
  237. if ($overwrite) {
  238. if (is_object($variables) && !$variables instanceof ArrayAccess) {
  239. $variables = ArrayUtils::iteratorToArray($variables);
  240. }
  241. $this->variables = $variables;
  242. return $this;
  243. }
  244. foreach ($variables as $key => $value) {
  245. $this->setVariable($key, $value);
  246. }
  247. return $this;
  248. }
  249. /**
  250. * Get view variables
  251. *
  252. * @return array|ArrayAccess|Traversable
  253. */
  254. public function getVariables()
  255. {
  256. return $this->variables;
  257. }
  258. /**
  259. * Clear all variables
  260. *
  261. * Resets the internal variable container to an empty container.
  262. *
  263. * @return ViewModel
  264. */
  265. public function clearVariables()
  266. {
  267. $this->variables = new ViewVariables();
  268. return $this;
  269. }
  270. /**
  271. * Set the template to be used by this model
  272. *
  273. * @param string $template
  274. * @return ViewModel
  275. */
  276. public function setTemplate($template)
  277. {
  278. $this->template = (string) $template;
  279. return $this;
  280. }
  281. /**
  282. * Get the template to be used by this model
  283. *
  284. * @return string
  285. */
  286. public function getTemplate()
  287. {
  288. return $this->template;
  289. }
  290. /**
  291. * Add a child model
  292. *
  293. * @param ModelInterface $child
  294. * @param null|string $captureTo Optional; if specified, the "capture to" value to set on the child
  295. * @param null|bool $append Optional; if specified, append to child with the same capture
  296. * @return ViewModel
  297. */
  298. public function addChild(ModelInterface $child, $captureTo = null, $append = null)
  299. {
  300. $this->children[] = $child;
  301. if (null !== $captureTo) {
  302. $child->setCaptureTo($captureTo);
  303. }
  304. if (null !== $append) {
  305. $child->setAppend($append);
  306. }
  307. return $this;
  308. }
  309. /**
  310. * Return all children.
  311. *
  312. * Return specifies an array, but may be any iterable object.
  313. *
  314. * @return array
  315. */
  316. public function getChildren()
  317. {
  318. return $this->children;
  319. }
  320. /**
  321. * Does the model have any children?
  322. *
  323. * @return bool
  324. */
  325. public function hasChildren()
  326. {
  327. return (0 < count($this->children));
  328. }
  329. /**
  330. * Clears out all child models
  331. *
  332. * @return ViewModel
  333. */
  334. public function clearChildren()
  335. {
  336. $this->children = array();
  337. return $this;
  338. }
  339. /**
  340. * Returns an array of Viewmodels with captureTo value $capture
  341. *
  342. * @param string $capture
  343. * @param bool $recursive search recursive through children, default true
  344. * @return array
  345. */
  346. public function getChildrenByCaptureTo($capture, $recursive = true)
  347. {
  348. $children = array();
  349. foreach ($this->children as $child) {
  350. if ($recursive === true) {
  351. $children += $child->getChildrenByCaptureTo($capture);
  352. }
  353. if ($child->captureTo() === $capture) {
  354. $children[] = $child;
  355. }
  356. }
  357. return $children;
  358. }
  359. /**
  360. * Set the name of the variable to capture this model to, if it is a child model
  361. *
  362. * @param string $capture
  363. * @return ViewModel
  364. */
  365. public function setCaptureTo($capture)
  366. {
  367. $this->captureTo = (string) $capture;
  368. return $this;
  369. }
  370. /**
  371. * Get the name of the variable to which to capture this model
  372. *
  373. * @return string
  374. */
  375. public function captureTo()
  376. {
  377. return $this->captureTo;
  378. }
  379. /**
  380. * Set flag indicating whether or not this is considered a terminal or standalone model
  381. *
  382. * @param bool $terminate
  383. * @return ViewModel
  384. */
  385. public function setTerminal($terminate)
  386. {
  387. $this->terminate = (bool) $terminate;
  388. return $this;
  389. }
  390. /**
  391. * Is this considered a terminal or standalone model?
  392. *
  393. * @return bool
  394. */
  395. public function terminate()
  396. {
  397. return $this->terminate;
  398. }
  399. /**
  400. * Set flag indicating whether or not append to child with the same capture
  401. *
  402. * @param bool $append
  403. * @return ViewModel
  404. */
  405. public function setAppend($append)
  406. {
  407. $this->append = (bool) $append;
  408. return $this;
  409. }
  410. /**
  411. * Is this append to child with the same capture?
  412. *
  413. * @return bool
  414. */
  415. public function isAppend()
  416. {
  417. return $this->append;
  418. }
  419. /**
  420. * Return count of children
  421. *
  422. * @return int
  423. */
  424. public function count()
  425. {
  426. return count($this->children);
  427. }
  428. /**
  429. * Get iterator of children
  430. *
  431. * @return ArrayIterator
  432. */
  433. public function getIterator()
  434. {
  435. return new ArrayIterator($this->children);
  436. }
  437. }