00001 <?php
00026 require_once 'Zend/View/Helper/Navigation/HelperAbstract.php';
00027
00037 class Zend_View_Helper_Navigation_Links
00038 extends Zend_View_Helper_Navigation_HelperAbstract
00039 {
00045 const RENDER_ALTERNATE = 0x0001;
00046 const RENDER_STYLESHEET = 0x0002;
00047 const RENDER_START = 0x0004;
00048 const RENDER_NEXT = 0x0008;
00049 const RENDER_PREV = 0x0010;
00050 const RENDER_CONTENTS = 0x0020;
00051 const RENDER_INDEX = 0x0040;
00052 const RENDER_GLOSSARY = 0x0080;
00053 const RENDER_COPYRIGHT = 0x0100;
00054 const RENDER_CHAPTER = 0x0200;
00055 const RENDER_SECTION = 0x0400;
00056 const RENDER_SUBSECTION = 0x0800;
00057 const RENDER_APPENDIX = 0x1000;
00058 const RENDER_HELP = 0x2000;
00059 const RENDER_BOOKMARK = 0x4000;
00060 const RENDER_CUSTOM = 0x8000;
00061 const RENDER_ALL = 0xffff;
00069 protected static $_RELATIONS = array(
00070 self::RENDER_ALTERNATE => 'alternate',
00071 self::RENDER_STYLESHEET => 'stylesheet',
00072 self::RENDER_START => 'start',
00073 self::RENDER_NEXT => 'next',
00074 self::RENDER_PREV => 'prev',
00075 self::RENDER_CONTENTS => 'contents',
00076 self::RENDER_INDEX => 'index',
00077 self::RENDER_GLOSSARY => 'glossary',
00078 self::RENDER_COPYRIGHT => 'copyright',
00079 self::RENDER_CHAPTER => 'chapter',
00080 self::RENDER_SECTION => 'section',
00081 self::RENDER_SUBSECTION => 'subsection',
00082 self::RENDER_APPENDIX => 'appendix',
00083 self::RENDER_HELP => 'help',
00084 self::RENDER_BOOKMARK => 'bookmark'
00085 );
00086
00094 protected $_renderFlag = self::RENDER_ALL;
00095
00106 protected $_root;
00107
00117 public function links(Zend_Navigation_Container $container = null)
00118 {
00119 if (null !== $container) {
00120 $this->setContainer($container);
00121 }
00122
00123 return $this;
00124 }
00125
00141 public function __call($method, array $arguments = array())
00142 {
00143 if (@preg_match('/find(Rel|Rev)(.+)/', $method, $match)) {
00144 return $this->findRelation($arguments[0],
00145 strtolower($match[1]),
00146 strtolower($match[2]));
00147 }
00148
00149 return parent::__call($method, $arguments);
00150 }
00151
00152
00153
00184 public function setRenderFlag($renderFlag)
00185 {
00186 $this->_renderFlag = (int) $renderFlag;
00187 return $this;
00188 }
00189
00195 public function getRenderFlag()
00196 {
00197 return $this->_renderFlag;
00198 }
00199
00200
00201
00225 public function findAllRelations(Zend_Navigation_Page $page,
00226 $flag = null)
00227 {
00228 if (!is_int($flag)) {
00229 $flag = self::RENDER_ALL;
00230 }
00231
00232 $result = array('rel' => array(), 'rev' => array());
00233 $native = array_values(self::$_RELATIONS);
00234
00235 foreach (array_keys($result) as $rel) {
00236 $meth = 'getDefined' . ucfirst($rel);
00237 $types = array_merge($native, array_diff($page->$meth(), $native));
00238
00239 foreach ($types as $type) {
00240 if (!$relFlag = array_search($type, self::$_RELATIONS)) {
00241 $relFlag = self::RENDER_CUSTOM;
00242 }
00243 if (!($flag & $relFlag)) {
00244 continue;
00245 }
00246 if ($found = $this->findRelation($page, $rel, $type)) {
00247 if (!is_array($found)) {
00248 $found = array($found);
00249 }
00250 $result[$rel][$type] = $found;
00251 }
00252 }
00253 }
00254
00255 return $result;
00256 }
00257
00270 public function findRelation(Zend_Navigation_Page $page, $rel, $type)
00271 {
00272 if (!in_array($rel, array('rel', 'rev'))) {
00273 require_once 'Zend/View/Exception.php';
00274 throw new Zend_View_Exception(sprintf(
00275 'Invalid argument: $rel must be "rel" or "rev"; "%s" given',
00276 $rel));
00277 }
00278
00279 if (!$result = $this->_findFromProperty($page, $rel, $type)) {
00280 $result = $this->_findFromSearch($page, $rel, $type);
00281 }
00282
00283 return $result;
00284 }
00285
00295 protected function _findFromProperty(Zend_Navigation_Page $page, $rel, $type)
00296 {
00297 $method = 'get' . ucfirst($rel);
00298 if ($result = $page->$method($type)) {
00299 if ($result = $this->_convertToPages($result)) {
00300 if (!is_array($result)) {
00301 $result = array($result);
00302 }
00303
00304 foreach ($result as $key => $page) {
00305 if (!$this->accept($page)) {
00306 unset($result[$key]);
00307 }
00308 }
00309
00310 return count($result) == 1 ? $result[0] : $result;
00311 }
00312 }
00313
00314 return null;
00315 }
00316
00326 protected function _findFromSearch(Zend_Navigation_Page $page, $rel, $type)
00327 {
00328 $found = null;
00329
00330 $method = 'search' . ucfirst($rel) . ucfirst($type);
00331 if (method_exists($this, $method)) {
00332 $found = $this->$method($page);
00333 }
00334
00335 return $found;
00336 }
00337
00338
00339
00352 public function searchRelStart(Zend_Navigation_Page $page)
00353 {
00354 $found = $this->_findRoot($page);
00355 if (!$found instanceof Zend_Navigation_Page) {
00356 $found->rewind();
00357 $found = $found->current();
00358 }
00359
00360 if ($found === $page || !$this->accept($found)) {
00361 $found = null;
00362 }
00363
00364 return $found;
00365 }
00366
00379 public function searchRelNext(Zend_Navigation_Page $page)
00380 {
00381 $found = null;
00382 $break = false;
00383 $iterator = new RecursiveIteratorIterator($this->_findRoot($page),
00384 RecursiveIteratorIterator::SELF_FIRST);
00385 foreach ($iterator as $intermediate) {
00386 if ($intermediate === $page) {
00387
00388 $break = true;
00389 continue;
00390 }
00391
00392 if ($break && $this->accept($intermediate)) {
00393 $found = $intermediate;
00394 break;
00395 }
00396 }
00397
00398 return $found;
00399 }
00400
00412 public function searchRelPrev(Zend_Navigation_Page $page)
00413 {
00414 $found = null;
00415 $prev = null;
00416 $iterator = new RecursiveIteratorIterator(
00417 $this->_findRoot($page),
00418 RecursiveIteratorIterator::SELF_FIRST);
00419 foreach ($iterator as $intermediate) {
00420 if (!$this->accept($intermediate)) {
00421 continue;
00422 }
00423 if ($intermediate === $page) {
00424 $found = $prev;
00425 break;
00426 }
00427
00428 $prev = $intermediate;
00429 }
00430
00431 return $found;
00432 }
00433
00444 public function searchRelChapter(Zend_Navigation_Page $page)
00445 {
00446 $found = array();
00447
00448
00449 $root = $this->_findRoot($page);
00450
00451
00452 $start = $this->findRelation($page, 'rel', 'start');
00453 if (!is_array($start)) {
00454 $start = array($start);
00455 }
00456
00457 foreach ($root as $chapter) {
00458
00459 if ($chapter !== $page &&
00460 !in_array($chapter, $start) &&
00461 $this->accept($chapter)) {
00462 $found[] = $chapter;
00463 }
00464 }
00465
00466 switch (count($found)) {
00467 case 0:
00468 return null;
00469 case 1:
00470 return $found[0];
00471 default:
00472 return $found;
00473 }
00474 }
00475
00486 public function searchRelSection(Zend_Navigation_Page $page)
00487 {
00488 $found = array();
00489
00490
00491 if ($page->hasPages() && $this->_findRoot($page)->hasPage($page)) {
00492 foreach ($page as $section) {
00493 if ($this->accept($section)) {
00494 $found[] = $section;
00495 }
00496 }
00497 }
00498
00499 switch (count($found)) {
00500 case 0:
00501 return null;
00502 case 1:
00503 return $found[0];
00504 default:
00505 return $found;
00506 }
00507 }
00508
00520 public function searchRelSubsection(Zend_Navigation_Page $page)
00521 {
00522 $found = array();
00523
00524 if ($page->hasPages()) {
00525
00526 foreach ($this->_findRoot($page) as $chapter) {
00527
00528 if ($chapter->hasPage($page)) {
00529 foreach ($page as $subsection) {
00530 if ($this->accept($subsection)) {
00531 $found[] = $subsection;
00532 }
00533 }
00534 }
00535 }
00536 }
00537
00538 switch (count($found)) {
00539 case 0:
00540 return null;
00541 case 1:
00542 return $found[0];
00543 default:
00544 return $found;
00545 }
00546 }
00547
00558 public function searchRevSection(Zend_Navigation_Page $page)
00559 {
00560 $found = null;
00561
00562 if ($parent = $page->getParent()) {
00563 if ($parent instanceof Zend_Navigation_Page &&
00564 $this->_findRoot($page)->hasPage($parent)) {
00565 $found = $parent;
00566 }
00567 }
00568
00569 return $found;
00570 }
00571
00583 public function searchRevSubsection(Zend_Navigation_Page $page)
00584 {
00585 $found = null;
00586
00587 if ($parent = $page->getParent()) {
00588 if ($parent instanceof Zend_Navigation_Page) {
00589 $root = $this->_findRoot($page);
00590 foreach ($root as $chapter) {
00591 if ($chapter->hasPage($parent)) {
00592 $found = $parent;
00593 break;
00594 }
00595 }
00596 }
00597 }
00598
00599 return $found;
00600 }
00601
00602
00603
00615 protected function _findRoot(Zend_Navigation_Page $page)
00616 {
00617 if ($this->_root) {
00618 return $this->_root;
00619 }
00620
00621 $root = $page;
00622
00623 while ($parent = $page->getParent()) {
00624 $root = $parent;
00625 if ($parent instanceof Zend_Navigation_Page) {
00626 $page = $parent;
00627 } else {
00628 break;
00629 }
00630 }
00631
00632 return $root;
00633 }
00634
00643 protected function _convertToPages($mixed, $recursive = true)
00644 {
00645 if (is_object($mixed)) {
00646 if ($mixed instanceof Zend_Navigation_Page) {
00647
00648 return $mixed;
00649 } elseif ($mixed instanceof Zend_Navigation_Container) {
00650
00651 $pages = array();
00652 foreach ($mixed as $page) {
00653 $pages[] = $page;
00654 }
00655 return $pages;
00656 } elseif ($mixed instanceof Zend_Config) {
00657
00658 return $this->_convertToPages($mixed->toArray(), $recursive);
00659 }
00660 } elseif (is_string($mixed)) {
00661
00662 return Zend_Navigation_Page::factory(array(
00663 'type' => 'uri',
00664 'uri' => $mixed
00665 ));
00666 } elseif (is_array($mixed) && !empty($mixed)) {
00667 if ($recursive && is_numeric(key($mixed))) {
00668
00669 $pages = array();
00670 foreach ($mixed as $value) {
00671 if ($value = $this->_convertToPages($value, false)) {
00672 $pages[] = $value;
00673 }
00674 }
00675 return $pages;
00676 } else {
00677
00678 try {
00679 $page = Zend_Navigation_Page::factory($mixed);
00680 return $page;
00681 } catch (Exception $e) {
00682 }
00683 }
00684 }
00685
00686
00687 return null;
00688 }
00689
00690
00691
00707 public function renderLink(Zend_Navigation_Page $page, $attrib, $relation)
00708 {
00709 if (!in_array($attrib, array('rel', 'rev'))) {
00710 require_once 'Zend/View/Exception.php';
00711 throw new Zend_View_Exception(sprintf(
00712 'Invalid relation attribute "%s", must be "rel" or "rev"',
00713 $attrib));
00714 }
00715
00716 if (!$href = $page->getHref()) {
00717 return '';
00718 }
00719
00720
00721
00722 $attribs = array(
00723 $attrib => $relation,
00724 'href' => $href,
00725 'title' => $page->getLabel()
00726 );
00727
00728 return '<link' .
00729 $this->_htmlAttribs($attribs) .
00730 $this->getClosingBracket();
00731 }
00732
00733
00734
00746 public function render(Zend_Navigation_Container $container = null)
00747 {
00748 if (null === $container) {
00749 $container = $this->getContainer();
00750 }
00751
00752 if ($active = $this->findActive($container)) {
00753 $active = $active['page'];
00754 } else {
00755
00756 return '';
00757 }
00758
00759 $output = '';
00760 $indent = $this->getIndent();
00761 $this->_root = $container;
00762
00763 $result = $this->findAllRelations($active, $this->getRenderFlag());
00764 foreach ($result as $attrib => $types) {
00765 foreach ($types as $relation => $pages) {
00766 foreach ($pages as $page) {
00767 if ($r = $this->renderLink($page, $attrib, $relation)) {
00768 $output .= $indent . $r . self::EOL;
00769 }
00770 }
00771 }
00772 }
00773
00774 $this->_root = null;
00775
00776
00777 return strlen($output) ? rtrim($output, self::EOL) : '';
00778 }
00779 }