Bläddra i källkod

Merge r25236 to 1.12 release branch

git-svn-id: http://framework.zend.com/svn/framework/standard/branches/release-1.12@25237 44c647ce-9c0f-0410-b52a-842ac1e357ba
frosch 13 år sedan
förälder
incheckning
c7cb4761c3
2 ändrade filer med 350 tillägg och 39 borttagningar
  1. 135 33
      library/Zend/Navigation/Container.php
  2. 215 6
      tests/Zend/Navigation/ContainerTest.php

+ 135 - 33
library/Zend/Navigation/Container.php

@@ -274,45 +274,138 @@ abstract class Zend_Navigation_Container implements RecursiveIterator, Countable
     }
 
     /**
-     * Returns a child page matching $property == $value, or null if not found
+     * Returns a child page matching $property == $value or 
+     * preg_match($value, $property), or null if not found
      *
-     * @param  string $property           name of property to match against
-     * @param  mixed  $value              value to match property against
+     * @param  string  $property          name of property to match against
+     * @param  mixed   $value             value to match property against
+     * @param  bool    $useRegex          [optional] if true PHP's preg_match
+     *                                    is used. Default is false.
      * @return Zend_Navigation_Page|null  matching page or null
      */
-    public function findOneBy($property, $value)
-    {
-        $iterator = new RecursiveIteratorIterator($this,
-                            RecursiveIteratorIterator::SELF_FIRST);
+    public function findOneBy($property, $value, $useRegex = false)
+    {        
+        $iterator = new RecursiveIteratorIterator(
+            $this,
+            RecursiveIteratorIterator::SELF_FIRST
+        );
 
         foreach ($iterator as $page) {
-            if ($page->get($property) == $value) {
-                return $page;
+            $pageProperty = $page->get($property);
+            
+            // Rel and rev
+            if (is_array($pageProperty)) {
+                foreach ($pageProperty as $item) {
+                    if (is_array($item)) {
+                        // Use regex?
+                        if (true === $useRegex) {
+                            foreach ($item as $item2) {
+                                if (0 !== preg_match($value, $item2)) {
+                                    return $page;
+                                }
+                            }
+                        } else {
+                            if (in_array($value, $item)) {
+                                return $page;
+                            }
+                        }
+                    } else {
+                        // Use regex?
+                        if (true === $useRegex) {
+                            if (0 !== preg_match($value, $item)) {
+                                return $page;
+                            }
+                        } else {
+                            if ($item == $value) {
+                                return $page;
+                            }
+                        }
+                    }
+                }
+                
+                continue;
+            }
+            
+            // Use regex?
+            if (true === $useRegex) {
+                if (preg_match($value, $pageProperty)) {
+                    return $page;
+                }
+            } else {
+                if ($pageProperty == $value) {
+                    return $page;
+                }
             }
         }
-
+        
         return null;
     }
 
     /**
-     * Returns all child pages matching $property == $value, or an empty array
-     * if no pages are found
+     * Returns all child pages matching $property == $value or
+     * preg_match($value, $property), 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
+     * @param  bool   $useRegex  [optional] if true PHP's preg_match is used.
+     *                           Default is false.
      * @return array             array containing only Zend_Navigation_Page
      *                           instances
      */
-    public function findAllBy($property, $value)
-    {
+    public function findAllBy($property, $value, $useRegex = false)
+    {        
         $found = array();
 
-        $iterator = new RecursiveIteratorIterator($this,
-                            RecursiveIteratorIterator::SELF_FIRST);
-
+        $iterator = new RecursiveIteratorIterator(
+            $this,
+            RecursiveIteratorIterator::SELF_FIRST
+        );
+        
         foreach ($iterator as $page) {
-            if ($page->get($property) == $value) {
-                $found[] = $page;
+            $pageProperty = $page->get($property);
+            
+            // Rel and rev
+            if (is_array($pageProperty)) {
+                foreach ($pageProperty as $item) {
+                    if (is_array($item)) {
+                        // Use regex?
+                        if (true === $useRegex) {
+                            foreach ($item as $item2) {
+                                if (0 !== preg_match($value, $item2)) {
+                                    $found[] = $page;
+                                }
+                            }
+                        } else {
+                            if (in_array($value, $item)) {
+                                $found[] = $page;
+                            }
+                        }
+                    } else {
+                        // Use regex?
+                        if (true === $useRegex) {
+                            if (0 !== preg_match($value, $item)) {
+                                $found[] = $page;
+                            }
+                        } else {
+                            if ($item == $value) {
+                                $found[] = $page;
+                            }
+                        }
+                    }
+                }
+                
+                continue;
+            }
+            
+            // Use regex?
+            if (true === $useRegex) {
+                if (0 !== preg_match($value, $pageProperty)) {
+                    $found[] = $page;
+                }
+            } else {
+                if ($pageProperty == $value) {
+                    $found[] = $page;
+                }
             }
         }
 
@@ -320,7 +413,8 @@ abstract class Zend_Navigation_Container implements RecursiveIterator, Countable
     }
 
     /**
-     * Returns page(s) matching $property == $value
+     * Returns page(s) matching $property == $value or
+     * preg_match($value, $property)
      *
      * @param  string $property  name of property to match against
      * @param  mixed  $value     value to match property against
@@ -330,14 +424,16 @@ abstract class Zend_Navigation_Container implements RecursiveIterator, Countable
      *                           matching pages are found. If false, null will
      *                           be returned if no matching page is found.
      *                           Default is false.
+     * @param  bool   $useRegex  [optional] if true PHP's preg_match is used.
+     *                           Default is false.
      * @return Zend_Navigation_Page|null  matching page or null
      */
-    public function findBy($property, $value, $all = false)
+    public function findBy($property, $value, $all = false, $useRegex = false)
     {
         if ($all) {
-            return $this->findAllBy($property, $value);
+            return $this->findAllBy($property, $value, $useRegex);
         } else {
-            return $this->findOneBy($property, $value);
+            return $this->findOneBy($property, $value, $useRegex);
         }
     }
 
@@ -346,27 +442,33 @@ abstract class Zend_Navigation_Container implements RecursiveIterator, Countable
      *
      * Examples of finder calls:
      * <code>
-     * // METHOD                    // SAME AS
-     * $nav->findByLabel('foo');    // $nav->findOneBy('label', 'foo');
-     * $nav->findOneByLabel('foo'); // $nav->findOneBy('label', 'foo');
-     * $nav->findAllByClass('foo'); // $nav->findAllBy('class', 'foo');
+     * // METHOD                         // SAME AS
+     * $nav->findByLabel('foo');         // $nav->findOneBy('label', 'foo');
+     * $nav->findByLabel('/foo/', true); // $nav->findBy('label', '/foo/', true);
+     * $nav->findOneByLabel('foo');      // $nav->findOneBy('label', 'foo');
+     * $nav->findAllByClass('foo');      // $nav->findAllBy('class', 'foo');
      * </code>
      *
-     * @param  string $method             method name
-     * @param  array  $arguments          method arguments
-     * @throws Zend_Navigation_Exception  if method does not exist
+     * @param  string $method                       method name
+     * @param  array  $arguments                    method arguments
+     * @return mixed  Zend_Navigation|array|null    matching page, array of pages
+     *                                              or null
+     * @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]);
+            return $this->{$match[1]}($match[2], $arguments[0], !empty($arguments[1]));
         }
 
         require_once 'Zend/Navigation/Exception.php';
-        throw new Zend_Navigation_Exception(sprintf(
+        throw new Zend_Navigation_Exception(
+            sprintf(
                 'Bad method call: Unknown method %s::%s',
                 get_class($this),
-                $method));
+                $method
+            )
+        );
     }
 
     /**

+ 215 - 6
tests/Zend/Navigation/ContainerTest.php

@@ -22,6 +22,8 @@
 
 require_once 'Zend/Navigation.php';
 require_once 'Zend/Config.php';
+require_once 'Zend/Controller/Front.php';
+require_once 'Zend/Controller/Request/Http.php';
 
 /**
  * Tests the class Zend_Navigation_Container
@@ -41,7 +43,9 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
      */
     protected function setUp()
     {
-
+        Zend_Controller_Front::getInstance()->setRequest(
+            new Zend_Controller_Request_Http()
+        );
     }
 
     /**
@@ -787,6 +791,75 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
         $found = $nav->findOneBy('id', 'non-existant');
         $this->assertNull($found);
     }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindOneByWithRegex()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        $found = $nav->findOneBy('id', '/page_2/', true);
+        $this->assertEquals('Page 2', $found->getLabel());
+        
+        $found = $nav->findOneBy('class', '/([o]{2})/', true);
+        $this->assertEquals('Page 1.3', $found->getLabel());
+    }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindOneWithinArrayProperties()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        $found = $nav->findOneBy('rel', 'Example.org');
+        $this->assertEquals('Page 1.2', $found->getLabel());
+        
+        $found = $nav->findOneBy('rel', '/Example/', true);
+        $this->assertEquals('Page 1.2', $found->getLabel());
+    }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindOneWithRegexWithinArrayProperties()
+    {
+        $nav = $this->_getFindByNavigation();
+
+        $found = $nav->findOneBy('rel', '#Example(.*)#', true);
+        $this->assertEquals('Page 1.2', $found->getLabel());
+        
+        $found = $nav->findOneBy('rel', '?Ex([a-z]*)?', true);
+        $this->assertEquals('Page 1.2', $found->getLabel());
+    }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindByWithRegex()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        // Find one
+        $found = $nav->findBy('id', '/page_2/', false, true);
+        $this->assertEquals('Page 2', $found->getLabel());
+        
+        $found = $nav->findBy('class', '/([fo]{2})/', false, true);
+        $this->assertEquals('Page 1.3', $found->getLabel());
+        
+        // Find all
+        $found = $nav->findBy('title', '/(The){1}.*(given){1}/', true, true);
+        
+        $expected = array('Page 1.1', 'Page 1.2', 'Page 1.3');
+        $actual   = array();
+
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+    }
 
     public function testFindAllByShouldReturnAllMatchingPages()
     {
@@ -814,6 +887,76 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
         $actual = array('type' => gettype($found), 'count' => count($found));
         $this->assertEquals($expected, $actual);
     }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindAllByWithRegex()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        $found = $nav->findAllBy('title', '/(The){1}.*(given){1}/', true);
+        
+        $expected = array('Page 1.1', 'Page 1.2', 'Page 1.3');
+        $actual = array();
+
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+    }
+        
+    /**
+     * @group ZF-9994
+     */
+    public function testFindAllWithinArrayProperties()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        // Strict is true
+        $found = $nav->findAllBy('rel', 'Example.org');
+        
+        $expected = array('Page 1.2', 'Page 1.3');
+        $actual   = array();
+
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+    }
+        
+    /**
+     * @group ZF-9994
+     */
+    public function testFindAllWithRegexWithinArrayProperties()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        // Test 1
+        $found = $nav->findAllBy('rel', '#Example(.*)#', true);
+        
+        $expected = array('Page 1.2', 'Page 1.3');
+        $actual   = array();
+
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+        
+        // Test 2
+        $found = $nav->findAllBy('rel', '?Ex([a-z]*)?', true);
+        
+        $actual = array();
+
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+    }
 
     public function testFindByShouldDefaultToFindOneBy()
     {
@@ -923,6 +1066,59 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
             $this->assertContains('Bad method call', $e->getMessage());
         }
     }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindByMagicMethodWithRegex()
+    {
+        $nav = $this->_getFindByNavigation();
+        
+        // Find one
+        $found = $nav->findOneByClass('/bar/', true);
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        // Find all
+        $found = $nav->findAllById('/page_2_/', true);
+        $this->assertContainsOnly('Zend_Navigation_Page', $found, false);
+
+        $expected = array('Page 2', 'Page 3');
+        $actual = array();
+        foreach ($found as $page) {
+            $actual[] = $page->getLabel();
+        }
+
+        $this->assertEquals($expected, $actual);
+    }
+    
+    /**
+     * @group ZF-9994
+     */
+    public function testFindByMagicMethodActivateRegex()
+    {
+        $nav = $this->_getFindByNavigation();
+                
+        $found = $nav->findOneByClass('/bar/', true);
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        $found = $nav->findOneByClass('/bar/', 1);
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        $found = $nav->findOneByClass('/bar/', 42);
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        $found = $nav->findOneByClass('/bar/', 'true');
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        $found = $nav->findOneByClass('/bar/', (object) null);
+        $this->assertSame('page-1.3', $found->getUri());
+        
+        $found = $nav->findOneByClass('/bar/', '0');
+        $this->assertNull($found);
+        
+        $found = $nav->findOneByClass('/bar/', array());
+        $this->assertNull($found);               
+    }
 
     protected function _getFindByNavigation()
     {
@@ -941,19 +1137,32 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
                         'label' => 'Page 1.1',
                         'uri'   => 'page-1.1',
                         'foo'   => 'bar',
-                        'title' => 'The given title'
+                        'title' => 'The given title',
                     ),
                     array(
                         'label' => 'Page 1.2',
                         'uri'   => 'page-1.2',
-                        'title' => 'The given title'
+                        'title' => 'The given title',
+                        'rel'   => array(
+                            'alternate' => array(
+                                'label' => 'Example.org',
+                                'uri'   => 'http://www.example.org/',
+                            ),
+                        ),
                     ),
                     array(
                         'type'   => 'uri',
                         'label'  => 'Page 1.3',
                         'uri'    => 'page-1.3',
                         'title'  => 'The given title',
-                        'action' => 'about'
+                        'action' => 'about',
+                        'class'  => 'foo bar',
+                        'rel'    => array(
+                            'alternate' => array(
+                                'label' => 'Example.org',
+                                'uri'   => 'http://www.example.org/',
+                            ),
+                        ),
                     )
                 )
             ),
@@ -963,14 +1172,14 @@ class Zend_Navigation_ContainerTest extends PHPUnit_Framework_TestCase
                 'module'     => 'page2',
                 'controller' => 'index',
                 'action'     => 'page1',
-                'page2'      => 'page2'
+                'page2'      => 'page2',
             ),
             array(
                 'id'         => 'page_2_and_3',
                 'label'      => 'Page 3',
                 'module'     => 'page3',
                 'controller' => 'index',
-                'action'     => 'about'
+                'action'     => 'about',
             )
         ));
     }