diff -r 5b37998e522e -r 162c1de6545a web/lib/Zend/Navigation/Container.php --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/Zend/Navigation/Container.php Fri Mar 11 15:05:35 2011 +0100 @@ -0,0 +1,503 @@ +_dirtyIndex) { + $newIndex = array(); + $index = 0; + + foreach ($this->_pages as $hash => $page) { + $order = $page->getOrder(); + if ($order === null) { + $newIndex[$hash] = $index; + $index++; + } else { + $newIndex[$hash] = $order; + } + } + + asort($newIndex); + $this->_index = $newIndex; + $this->_dirtyIndex = false; + } + } + + // Public methods: + + /** + * Notifies container that the order of pages are updated + * + * @return void + */ + public function notifyOrderUpdated() + { + $this->_dirtyIndex = true; + } + + /** + * Adds a page to the container + * + * This method will inject the container as the given page's parent by + * calling {@link Zend_Navigation_Page::setParent()}. + * + * @param Zend_Navigation_Page|array|Zend_Config $page page to add + * @return Zend_Navigation_Container fluent interface, + * returns self + * @throws Zend_Navigation_Exception if page is invalid + */ + public function addPage($page) + { + if ($page === $this) { + require_once 'Zend/Navigation/Exception.php'; + throw new Zend_Navigation_Exception( + 'A page cannot have itself as a parent'); + } + + if (is_array($page) || $page instanceof Zend_Config) { + require_once 'Zend/Navigation/Page.php'; + $page = Zend_Navigation_Page::factory($page); + } elseif (!$page instanceof Zend_Navigation_Page) { + require_once 'Zend/Navigation/Exception.php'; + throw new Zend_Navigation_Exception( + 'Invalid argument: $page must be an instance of ' . + 'Zend_Navigation_Page or Zend_Config, or an array'); + } + + $hash = $page->hashCode(); + + if (array_key_exists($hash, $this->_index)) { + // page is already in container + return $this; + } + + // adds page to container and sets dirty flag + $this->_pages[$hash] = $page; + $this->_index[$hash] = $page->getOrder(); + $this->_dirtyIndex = true; + + // inject self as page parent + $page->setParent($this); + + return $this; + } + + /** + * Adds several pages at once + * + * @param array|Zend_Config $pages pages to add + * @return Zend_Navigation_Container fluent interface, returns self + * @throws Zend_Navigation_Exception if $pages is not array or Zend_Config + */ + public function addPages($pages) + { + if ($pages instanceof Zend_Config) { + $pages = $pages->toArray(); + } + + if (!is_array($pages)) { + require_once 'Zend/Navigation/Exception.php'; + throw new Zend_Navigation_Exception( + 'Invalid argument: $pages must be an array or an ' . + 'instance of Zend_Config'); + } + + foreach ($pages as $page) { + $this->addPage($page); + } + + return $this; + } + + /** + * Sets pages this container should have, removing existing pages + * + * @param array $pages pages to set + * @return Zend_Navigation_Container fluent interface, returns self + */ + public function setPages(array $pages) + { + $this->removePages(); + return $this->addPages($pages); + } + + /** + * Returns pages in the container + * + * @return array array of Zend_Navigation_Page instances + */ + public function getPages() + { + return $this->_pages; + } + + /** + * Removes the given page from the container + * + * @param Zend_Navigation_Page|int $page page to remove, either a page + * instance or a specific page order + * @return bool whether the removal was + * successful + */ + public function removePage($page) + { + if ($page instanceof Zend_Navigation_Page) { + $hash = $page->hashCode(); + } elseif (is_int($page)) { + $this->_sort(); + if (!$hash = array_search($page, $this->_index)) { + return false; + } + } else { + return false; + } + + if (isset($this->_pages[$hash])) { + unset($this->_pages[$hash]); + unset($this->_index[$hash]); + $this->_dirtyIndex = true; + return true; + } + + return false; + } + + /** + * Removes all pages in container + * + * @return Zend_Navigation_Container fluent interface, returns self + */ + public function removePages() + { + $this->_pages = array(); + $this->_index = array(); + return $this; + } + + /** + * Checks if the container has the given page + * + * @param Zend_Navigation_Page $page page to look for + * @param bool $recursive [optional] whether to search + * recursively. Default is false. + * @return bool whether page is in container + */ + public function hasPage(Zend_Navigation_Page $page, $recursive = false) + { + if (array_key_exists($page->hashCode(), $this->_index)) { + return true; + } elseif ($recursive) { + foreach ($this->_pages as $childPage) { + if ($childPage->hasPage($page, true)) { + return true; + } + } + } + + return false; + } + + /** + * Returns true if container contains any pages + * + * @return bool whether container has any pages + */ + public function hasPages() + { + return count($this->_index) > 0; + } + + /** + * Returns a child page matching $property == $value, or null if not found + * + * @param string $property name of property to match against + * @param mixed $value value to match property against + * @return Zend_Navigation_Page|null matching page or null + */ + public function findOneBy($property, $value) + { + $iterator = new RecursiveIteratorIterator($this, + RecursiveIteratorIterator::SELF_FIRST); + + foreach ($iterator as $page) { + if ($page->get($property) == $value) { + return $page; + } + } + + return null; + } + + /** + * Returns all child pages matching $property == $value, or an empty array + * if no pages are found + * + * @param string $property name of property to match against + * @param mixed $value value to match property against + * @return array array containing only Zend_Navigation_Page + * instances + */ + public function findAllBy($property, $value) + { + $found = array(); + + $iterator = new RecursiveIteratorIterator($this, + RecursiveIteratorIterator::SELF_FIRST); + + foreach ($iterator as $page) { + if ($page->get($property) == $value) { + $found[] = $page; + } + } + + return $found; + } + + /** + * Returns page(s) matching $property == $value + * + * @param string $property name of property to match against + * @param mixed $value value to match property against + * @param bool $all [optional] whether an array of all matching + * pages should be returned, or only the first. + * If true, an array will be returned, even if not + * matching pages are found. If false, null will + * be returned if no matching page is found. + * Default is false. + * @return Zend_Navigation_Page|null matching page or null + */ + public function findBy($property, $value, $all = false) + { + if ($all) { + return $this->findAllBy($property, $value); + } else { + return $this->findOneBy($property, $value); + } + } + + /** + * Magic overload: Proxy calls to finder methods + * + * Examples of finder calls: + * + * // METHOD // SAME AS + * $nav->findByLabel('foo'); // $nav->findOneBy('label', 'foo'); + * $nav->findOneByLabel('foo'); // $nav->findOneBy('label', 'foo'); + * $nav->findAllByClass('foo'); // $nav->findAllBy('class', 'foo'); + * + * + * @param string $method method name + * @param array $arguments method arguments + * @throws Zend_Navigation_Exception if method does not exist + */ + public function __call($method, $arguments) + { + if (@preg_match('/(find(?:One|All)?By)(.+)/', $method, $match)) { + return $this->{$match[1]}($match[2], $arguments[0]); + } + + require_once 'Zend/Navigation/Exception.php'; + throw new Zend_Navigation_Exception(sprintf( + 'Bad method call: Unknown method %s::%s', + get_class($this), + $method)); + } + + /** + * Returns an array representation of all pages in container + * + * @return array + */ + public function toArray() + { + $pages = array(); + + $this->_dirtyIndex = true; + $this->_sort(); + $indexes = array_keys($this->_index); + foreach ($indexes as $hash) { + $pages[] = $this->_pages[$hash]->toArray(); + } + return $pages; + } + + // RecursiveIterator interface: + + /** + * Returns current page + * + * Implements RecursiveIterator interface. + * + * @return Zend_Navigation_Page current page or null + * @throws Zend_Navigation_Exception if the index is invalid + */ + public function current() + { + $this->_sort(); + current($this->_index); + $hash = key($this->_index); + + if (isset($this->_pages[$hash])) { + return $this->_pages[$hash]; + } else { + require_once 'Zend/Navigation/Exception.php'; + throw new Zend_Navigation_Exception( + 'Corruption detected in container; ' . + 'invalid key found in internal iterator'); + } + } + + /** + * Returns hash code of current page + * + * Implements RecursiveIterator interface. + * + * @return string hash code of current page + */ + public function key() + { + $this->_sort(); + return key($this->_index); + } + + /** + * Moves index pointer to next page in the container + * + * Implements RecursiveIterator interface. + * + * @return void + */ + public function next() + { + $this->_sort(); + next($this->_index); + } + + /** + * Sets index pointer to first page in the container + * + * Implements RecursiveIterator interface. + * + * @return void + */ + public function rewind() + { + $this->_sort(); + reset($this->_index); + } + + /** + * Checks if container index is valid + * + * Implements RecursiveIterator interface. + * + * @return bool + */ + public function valid() + { + $this->_sort(); + return current($this->_index) !== false; + } + + /** + * Proxy to hasPages() + * + * Implements RecursiveIterator interface. + * + * @return bool whether container has any pages + */ + public function hasChildren() + { + return $this->hasPages(); + } + + /** + * Returns the child container. + * + * Implements RecursiveIterator interface. + * + * @return Zend_Navigation_Page|null + */ + public function getChildren() + { + $hash = key($this->_index); + + if (isset($this->_pages[$hash])) { + return $this->_pages[$hash]; + } + + return null; + } + + // Countable interface: + + /** + * Returns number of pages in container + * + * Implements Countable interface. + * + * @return int number of pages in the container + */ + public function count() + { + return count($this->_index); + } +}