PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/applications/core/lib/Zend/Navigation/Page.php

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