2
0
Просмотр исходного кода

ZF-7272: Allow adding an id attribute to ul elements when using Navigation menu view helper

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@24962 44c647ce-9c0f-0410-b52a-842ac1e357ba
adamlundrigan 13 лет назад
Родитель
Сommit
36eb7abc5e

+ 70 - 7
library/Zend/View/Helper/Navigation/HelperAbstract.php

@@ -72,6 +72,20 @@ abstract class Zend_View_Helper_Navigation_HelperAbstract
     protected $_indent = '';
 
     /**
+     * Prefix for IDs when they are normalized
+     *
+     * @var string|null
+     */
+    protected $_prefixForId = null;
+
+    /**
+     * Skip current prefix for IDs when they are normalized (flag)
+     *
+     * @var bool
+     */
+    protected $_skipPrefixForId = false;
+
+    /**
      * Translator
      *
      * @var Zend_Translate_Adapter
@@ -274,6 +288,50 @@ abstract class Zend_View_Helper_Navigation_HelperAbstract
     }
 
     /**
+     * Sets prefix for IDs when they are normalized
+     *
+     * @param   string $prefix                              Prefix for IDs
+     * @return  Zend_View_Helper_Navigation_HelperAbstract  fluent interface, returns self
+     */
+    public function setPrefixForId($prefix)
+    {
+        if (is_string($prefix)) {
+            $this->_prefixForId = trim($prefix);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns prefix for IDs when they are normalized
+     *
+     * @return string   Prefix for
+     */
+    public function getPrefixForId()
+    {
+        if (null === $this->_prefixForId) {
+            $prefix             = get_class($this);
+            $this->_prefixForId = strtolower(
+                    trim(substr($prefix, strrpos($prefix, '_')), '_')
+                ) . '-';
+        }
+
+        return $this->_prefixForId;
+    }
+
+    /**
+     * Skip the current prefix for IDs when they are normalized
+     *
+     * @param  bool $flag
+     * @return Zend_View_Helper_Navigation_HelperAbstract  fluent interface, returns self
+     */
+    public function skipPrefixForId($flag = true)
+    {
+        $this->_skipPrefixForId = (bool) $flag;
+        return $this;
+    }
+
+    /**
      * Sets translator to use in helper
      *
      * Implements {@link Zend_View_Helper_Navigation_Helper::setTranslator()}.
@@ -803,17 +861,22 @@ abstract class Zend_View_Helper_Navigation_HelperAbstract
     /**
      * Normalize an ID
      *
-     * Overrides {@link Zend_View_Helper_HtmlElement::_normalizeId()}.
+     * Extends {@link Zend_View_Helper_HtmlElement::_normalizeId()}.
      *
-     * @param  string $value
-     * @return string
+     * @param  string $value    ID
+     * @return string           Normalized ID
      */
     protected function _normalizeId($value)
-    {
-        $prefix = get_class($this);
-        $prefix = strtolower(trim(substr($prefix, strrpos($prefix, '_')), '_'));
+    {        
+        if (false === $this->_skipPrefixForId) {
+            $prefix = $this->getPrefixForId();
+
+            if (strlen($prefix)) {
+                return $prefix . $value;
+            }
+        }
 
-        return $prefix . '-' . $value;
+        return parent::_normalizeId($value);
     }
 
     // Static methods:

+ 98 - 16
library/Zend/View/Helper/Navigation/Menu.php

@@ -45,6 +45,13 @@ class Zend_View_Helper_Navigation_Menu
     protected $_ulClass = 'navigation';
 
     /**
+     * Unique identifier (id) for the ul element
+     *
+     * @var string
+     */
+    protected $_ulId = null;
+
+    /**
      * Whether only active branch should be rendered
      *
      * @var bool
@@ -116,6 +123,33 @@ class Zend_View_Helper_Navigation_Menu
     }
 
     /**
+     * Sets unique identifier (id) to use for the first 'ul' element when
+     * rendering
+     *
+     * @param  string|null  $ulId                Unique identifier (id) to set
+     * @return Zend_View_Helper_Navigation_Menu  fluent interface, returns self
+     */
+    public function setUlId($ulId)
+    {
+        if (is_string($ulId)) {
+            $this->_ulId = $ulId;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns unique identifier (id) to use for the first 'ul' element when
+     * rendering
+     *
+     * @return string|null  Unique identifier (id); Default is 'null'
+     */
+    public function getUlId()
+    {
+        return $this->_ulId;
+    }
+
+    /**
      * Sets a flag indicating whether only active branch should be rendered
      *
      * @param  bool $flag                        [optional] render only active
@@ -298,6 +332,12 @@ class Zend_View_Helper_Navigation_Menu
             $options['ulClass'] = $this->getUlClass();
         }
 
+        if (isset($options['ulId']) && $options['ulId'] !== null) {
+            $options['ulId'] = (string) $options['ulId'];
+        } else {
+            $options['ulId'] = $this->getUlId();
+        }
+
         if (array_key_exists('minDepth', $options)) {
             if (null !== $options['minDepth']) {
                 $options['minDepth'] = (int) $options['minDepth'];
@@ -310,6 +350,7 @@ class Zend_View_Helper_Navigation_Menu
             $options['minDepth'] = 0;
         }
 
+        // Maximum depth
         if (array_key_exists('maxDepth', $options)) {
             if (null !== $options['maxDepth']) {
                 $options['maxDepth'] = (int) $options['maxDepth'];
@@ -345,13 +386,16 @@ class Zend_View_Helper_Navigation_Menu
      * @param  string                    $indent     initial indentation
      * @param  int|null                  $minDepth   minimum depth
      * @param  int|null                  $maxDepth   maximum depth
+     * @param  string|null               $ulId       unique identifier (id) for
+     *                                               first UL
      * @return string                                rendered menu
      */
     protected function _renderDeepestMenu(Zend_Navigation_Container $container,
                                           $ulClass,
                                           $indent,
                                           $minDepth,
-                                          $maxDepth)
+                                          $maxDepth,
+                                          $ulId)
     {
         if (!$active = $this->findActive($container, $minDepth - 1, $maxDepth)) {
             return '';
@@ -370,8 +414,22 @@ class Zend_View_Helper_Navigation_Menu
             $active['page'] = $active['page']->getParent();
         }
 
-        $ulClass = $ulClass ? ' class="' . $ulClass . '"' : '';
-        $html = $indent . '<ul' . $ulClass . '>' . self::EOL;
+        $attribs = array(
+            'class' => $ulClass,
+            'id'    => $ulId,
+        );
+
+        // We don't need a prefix for the menu ID (backup)
+        $skipValue = $this->_skipPrefixForId;
+        $this->skipPrefixForId();
+
+        $html = $indent . '<ul'
+                        . $this->_htmlAttribs($attribs)
+                        . '>'
+                        . self::EOL;
+
+        // Reset prefix for IDs
+        $this->_skipPrefixForId = $skipValue;
 
         foreach ($active['page'] as $subPage) {
             if (!$this->accept($subPage)) {
@@ -397,7 +455,10 @@ class Zend_View_Helper_Navigation_Menu
      * @param  int|null                  $minDepth    minimum depth
      * @param  int|null                  $maxDepth    maximum depth
      * @param  bool                      $onlyActive  render only active branch?
-     * @param  bool                      $expandSibs  render siblings of active branch nodes?
+     * @param  bool                      $expandSibs  render siblings of active
+     *                                                branch nodes?
+     * @param  string|null               $ulId        unique identifier (id) for
+     *                                                first UL
      * @return string
      */
     protected function _renderMenu(Zend_Navigation_Container $container,
@@ -406,7 +467,8 @@ class Zend_View_Helper_Navigation_Menu
                                    $minDepth,
                                    $maxDepth,
                                    $onlyActive,
-                                   $expandSibs)
+                                   $expandSibs,
+                                   $ulId)
     {
         $html = '';
 
@@ -445,7 +507,7 @@ class Zend_View_Helper_Navigation_Menu
                         $accept = true;
                     }
                 }
-            	if (!$isActive && !$accept) {
+                if (!$isActive && !$accept) {
                     continue;
                 }
             } else if ($onlyActive && !$isActive) {
@@ -476,13 +538,27 @@ class Zend_View_Helper_Navigation_Menu
             $myIndent = $indent . str_repeat('        ', $depth);
 
             if ($depth > $prevDepth) {
+                $attribs = array();
+
                 // start new ul tag
-                if ($ulClass && $depth ==  0) {
-                    $ulClass = ' class="' . $ulClass . '"';
-                } else {
-                    $ulClass = '';
+                if (0 == $depth) {
+                    $attribs = array(
+                        'class' => $ulClass,
+                        'id'    => $ulId,
+                    );
                 }
-                $html .= $myIndent . '<ul' . $ulClass . '>' . self::EOL;
+
+                // We don't need a prefix for the menu ID (backup)
+                $skipValue = $this->_skipPrefixForId;
+                $this->skipPrefixForId();
+
+                $html .= $myIndent . '<ul'
+                                   . $this->_htmlAttribs($attribs)
+                                   . '>'
+                                   . self::EOL;
+
+                // Reset prefix for IDs
+                $this->_skipPrefixForId = $skipValue;
             } else if ($prevDepth > $depth) {
                 // close li/ul tags until we're at current depth
                 for ($i = $prevDepth; $i > $depth; $i--) {
@@ -551,7 +627,8 @@ class Zend_View_Helper_Navigation_Menu
                                               $options['ulClass'],
                                               $options['indent'],
                                               $options['minDepth'],
-                                              $options['maxDepth']);
+                                              $options['maxDepth'],
+                                              $options['ulId']);
         } else {
             $html = $this->_renderMenu($container,
                                        $options['ulClass'],
@@ -559,7 +636,8 @@ class Zend_View_Helper_Navigation_Menu
                                        $options['minDepth'],
                                        $options['maxDepth'],
                                        $options['onlyActiveBranch'],
-                                       $options['expandSiblingNodesOfActiveBranch']);
+                                       $options['expandSiblingNodesOfActiveBranch'],
+                                       $options['ulId']);
         }
 
         return $html;
@@ -584,7 +662,7 @@ class Zend_View_Helper_Navigation_Menu
      *                                               render. Default is to render
      *                                               the container registered in
      *                                               the helper.
-     * @param  string                    $ulClass    [optional] CSS class to
+     * @param  string|null               $ulClass    [optional] CSS class to
      *                                               use for UL element. Default
      *                                               is to use the value from
      *                                               {@link getUlClass()}.
@@ -593,11 +671,14 @@ class Zend_View_Helper_Navigation_Menu
      *                                               spaces. Default is to use
      *                                               the value retrieved from
      *                                               {@link getIndent()}.
+     * @param  string|null               $ulId       [optional] Unique identifier
+     *                                               (id) use for UL element
      * @return string                                rendered content
      */
     public function renderSubMenu(Zend_Navigation_Container $container = null,
                                   $ulClass = null,
-                                  $indent = null)
+                                  $indent = null,
+                                  $ulId   = null)
     {
         return $this->renderMenu($container, array(
             'indent'           => $indent,
@@ -605,7 +686,8 @@ class Zend_View_Helper_Navigation_Menu
             'minDepth'         => null,
             'maxDepth'         => null,
             'onlyActiveBranch' => true,
-            'renderParents'    => false
+            'renderParents'    => false,
+            'ulId'             => $ulId,
         ));
     }
 

+ 127 - 8
tests/Zend/View/Helper/Navigation/MenuTest.php

@@ -191,6 +191,83 @@ class Zend_View_Helper_Navigation_MenuTest
         $this->assertEquals($expected, $this->_helper->render($this->_nav2));
     }
 
+    /**
+     * @group ZF-10409
+     */
+    public function testSetPrefixForIdWithContent()
+    {
+        $this->_helper->setPrefixForId('test-');
+        $expected = $this->_getExpected('menu/normalize-id-prefix-with-content.html');
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testSetPrefixForIdWithoutContent()
+    {
+        $this->_helper->setPrefixForId('');
+        $expected = $this->_getExpected('menu/normalize-id-prefix-without-content.html');
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testSetPrefixForIdWithNull()
+    {
+        $this->_helper->setPrefixForId(null);
+        $expected = $this->_getExpected('menu/normalize-id-prefix-with-null.html');
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testGetPrefixForIdWithContent()
+    {
+        $this->_helper->setPrefixForId('test');
+        $this->assertEquals('test', $this->_helper->getPrefixForId());
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testGetPrefixForIdWithoutContent()
+    {
+        $this->_helper->setPrefixForId('');
+        $this->assertEquals('', $this->_helper->getPrefixForId());
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testGetPrefixForIdWithNull()
+    {
+        $this->_helper->setPrefixForId(null);
+        $this->assertEquals('menu-', $this->_helper->getPrefixForId());
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testSkipPrefixForIdTrue()
+    {
+        $this->_helper->skipPrefixForId(true);
+        $expected = $this->_getExpected('menu/normalize-id-prefix-without-content.html');
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
+
+    /**
+     * @group ZF-10409
+     */
+    public function testSkipPrefixForIdFalse()
+    {
+        $this->_helper->skipPrefixForId(false);
+        $expected = $this->_getExpected('menu/normalize-id-prefix-with-null.html');
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
+
     public function testTranslationUsingZendTranslate()
     {
         $translator = $this->_getTranslator();
@@ -268,14 +345,6 @@ class Zend_View_Helper_Navigation_MenuTest
         }
     }
 
-
-
-
-
-
-
-
-
     public function testSetMaxDepth()
     {
         $this->_helper->setMaxDepth(1);
@@ -585,4 +654,54 @@ class Zend_View_Helper_Navigation_MenuTest
 
         $this->assertEquals($expected, $this->_helper->render($this->_nav3));
     }
+
+    /**
+     * @group ZF-7212
+     */
+    public function testRenderingWithUlId()
+    {
+        $this->_helper->setUlId('foo');
+
+        $this->assertContains(
+            '<ul class="navigation" id="foo">',
+            $this->_helper->renderMenu()
+        );
+    }
+
+    /**
+     * @group ZF-7212
+     */
+    public function testRenderingWithUlIdPerOptions()
+    {
+        $this->assertContains(
+            '<ul class="navigation" id="foo">',
+            $this->_helper->renderMenu(null, array('ulId' => 'foo'))
+        );
+    }
+
+    /**
+     * @group ZF-7212
+     */
+    public function testRenderingOnlyActiveBranchWithUlId()
+    {
+        $this->_helper->setUlId('foo')
+                      ->setOnlyActiveBranch()
+                      ->setRenderParents();
+
+        $this->assertContains(
+            '<ul class="navigation" id="foo">',
+            $this->_helper->renderMenu()
+        );
+    }
+
+    /**
+     * @group ZF-7212
+     */
+    public function testRenderingSubMenuWithUlId()
+    {
+        $this->assertContains(
+            '<ul class="navigation" id="foo">',
+            $this->_helper->renderSubMenu(null, null, null, 'foo')
+        );
+    }
 }

+ 16 - 0
tests/Zend/View/Helper/Navigation/_files/expected/menu/normalize-id-prefix-with-content.html

@@ -0,0 +1,16 @@
+<ul class="navigation">
+    <li>
+        <a id="test-home" href="home">Home</a>
+    </li>
+    <li class="active">
+        <a href="contact">Contact</a>
+        <ul>
+            <li>
+                <a id="test-privacy" href="contact/privacy">Privacy</a>
+            </li>
+            <li>
+                <a id="test-imprint" href="contact/imprint">Imprint</a>
+            </li>
+        </ul>
+    </li>
+</ul>

+ 16 - 0
tests/Zend/View/Helper/Navigation/_files/expected/menu/normalize-id-prefix-with-null.html

@@ -0,0 +1,16 @@
+<ul class="navigation">
+    <li>
+        <a id="menu-home" href="home">Home</a>
+    </li>
+    <li class="active">
+        <a href="contact">Contact</a>
+        <ul>
+            <li>
+                <a id="menu-privacy" href="contact/privacy">Privacy</a>
+            </li>
+            <li>
+                <a id="menu-imprint" href="contact/imprint">Imprint</a>
+            </li>
+        </ul>
+    </li>
+</ul>

+ 16 - 0
tests/Zend/View/Helper/Navigation/_files/expected/menu/normalize-id-prefix-without-content.html

@@ -0,0 +1,16 @@
+<ul class="navigation">
+    <li>
+        <a id="home" href="home">Home</a>
+    </li>
+    <li class="active">
+        <a href="contact">Contact</a>
+        <ul>
+            <li>
+                <a id="privacy" href="contact/privacy">Privacy</a>
+            </li>
+            <li>
+                <a id="imprint" href="contact/imprint">Imprint</a>
+            </li>
+        </ul>
+    </li>
+</ul>