瀏覽代碼

ZF-11876: Add custom page property rendering to navigation menu view helper
Committed on behalf of Frank Brückner


git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@24879 44c647ce-9c0f-0410-b52a-842ac1e357ba

adamlundrigan 13 年之前
父節點
當前提交
65e785a78f

+ 139 - 17
library/Zend/Navigation/Page.php

@@ -163,6 +163,13 @@ abstract class Zend_Navigation_Page extends Zend_Navigation_Container
     protected $_properties = array();
 
     /**
+     * Custom HTML attributes
+     *
+     * @var array
+     */
+    protected $_customHtmlAttribs = array();
+
+    /**
      * The type of page to use when it wasn't set
      *
      * @var string
@@ -671,6 +678,119 @@ abstract class Zend_Navigation_Page extends Zend_Navigation_Container
     }
 
     /**
+     * Sets a single custom HTML attribute
+     *
+     * @param  string      $name            name of the HTML attribute
+     * @param  string|null $value           value for the HTML attribute
+     * @return Zend_Navigation_Page         fluent interface, returns self
+     * @throws Zend_Navigation_Exception    if name is not string or value is
+     *                                      not null or a string
+     */
+    public function setCustomHtmlAttrib($name, $value)
+    {
+        if (!is_string($name)) {
+            require_once 'Zend/Navigation/Exception.php';
+            throw new Zend_Navigation_Exception(
+                'Invalid argument: $name must be a string'
+            );
+        }
+
+        if (null !== $value && !is_string($value)) {
+            require_once 'Zend/Navigation/Exception.php';
+            throw new Zend_Navigation_Exception(
+                'Invalid argument: $value must be a string or null'
+            );
+        }
+
+        if (null === $value && isset($this->_customHtmlAttribs[$name])) {
+            unset($this->_customHtmlAttribs[$name]);
+        } else {
+            $this->_customHtmlAttribs[$name] = $value;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Returns a single custom HTML attributes by name
+     *
+     * @param  string $name                 name of the HTML attribute
+     * @return string|null                  value for the HTML attribute or null
+     * @throws Zend_Navigation_Exception    if name is not string
+     */
+    public function getCustomHtmlAttrib($name)
+    {
+        if (!is_string($name)) {
+            require_once 'Zend/Navigation/Exception.php';
+            throw new Zend_Navigation_Exception(
+                'Invalid argument: $name must be a string'
+            );
+        }
+
+        if (isset($this->_customHtmlAttribs[$name])) {
+            return $this->_customHtmlAttribs[$name];
+        }
+
+        return null;
+    }
+
+    /**
+     * Sets multiple custom HTML attributes at once
+     *
+     * @param array $attribs        an associative array of html attributes
+     * @return Zend_Navigation_Page fluent interface, returns self
+     */
+    public function setCustomHtmlAttribs(array $attribs)
+    {
+        foreach ($attribs as $key => $value) {
+            $this->setCustomHtmlAttrib($key, $value);
+        }
+        return $this;
+    }
+
+    /**
+     * Returns all custom HTML attributes as an array
+     *
+     * @return array    an array containing custom HTML attributes
+     */
+    public function getCustomHtmlAttribs()
+    {
+        return $this->_customHtmlAttribs;
+    }
+
+    /**
+     * Removes a custom HTML attribute from the page
+     *
+     * @param  string $name          name of the custom HTML attribute
+     * @return Zend_Navigation_Page  fluent interface, returns self
+     */
+    public function removeCustomHtmlAttrib($name)
+    {
+        if (!is_string($name)) {
+            require_once 'Zend/Navigation/Exception.php';
+            throw new Zend_Navigation_Exception(
+                'Invalid argument: $name must be a string'
+            );
+        }
+
+        if (isset($this->_customHtmlAttribs[$name])) {
+            unset($this->_customHtmlAttribs[$name]);
+        }
+    }
+
+    /**
+     * Clear all custom HTML attributes
+     *
+     * @return Zend_Navigation_Page fluent interface, returns self
+     */
+    public function clearCustomHtmlAttribs()
+    {
+        $this->_customHtmlAttribs = array();
+
+        return $this;
+    }
+
+    /**
      * Sets page order to use in parent container
      *
      * @param  int $order                 [optional] page order in container.
@@ -1187,23 +1307,25 @@ abstract class Zend_Navigation_Page extends Zend_Navigation_Container
         return array_merge(
             $this->getCustomProperties(),
             array(
-                'label'     => $this->getlabel(),
-                'fragment' => $this->getFragment(),
-                'id'        => $this->getId(),
-                'class'     => $this->getClass(),
-                'title'     => $this->getTitle(),
-                'target'    => $this->getTarget(),
-                'accesskey' => $this->getAccesskey(),
-                'rel'       => $this->getRel(),
-                'rev'       => $this->getRev(),
-                'order'     => $this->getOrder(),
-                'resource'  => $this->getResource(),
-                'privilege' => $this->getPrivilege(),
-                'active'    => $this->isActive(),
-                'visible'   => $this->isVisible(),
-                'type'      => get_class($this),
-                'pages'     => parent::toArray()
-            ));
+                'label'             => $this->getlabel(),
+                'fragment'          => $this->getFragment(),
+                'id'                => $this->getId(),
+                'class'             => $this->getClass(),
+                'title'             => $this->getTitle(),
+                'target'            => $this->getTarget(),
+                'accesskey'         => $this->getAccesskey(),
+                'rel'               => $this->getRel(),
+                'rev'               => $this->getRev(),
+                'customHtmlAttribs' => $this->getCustomHtmlAttribs(),
+                'order'             => $this->getOrder(),
+                'resource'          => $this->getResource(),
+                'privilege'         => $this->getPrivilege(),
+                'active'            => $this->isActive(),
+                'visible'           => $this->isVisible(),
+                'type'              => get_class($this),
+                'pages'             => parent::toArray()
+            )
+        );
     }
 
     // Internal methods:

+ 9 - 6
library/Zend/View/Helper/Navigation/HelperAbstract.php

@@ -669,12 +669,15 @@ abstract class Zend_View_Helper_Navigation_HelperAbstract
         }
 
         // get attribs for anchor element
-        $attribs = array(
-            'id'     => $page->getId(),
-            'title'  => $title,
-            'class'  => $page->getClass(),
-            'href'   => $page->getHref(),
-            'target' => $page->getTarget()
+        $attribs = array_merge(
+            array(
+                'id'     => $page->getId(),
+                'title'  => $title,
+                'class'  => $page->getClass(),
+                'href'   => $page->getHref(),
+                'target' => $page->getTarget()
+            ),
+            $page->getCustomHtmlAttribs()
         );
 
         return '<a' . $this->_htmlAttribs($attribs) . '>'

+ 6 - 3
library/Zend/View/Helper/Navigation/Menu.php

@@ -262,14 +262,17 @@ class Zend_View_Helper_Navigation_Menu
 
         // does page have a href?
         if ($href = $page->getHref()) {
-            $element = 'a';
-            $attribs['href'] = $href;
-            $attribs['target'] = $page->getTarget();
+            $element              = 'a';
+            $attribs['href']      = $href;
+            $attribs['target']    = $page->getTarget();
             $attribs['accesskey'] = $page->getAccessKey();
         } else {
             $element = 'span';
         }
 
+        // Add custom HTML attributes
+        $attribs = array_merge($attribs, $page->getCustomHtmlAttribs());
+
         return '<' . $element . $this->_htmlAttribs($attribs) . '>'
              . $this->view->escape($label)
              . '</' . $element . '>';

+ 100 - 1
tests/Zend/Navigation/PageTest.php

@@ -1156,6 +1156,100 @@ class Zend_Navigation_PageTest extends PHPUnit_Framework_TestCase
         $this->assertEquals($expected, $page->getCustomProperties());
     }
 
+    /**
+     * @group ZF-11876
+     */
+    public function testSetCustomHtmlAttrib()
+    {
+        $page = Zend_Navigation_Page::factory(
+            array(
+                 'type' => 'uri',
+            )
+        );
+
+        $page->setCustomHtmlAttrib('rel', 'nofollow');
+
+        $this->assertEquals('nofollow', $page->getCustomHtmlAttrib('rel'));
+    }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testSetCustomHtmlAttribWithNull()
+    {
+        $page = Zend_Navigation_Page::factory(
+            array(
+                 'type' => 'uri',
+            )
+        );
+
+        $page->setCustomHtmlAttrib('rel', 'nofollow');
+        $page->setCustomHtmlAttrib('rel', null);
+
+        $this->assertNull($page->getCustomHtmlAttrib('rel'));
+    }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testSetCustomHtmlAttribs()
+    {
+        $page = Zend_Navigation_Page::factory(
+            array(
+                 'type' => 'uri',
+            )
+        );
+
+        $attribs = array(
+             'rel'   => 'nofollow',
+             'style' => 'font-weight: bold;',
+        );
+
+        $page->setCustomHtmlAttribs($attribs);
+
+        $this->assertEquals($attribs, $page->getCustomHtmlAttribs());
+    }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testRemoveCustomHtmlAttrib()
+    {
+        $page = Zend_Navigation_Page::factory(
+            array(
+                 'type' => 'uri',
+            )
+        );
+
+        $page->setCustomHtmlAttrib('rel', 'nofollow');
+        $page->removeCustomHtmlAttrib('rel');
+
+        $this->assertEquals(array(), $page->getCustomHtmlAttribs());
+    }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testClearCustomHtmlAttribs()
+    {
+        $page = Zend_Navigation_Page::factory(
+            array(
+                 'type' => 'uri',
+            )
+        );
+
+        $page->setCustomHtmlAttribs(
+            array(
+                 'rel'   => 'nofollow',
+                 'style' => 'font-weight: bold;',
+            )
+        );
+
+        $page->clearCustomHtmlAttribs();
+
+        $this->assertEquals(array(), $page->getCustomHtmlAttribs());
+    }
+
     public function testToArrayMethod()
     {
         $options = array(
@@ -1188,7 +1282,12 @@ class Zend_Navigation_PageTest extends PHPUnit_Framework_TestCase
                     'label' => 'foo.baz',
                     'uri'   => 'http://www.example.com/foo.html'
                 )
-            )
+            ),
+
+            'customHtmlAttribs' => array(
+                'rel'   => 'nofollow',
+                'style' => 'font-weight: bold;',
+            ),
         );
 
         $page = Zend_Navigation_Page::factory($options);

+ 43 - 0
tests/Zend/View/Helper/Navigation/BreadcrumbsTest.php

@@ -251,4 +251,47 @@ class Zend_View_Helper_Navigation_BreadcrumbsTest
 
         $this->assertEquals($expected, $actual);
     }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testRenderingWithCustomHtmlAttribs()
+    {
+        $container = new Zend_Navigation(array(
+            array(
+                'label'             => 'Page 1',
+                'uri'               => 'p1',
+                'customHtmlAttribs' => array(
+                    'rel'   => 'nofollow',
+                    'style' => 'font-weight: bold;',
+                ),
+                'pages'             => array(
+                    array(
+                        'label'             => 'Page 2',
+                        'uri'               => 'p2',
+                        'customHtmlAttribs' => array(
+                            'rel'   => 'nofollow',
+                        ),
+                        'pages'             => array(
+                            array(
+                                'label'             => 'Page 3',
+                                'uri'               => 'p3',
+                                'active'            => true,
+                            ),
+                        ),
+                    ),
+                ),
+            ),
+        ));
+
+        $expected = '<a href="p1" rel="nofollow" style="font-weight: bold;">Page 1</a>'
+                  . ' &gt; '
+                  . '<a href="p2" rel="nofollow">Page 2</a>'
+                  . ' &gt; '
+                  . 'Page 3';
+
+        $actual = $this->_helper->setMinDepth(0)->render($container);
+
+        $this->assertEquals($expected, $actual);
+    }
 }

+ 19 - 0
tests/Zend/View/Helper/Navigation/MenuTest.php

@@ -566,4 +566,23 @@ class Zend_View_Helper_Navigation_MenuTest
  
         $this->assertEquals($expected, $actual);
     }
+
+    /**
+     * @group ZF-11876
+     */
+    public function testRenderingWithCustomHtmlAttribs()
+    {
+        $this->_nav3->findOneBy('id', 'home')->setCustomHtmlAttrib('rel', 'nofollow');
+        $this->_nav3->findOneBy('uri', 'contact')->setCustomHtmlAttribs(
+            array(
+                 'rel'   => 'nofollow',
+                 'style' => 'font-weight: bold;',
+            )
+        );
+        $this->_nav3->findOneBy('id', 'imprint')->setCustomHtmlAttrib('rel', 'nofollow');
+
+        $expected = $this->_getExpected('menu/customhtmlattribs.html');
+
+        $this->assertEquals($expected, $this->_helper->render($this->_nav3));
+    }
 }

+ 16 - 0
tests/Zend/View/Helper/Navigation/_files/expected/menu/customhtmlattribs.html

@@ -0,0 +1,16 @@
+<ul class="navigation">
+    <li>
+        <a id="menu-home" href="home" rel="nofollow">Home</a>
+    </li>
+    <li class="active">
+        <a href="contact" rel="nofollow" style="font-weight: bold;">Contact</a>
+        <ul>
+            <li>
+                <a id="menu-privacy" href="contact/privacy">Privacy</a>
+            </li>
+            <li>
+                <a id="menu-imprint" href="contact/imprint" rel="nofollow">Imprint</a>
+            </li>
+        </ul>
+    </li>
+</ul>