PageRenderTime 60ms CodeModel.GetById 32ms RepoModel.GetById 0ms app.codeStats 1ms

/library/Zend/Navigation/Page.php

http://github.com/valentinbora/joobsbox-php
PHP | 1118 lines | 470 code | 118 blank | 530 comment | 73 complexity | 194ab0ef6a933717594456a88503fd1f MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Navigation
  17. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  18. * @license http://framework.zend.com/license/new-bsd New BSD License
  19. */
  20. /**
  21. * @see Zend_Navigation_Container
  22. */
  23. require_once 'Zend/Navigation/Container.php';
  24. /**
  25. * Base class for Zend_Navigation_Page pages
  26. *
  27. * @category Zend
  28. * @package Zend_Navigation
  29. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  30. * @license http://framework.zend.com/license/new-bsd New BSD License
  31. */
  32. abstract class Zend_Navigation_Page extends Zend_Navigation_Container
  33. {
  34. /**
  35. * Page label
  36. *
  37. * @var string|null
  38. */
  39. protected $_label;
  40. /**
  41. * Page id
  42. *
  43. * @var string|null
  44. */
  45. protected $_id;
  46. /**
  47. * Style class for this page (CSS)
  48. *
  49. * @var string|null
  50. */
  51. protected $_class;
  52. /**
  53. * A more descriptive title for this page
  54. *
  55. * @var string|null
  56. */
  57. protected $_title;
  58. /**
  59. * This page's target
  60. *
  61. * @var string|null
  62. */
  63. protected $_target;
  64. /**
  65. * Forward links to other pages
  66. *
  67. * @link http://www.w3.org/TR/html4/struct/links.html#h-12.3.1
  68. *
  69. * @var array
  70. */
  71. protected $_rel = array();
  72. /**
  73. * Reverse links to other pages
  74. *
  75. * @link http://www.w3.org/TR/html4/struct/links.html#h-12.3.1
  76. *
  77. * @var array
  78. */
  79. protected $_rev = array();
  80. /**
  81. * Page order used by parent container
  82. *
  83. * @var int|null
  84. */
  85. protected $_order;
  86. /**
  87. * ACL resource associated with this page
  88. *
  89. * @var string|Zend_Acl_Resource_Interface|null
  90. */
  91. protected $_resource;
  92. /**
  93. * ACL privilege associated with this page
  94. *
  95. * @var string|null
  96. */
  97. protected $_privilege;
  98. /**
  99. * Whether this page should be considered active
  100. *
  101. * @var bool
  102. */
  103. protected $_active = false;
  104. /**
  105. * Whether this page should be considered visible
  106. *
  107. * @var bool
  108. */
  109. protected $_visible = true;
  110. /**
  111. * Parent container
  112. *
  113. * @var Zend_Navigation_Container|null
  114. */
  115. protected $_parent;
  116. /**
  117. * Custom page properties, used by __set(), __get() and __isset()
  118. *
  119. * @var array
  120. */
  121. protected $_properties = array();
  122. // Initialization:
  123. /**
  124. * Factory for Zend_Navigation_Page classes
  125. *
  126. * A specific type to construct can be specified by specifying the key
  127. * 'type' in $options. If type is 'uri' or 'mvc', the type will be resolved
  128. * to Zend_Navigation_Page_Uri or Zend_Navigation_Page_Mvc. Any other value
  129. * for 'type' will be considered the full name of the class to construct.
  130. * A valid custom page class must extend Zend_Navigation_Page.
  131. *
  132. * If 'type' is not given, the type of page to construct will be determined
  133. * by the following rules:
  134. * - If $options contains either of the keys 'action', 'controller',
  135. * 'module', or 'route', a Zend_Navigation_Page_Mvc page will be created.
  136. * - If $options contains the key 'uri', a Zend_Navigation_Page_Uri page
  137. * will be created.
  138. *
  139. * @param array|Zend_Config $options options used for creating page
  140. * @return Zend_Navigation_Page a page instance
  141. * @throws Zend_Navigation_Exception if $options is not array/Zend_Config
  142. * @throws Zend_Exception if 'type' is specified and
  143. * Zend_Loader is unable to load the
  144. * class
  145. * @throws Zend_Navigation_Exception if something goes wrong during
  146. * instantiation of the page
  147. * @throws Zend_Navigation_Exception if 'type' is given, and the specified
  148. * type does not extend this class
  149. * @throws Zend_Navigation_Exception if unable to determine which class
  150. * to instantiate
  151. */
  152. public static function factory($options)
  153. {
  154. if ($options instanceof Zend_Config) {
  155. $options = $options->toArray();
  156. }
  157. if (!is_array($options)) {
  158. require_once 'Zend/Navigation/Exception.php';
  159. throw new Zend_Navigation_Exception(
  160. 'Invalid argument: $options must be an array or Zend_Config');
  161. }
  162. if (isset($options['type'])) {
  163. $type = $options['type'];
  164. if (is_string($type) && !empty($type)) {
  165. switch (strtolower($type)) {
  166. case 'mvc':
  167. $type = 'Zend_Navigation_Page_Mvc';
  168. break;
  169. case 'uri':
  170. $type = 'Zend_Navigation_Page_Uri';
  171. break;
  172. }
  173. if (!class_exists($type)) {
  174. require_once 'Zend/Loader.php';
  175. @Zend_Loader::loadClass($type);
  176. }
  177. $page = new $type($options);
  178. if (!$page instanceof Zend_Navigation_Page) {
  179. require_once 'Zend/Navigation/Exception.php';
  180. throw new Zend_Navigation_Exception(sprintf(
  181. 'Invalid argument: Detected type "%s", which ' .
  182. 'is not an instance of Zend_Navigation_Page',
  183. $type));
  184. }
  185. return $page;
  186. }
  187. }
  188. $hasUri = isset($options['uri']);
  189. $hasMvc = isset($options['action']) || isset($options['controller']) ||
  190. isset($options['module']) || isset($options['route']);
  191. if ($hasMvc) {
  192. require_once 'Zend/Navigation/Page/Mvc.php';
  193. return new Zend_Navigation_Page_Mvc($options);
  194. } elseif ($hasUri) {
  195. require_once 'Zend/Navigation/Page/Uri.php';
  196. return new Zend_Navigation_Page_Uri($options);
  197. } else {
  198. require_once 'Zend/Navigation/Exception.php';
  199. throw new Zend_Navigation_Exception(
  200. 'Invalid argument: Unable to determine class to instantiate');
  201. }
  202. }
  203. /**
  204. * Page constructor
  205. *
  206. * @param array|Zend_Config $options [optional] page options. Default is
  207. * null, which should set defaults.
  208. * @throws Zend_Navigation_Exception if invalid options are given
  209. */
  210. public function __construct($options = null)
  211. {
  212. if (is_array($options)) {
  213. $this->setOptions($options);
  214. } elseif ($options instanceof Zend_Config) {
  215. $this->setConfig($config);
  216. }
  217. // do custom initialization
  218. $this->_init();
  219. }
  220. /**
  221. * Initializes page (used by subclasses)
  222. *
  223. * @return void
  224. */
  225. protected function _init()
  226. {
  227. }
  228. /**
  229. * Sets page properties using a Zend_Config object
  230. *
  231. * @param Zend_Config $config config object to get properties from
  232. * @return Zend_Navigation_Page fluent interface, returns self
  233. * @throws Zend_Navigation_Exception if invalid options are given
  234. */
  235. public function setConfig(Zend_Config $config)
  236. {
  237. return $this->setOptions($config->toArray());
  238. }
  239. /**
  240. * Sets page properties using options from an associative array
  241. *
  242. * Each key in the array corresponds to the according set*() method, and
  243. * each word is separated by underscores, e.g. the option 'target'
  244. * corresponds to setTarget(), and the option 'reset_params' corresponds to
  245. * the method setResetParams().
  246. *
  247. * @param array $options associative array of options to set
  248. * @return Zend_Navigation_Page fluent interface, returns self
  249. * @throws Zend_Navigation_Exception if invalid options are given
  250. */
  251. public function setOptions(array $options)
  252. {
  253. foreach ($options as $key => $value) {
  254. $this->set($key, $value);
  255. }
  256. return $this;
  257. }
  258. // Accessors:
  259. /**
  260. * Sets page label
  261. *
  262. * @param string $label new page label
  263. * @return Zend_Navigation_Page fluent interface, returns self
  264. * @throws Zend_Navigation_Exception if empty/no string is given
  265. */
  266. public function setLabel($label)
  267. {
  268. if (null !== $label && !is_string($label)) {
  269. require_once 'Zend/Navigation/Exception.php';
  270. throw new Zend_Navigation_Exception(
  271. 'Invalid argument: $label must be a string or null');
  272. }
  273. $this->_label = $label;
  274. return $this;
  275. }
  276. /**
  277. * Returns page label
  278. *
  279. * @return string page label or null
  280. */
  281. public function getLabel()
  282. {
  283. return $this->_label;
  284. }
  285. /**
  286. * Sets page id
  287. *
  288. * @param string|null $id [optional] id to set. Default is null,
  289. * which sets no id.
  290. * @return Zend_Navigation_Page fluent interface, returns self
  291. * @throws Zend_Navigation_Exception if not given string or null
  292. */
  293. public function setId($id = null)
  294. {
  295. if (null !== $id && !is_string($id) && !is_numeric($id)) {
  296. require_once 'Zend/Navigation/Exception.php';
  297. throw new Zend_Navigation_Exception(
  298. 'Invalid argument: $id must be a string, number or null');
  299. }
  300. $this->_id = null === $id ? $id : (string) $id;
  301. return $this;
  302. }
  303. /**
  304. * Returns page id
  305. *
  306. * @return string|null page id or null
  307. */
  308. public function getId()
  309. {
  310. return $this->_id;
  311. }
  312. /**
  313. * Sets page CSS class
  314. *
  315. * @param string|null $class [optional] CSS class to set. Default
  316. * is null, which sets no CSS class.
  317. * @return Zend_Navigation_Page fluent interface, returns self
  318. * @throws Zend_Navigation_Exception if not given string or null
  319. */
  320. public function setClass($class = null)
  321. {
  322. if (null !== $class && !is_string($class)) {
  323. require_once 'Zend/Navigation/Exception.php';
  324. throw new Zend_Navigation_Exception(
  325. 'Invalid argument: $class must be a string or null');
  326. }
  327. $this->_class = $class;
  328. return $this;
  329. }
  330. /**
  331. * Returns page class (CSS)
  332. *
  333. * @return string|null page's CSS class or null
  334. */
  335. public function getClass()
  336. {
  337. return $this->_class;
  338. }
  339. /**
  340. * Sets page title
  341. *
  342. * @param string $title [optional] page title. Default is
  343. * null, which sets no title.
  344. * @return Zend_Navigation_Page fluent interface, returns self
  345. * @throws Zend_Navigation_Exception if not given string or null
  346. */
  347. public function setTitle($title = null)
  348. {
  349. if (null !== $title && !is_string($title)) {
  350. require_once 'Zend/Navigation/Exception.php';
  351. throw new Zend_Navigation_Exception(
  352. 'Invalid argument: $title must be a non-empty string');
  353. }
  354. $this->_title = $title;
  355. return $this;
  356. }
  357. /**
  358. * Returns page title
  359. *
  360. * @return string|null page title or null
  361. */
  362. public function getTitle()
  363. {
  364. return $this->_title;
  365. }
  366. /**
  367. * Sets page target
  368. *
  369. * @param string|null $target [optional] target to set. Default is
  370. * null, which sets no target.
  371. * @return Zend_Navigation_Page fluent interface, returns self
  372. * @throws Zend_Navigation_Exception if target is not string or null
  373. */
  374. public function setTarget($target = null)
  375. {
  376. if (null !== $target && !is_string($target)) {
  377. require_once 'Zend/Navigation/Exception.php';
  378. throw new Zend_Navigation_Exception(
  379. 'Invalid argument: $target must be a string or null');
  380. }
  381. $this->_target = $target;
  382. return $this;
  383. }
  384. /**
  385. * Returns page target
  386. *
  387. * @return string|null page target or null
  388. */
  389. public function getTarget()
  390. {
  391. return $this->_target;
  392. }
  393. /**
  394. * Sets the page's forward links to other pages
  395. *
  396. * This method expects an associative array of forward links to other pages,
  397. * where each element's key is the name of the relation (e.g. alternate,
  398. * prev, next, help, etc), and the value is a mixed value that could somehow
  399. * be considered a page.
  400. *
  401. * @param array|Zend_Config $relations [optional] an associative array of
  402. * forward links to other pages
  403. * @return Zend_Navigation_Page fluent interface, returns self
  404. */
  405. public function setRel($relations = null)
  406. {
  407. $this->_rel = array();
  408. if (null !== $relations) {
  409. if ($relations instanceof Zend_Config) {
  410. $relations = $relations->toArray();
  411. }
  412. if (!is_array($relations)) {
  413. require_once 'Zend/Navigation/Exception.php';
  414. throw new Zend_Navigation_Exception(
  415. 'Invalid argument: $relations must be an ' .
  416. 'array or an instance of Zend_Config');
  417. }
  418. foreach ($relations as $name => $relation) {
  419. if (is_string($name)) {
  420. $this->_rel[$name] = $relation;
  421. }
  422. }
  423. }
  424. return $this;
  425. }
  426. /**
  427. * Returns the page's forward links to other pages
  428. *
  429. * This method returns an associative array of forward links to other pages,
  430. * where each element's key is the name of the relation (e.g. alternate,
  431. * prev, next, help, etc), and the value is a mixed value that could somehow
  432. * be considered a page.
  433. *
  434. * @param string $relation [optional] name of relation to return. If not
  435. * given, all relations will be returned.
  436. * @return array an array of relations. If $relation is not
  437. * specified, all relations will be returned in
  438. * an associative array.
  439. */
  440. public function getRel($relation = null)
  441. {
  442. if (null !== $relation) {
  443. return isset($this->_rel[$relation]) ?
  444. $this->_rel[$relation] :
  445. null;
  446. }
  447. return $this->_rel;
  448. }
  449. /**
  450. * Sets the page's reverse links to other pages
  451. *
  452. * This method expects an associative array of reverse links to other pages,
  453. * where each element's key is the name of the relation (e.g. alternate,
  454. * prev, next, help, etc), and the value is a mixed value that could somehow
  455. * be considered a page.
  456. *
  457. * @param array|Zend_Config $relations [optional] an associative array of
  458. * reverse links to other pages
  459. * @return Zend_Navigation_Page fluent interface, returns self
  460. */
  461. public function setRev($relations = null)
  462. {
  463. $this->_rev = array();
  464. if (null !== $relations) {
  465. if ($relations instanceof Zend_Config) {
  466. $relations = $relations->toArray();
  467. }
  468. if (!is_array($relations)) {
  469. require_once 'Zend/Navigation/Exception.php';
  470. throw new Zend_Navigation_Exception(
  471. 'Invalid argument: $relations must be an ' .
  472. 'array or an instance of Zend_Config');
  473. }
  474. foreach ($relations as $name => $relation) {
  475. if (is_string($name)) {
  476. $this->_rev[$name] = $relation;
  477. }
  478. }
  479. }
  480. return $this;
  481. }
  482. /**
  483. * Returns the page's reverse links to other pages
  484. *
  485. * This method returns an associative array of forward links to other pages,
  486. * where each element's key is the name of the relation (e.g. alternate,
  487. * prev, next, help, etc), and the value is a mixed value that could somehow
  488. * be considered a page.
  489. *
  490. * @param string $relation [optional] name of relation to return. If not
  491. * given, all relations will be returned.
  492. * @return array an array of relations. If $relation is not
  493. * specified, all relations will be returned in
  494. * an associative array.
  495. */
  496. public function getRev($relation = null)
  497. {
  498. if (null !== $relation) {
  499. return isset($this->_rev[$relation]) ?
  500. $this->_rev[$relation] :
  501. null;
  502. }
  503. return $this->_rev;
  504. }
  505. /**
  506. * Sets page order to use in parent container
  507. *
  508. * @param int $order [optional] page order in container.
  509. * Default is null, which sets no
  510. * specific order.
  511. * @return Zend_Navigation_Page fluent interface, returns self
  512. * @throws Zend_Navigation_Exception if order is not integer or null
  513. */
  514. public function setOrder($order = null)
  515. {
  516. if (is_string($order)) {
  517. $temp = (int) $order;
  518. if ($temp < 0 || $temp > 0 || $order == '0') {
  519. $order = $temp;
  520. }
  521. }
  522. if (null !== $order && !is_int($order)) {
  523. require_once 'Zend/Navigation/Exception.php';
  524. throw new Zend_Navigation_Exception(
  525. 'Invalid argument: $order must be an integer or null, ' .
  526. 'or a string that casts to an integer');
  527. }
  528. $this->_order = $order;
  529. // notify parent, if any
  530. if (isset($this->_parent)) {
  531. $this->_parent->notifyOrderUpdated();
  532. }
  533. return $this;
  534. }
  535. /**
  536. * Returns page order used in parent container
  537. *
  538. * @return int|null page order or null
  539. */
  540. public function getOrder()
  541. {
  542. return $this->_order;
  543. }
  544. /**
  545. * Sets ACL resource assoicated with this page
  546. *
  547. * @param string|Zend_Acl_Resource_Interface $resource [optional] resource
  548. * to associate with
  549. * page. Default is
  550. * null, which sets no
  551. * resource.
  552. * @throws Zend_Navigation_Exception if $resource if
  553. * invalid
  554. * @return Zend_Navigation_Page fluent interface,
  555. * returns self
  556. */
  557. public function setResource($resource = null)
  558. {
  559. if (null === $resource || is_string($resource) ||
  560. $resource instanceof Zend_Acl_Resource_Interface) {
  561. $this->_resource = $resource;
  562. } else {
  563. require_once 'Zend/Navigation/Exception.php';
  564. throw new Zend_Navigation_Exception(
  565. 'Invalid argument: $resource must be null, a string, ' .
  566. ' or an instance of Zend_Acl_Resource_Interface');
  567. }
  568. return $this;
  569. }
  570. /**
  571. * Returns ACL resource assoicated with this page
  572. *
  573. * @return string|Zend_Acl_Resource_Interface|null ACL resource or null
  574. */
  575. public function getResource()
  576. {
  577. return $this->_resource;
  578. }
  579. /**
  580. * Sets ACL privilege associated with this page
  581. *
  582. * @param string|null $privilege [optional] ACL privilege to associate
  583. * with this page. Default is null, which
  584. * sets no privilege.
  585. * @return Zend_Navigation_Page fluent interface, returns self
  586. */
  587. public function setPrivilege($privilege = null)
  588. {
  589. $this->_privilege = is_string($privilege) ? $privilege : null;
  590. return $this;
  591. }
  592. /**
  593. * Returns ACL privilege associated with this page
  594. *
  595. * @return string|null ACL privilege or null
  596. */
  597. public function getPrivilege()
  598. {
  599. return $this->_privilege;
  600. }
  601. /**
  602. * Sets whether page should be considered active or not
  603. *
  604. * @param bool $active [optional] whether page should be
  605. * considered active or not. Default is true.
  606. * @return Zend_Navigation_Page fluent interface, returns self
  607. */
  608. public function setActive($active = true)
  609. {
  610. $this->_active = (bool) $active;
  611. return $this;
  612. }
  613. /**
  614. * Returns whether page should be considered active or not
  615. *
  616. * @param bool $recursive [optional] whether page should be considered
  617. * active if any child pages are active. Default is
  618. * false.
  619. * @return bool whether page should be considered active
  620. */
  621. public function isActive($recursive = false)
  622. {
  623. if (!$this->_active && $recursive) {
  624. foreach ($this->_pages as $page) {
  625. if ($page->isActive(true)) {
  626. return true;
  627. }
  628. }
  629. return false;
  630. }
  631. return $this->_active;
  632. }
  633. /**
  634. * Proxy to isActive()
  635. *
  636. * @param bool $recursive [optional] whether page should be considered
  637. * active if any child pages are active. Default
  638. * is false.
  639. * @return bool whether page should be considered active
  640. */
  641. public function getActive($recursive = false)
  642. {
  643. return $this->isActive($recursive);
  644. }
  645. /**
  646. * Sets whether the page should be visible or not
  647. *
  648. * @param bool $visible [optional] whether page should be
  649. * considered visible or not. Default is true.
  650. * @return Zend_Navigation_Page fluent interface, returns self
  651. */
  652. public function setVisible($visible = true)
  653. {
  654. $this->_visible = (bool) $visible;
  655. return $this;
  656. }
  657. /**
  658. * Returns a boolean value indicating whether the page is visible
  659. *
  660. * @param bool $recursive [optional] whether page should be considered
  661. * invisible if parent is invisible. Default is
  662. * false.
  663. * @return bool whether page should be considered visible
  664. */
  665. public function isVisible($recursive = false)
  666. {
  667. if ($recursive && isset($this->_parent) &&
  668. $this->_parent instanceof Zend_Navigation_Page) {
  669. if (!$this->_parent->isVisible(true)) {
  670. return false;
  671. }
  672. }
  673. return $this->_visible;
  674. }
  675. /**
  676. * Proxy to isVisible()
  677. *
  678. * Returns a boolean value indicating whether the page is visible
  679. *
  680. * @param bool $recursive [optional] whether page should be considered
  681. * invisible if parent is invisible. Default is
  682. * false.
  683. * @return bool whether page should be considered visible
  684. */
  685. public function getVisible($recursive = false)
  686. {
  687. return $this->isVisible($recursive);
  688. }
  689. /**
  690. * Sets parent container
  691. *
  692. * @param Zend_Navigation_Container $parent [optional] new parent to set.
  693. * Default is null which will set
  694. * no parent.
  695. * @return Zend_Navigation_Page fluent interface, returns self
  696. */
  697. public function setParent(Zend_Navigation_Container $parent = null)
  698. {
  699. if ($parent === $this) {
  700. require_once 'Zend/Navigation/Exception.php';
  701. throw new Zend_Navigation_Exception(
  702. 'A page cannot have itself as a parent');
  703. }
  704. // return if the given parent already is parent
  705. if ($parent === $this->_parent) {
  706. return $this;
  707. }
  708. // remove from old parent
  709. if (null !== $this->_parent) {
  710. $this->_parent->removePage($this);
  711. }
  712. // set new parent
  713. $this->_parent = $parent;
  714. // add to parent if page and not already a child
  715. if (null !== $this->_parent && !$this->_parent->hasPage($this, false)) {
  716. $this->_parent->addPage($this);
  717. }
  718. return $this;
  719. }
  720. /**
  721. * Returns parent container
  722. *
  723. * @return Zend_Navigation_Container|null parent container or null
  724. */
  725. public function getParent()
  726. {
  727. return $this->_parent;
  728. }
  729. /**
  730. * Sets the given property
  731. *
  732. * If the given property is native (id, class, title, etc), the matching
  733. * set method will be used. Otherwise, it will be set as a custom property.
  734. *
  735. * @param string $property property name
  736. * @param mixed $value value to set
  737. * @return Zend_Navigation_Page fluent interface, returns self
  738. * @throws Zend_Navigation_Exception if property name is invalid
  739. */
  740. public function set($property, $value)
  741. {
  742. if (!is_string($property) || empty($property)) {
  743. require_once 'Zend/Navigation/Exception.php';
  744. throw new Zend_Navigation_Exception(
  745. 'Invalid argument: $property must be a non-empty string');
  746. }
  747. $method = 'set' . self::_normalizePropertyName($property);
  748. if ($method != 'setOptions' && $method != 'setConfig' &&
  749. method_exists($this, $method)) {
  750. $this->$method($value);
  751. } else {
  752. $this->_properties[$property] = $value;
  753. }
  754. return $this;
  755. }
  756. /**
  757. * Returns the value of the given property
  758. *
  759. * If the given property is native (id, class, title, etc), the matching
  760. * get method will be used. Otherwise, it will return the matching custom
  761. * property, or null if not found.
  762. *
  763. * @param string $property property name
  764. * @return mixed the property's value or null
  765. * @throws Zend_Navigation_Exception if property name is invalid
  766. */
  767. public function get($property)
  768. {
  769. if (!is_string($property) || empty($property)) {
  770. require_once 'Zend/Navigation/Exception.php';
  771. throw new Zend_Navigation_Exception(
  772. 'Invalid argument: $property must be a non-empty string');
  773. }
  774. $method = 'get' . self::_normalizePropertyName($property);
  775. if (method_exists($this, $method)) {
  776. return $this->$method();
  777. } elseif (isset($this->_properties[$property])) {
  778. return $this->_properties[$property];
  779. }
  780. return null;
  781. }
  782. // Magic overloads:
  783. /**
  784. * Sets a custom property
  785. *
  786. * Magic overload for enabling <code>$page->propname = $value</code>.
  787. *
  788. * @param string $name property name
  789. * @param mixed $value value to set
  790. * @return void
  791. * @throws Zend_Navigation_Exception if property name is invalid
  792. */
  793. public function __set($name, $value)
  794. {
  795. $this->set($name, $value);
  796. }
  797. /**
  798. * Returns a property, or null if it doesn't exist
  799. *
  800. * Magic overload for enabling <code>$page->propname</code>.
  801. *
  802. * @param string $name property name
  803. * @return mixed property value or null
  804. * @throws Zend_Navigation_Exception if property name is invalid
  805. */
  806. public function __get($name)
  807. {
  808. return $this->get($name);
  809. }
  810. /**
  811. * Checks if a property is set
  812. *
  813. * Magic overload for enabling <code>isset($page->propname)</code>.
  814. *
  815. * Returns true if the property is native (id, class, title, etc), and
  816. * true or false if it's a custom property (depending on whether the
  817. * property actually is set).
  818. *
  819. * @param string $name property name
  820. * @return bool whether the given property exists
  821. */
  822. public function __isset($name)
  823. {
  824. $method = 'get' . self::_normalizePropertyName($name);
  825. if (method_exists($this, $method)) {
  826. return true;
  827. }
  828. return isset($this->_properties[$name]);
  829. }
  830. /**
  831. * Unsets the given custom property
  832. *
  833. * Magic overload for enabling <code>unset($page->propname)</code>.
  834. *
  835. * @param string $name property name
  836. * @return void
  837. * @throws Zend_Navigation_Exception if the property is native
  838. */
  839. public function __unset($name)
  840. {
  841. $method = 'set' . self::_normalizePropertyName($name);
  842. if (method_exists($this, $method)) {
  843. require_once 'Zend/Navigation/Exception.php';
  844. throw new Zend_Navigation_Exception(sprintf(
  845. 'Unsetting native property "%s" is not allowed',
  846. $name));
  847. }
  848. if (isset($this->_properties[$name])) {
  849. unset($this->_properties[$name]);
  850. }
  851. }
  852. /**
  853. * Returns page label
  854. *
  855. * Magic overload for enabling <code>echo $page</code>.
  856. *
  857. * @return string page label
  858. */
  859. public function __toString()
  860. {
  861. return $this->_label;
  862. }
  863. // Public methods:
  864. /**
  865. * Adds a forward relation to the page
  866. *
  867. * @param string $relation relation name (e.g. alternate, glossary,
  868. * canonical, etc)
  869. * @param mixed $value value to set for relation
  870. * @return Zend_Navigation_Page fluent interface, returns self
  871. */
  872. public function addRel($relation, $value)
  873. {
  874. if (is_string($relation)) {
  875. $this->_rel[$relation] = $value;
  876. }
  877. return $this;
  878. }
  879. /**
  880. * Adds a reverse relation to the page
  881. *
  882. * @param string $relation relation name (e.g. alternate, glossary,
  883. * canonical, etc)
  884. * @param mixed $value value to set for relation
  885. * @return Zend_Navigation_Page fluent interface, returns self
  886. */
  887. public function addRev($relation, $value)
  888. {
  889. if (is_string($relation)) {
  890. $this->_rev[$relation] = $value;
  891. }
  892. return $this;
  893. }
  894. /**
  895. * Removes a forward relation from the page
  896. *
  897. * @param string $relation name of relation to remove
  898. * @return Zend_Navigation_Page fluent interface, returns self
  899. */
  900. public function removeRel($relation)
  901. {
  902. if (isset($this->_rel[$relation])) {
  903. unset($this->_rel[$relation]);
  904. }
  905. return $this;
  906. }
  907. /**
  908. * Removes a reverse relation from the page
  909. *
  910. * @param string $relation name of relation to remove
  911. * @return Zend_Navigation_Page fluent interface, returns self
  912. */
  913. public function removeRev($relation)
  914. {
  915. if (isset($this->_rev[$relation])) {
  916. unset($this->_rev[$relation]);
  917. }
  918. return $this;
  919. }
  920. /**
  921. * Returns an array containing the defined forward relations
  922. *
  923. * @return array defined forward relations
  924. */
  925. public function getDefinedRel()
  926. {
  927. return array_keys($this->_rel);
  928. }
  929. /**
  930. * Returns an array containing the defined reverse relations
  931. *
  932. * @return array defined reverse relations
  933. */
  934. public function getDefinedRev()
  935. {
  936. return array_keys($this->_rev);
  937. }
  938. /**
  939. * Returns custom properties as an array
  940. *
  941. * @return array an array containing custom properties
  942. */
  943. public function getCustomProperties()
  944. {
  945. return $this->_properties;
  946. }
  947. /**
  948. * Returns a hash code value for the page
  949. *
  950. * @return string a hash code value for this page
  951. */
  952. public final function hashCode()
  953. {
  954. return spl_object_hash($this);
  955. }
  956. /**
  957. * Returns an array representation of the page
  958. *
  959. * @return array associative array containing all page properties
  960. */
  961. public function toArray()
  962. {
  963. return array_merge(
  964. $this->getCustomProperties(),
  965. array(
  966. 'label' => $this->getlabel(),
  967. 'id' => $this->getId(),
  968. 'class' => $this->getClass(),
  969. 'title' => $this->getTitle(),
  970. 'target' => $this->getTarget(),
  971. 'rel' => $this->getRel(),
  972. 'rev' => $this->getRev(),
  973. 'order' => $this->getOrder(),
  974. 'resource' => $this->getResource(),
  975. 'privilege' => $this->getPrivilege(),
  976. 'active' => $this->isActive(),
  977. 'visible' => $this->isVisible(),
  978. 'type' => get_class($this),
  979. 'pages' => parent::toArray()
  980. ));
  981. }
  982. // Internal methods:
  983. /**
  984. * Normalizes a property name
  985. *
  986. * @param string $property property name to normalize
  987. * @return string normalized property name
  988. */
  989. protected static function _normalizePropertyName($property)
  990. {
  991. return str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
  992. }
  993. // Abstract methods:
  994. /**
  995. * Returns href for this page
  996. *
  997. * @return string the page's href
  998. */
  999. abstract public function getHref();
  1000. }