Procházet zdrojové kódy

[ZF-6533] Allowing escaping of @ and : characters in the beginning of a route segment

git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@15463 44c647ce-9c0f-0410-b52a-842ac1e357ba
dasprid před 16 roky
rodič
revize
585d3bc2fb

+ 17 - 0
documentation/manual/en/module_specs/Zend_Controller-Migration.xml

@@ -9,6 +9,23 @@
         migrate your scripts to use the new architecture.
     </para>
 
+    <sect2 id="zend.controller.migration.fromoneseventooneeight">
+        <title>Migrating from 1.7.x to 1.8.0 or newer</title>
+
+        <sect3 id="zend.controller.migration.fromoneseventooneeight.router">
+            <title>Standard Route Changes</title>
+
+            <para>
+                As translated segements were introduced into the new standard
+                route, the <code>@</code> character is no a special character
+                in the beginning of a route segment. To be able to use it in a
+                static segment, you must escape it by prefixing it with  second
+                <code>@</code> character. The same rule now applies for the
+                <code>:</code> character.
+            </para>
+        </sect3>
+    </sect2>
+
     <sect2 id="zend.controller.migration.fromonesixtooneseven">
         <title>Migrating from 1.6.x to 1.7.0 or newer</title>
 

+ 22 - 6
library/Zend/Controller/Router/Route.php

@@ -165,10 +165,10 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
 
         if ($route !== '') {
             foreach (explode($this->_urlDelimiter, $route) as $pos => $part) {
-                if (substr($part, 0, 1) == $this->_urlVariable) {
+                if (substr($part, 0, 1) == $this->_urlVariable && substr($part, 1, 1) != $this->_urlVariable) {
                     $name = substr($part, 1);
 
-                    if (substr($name, 0, 1) === '@') {
+                    if (substr($name, 0, 1) === '@' && substr($name, 1, 1) !== '@') {
                         $name                  = substr($name, 1);
                         $this->_translatable[] = $name;
                         $this->_isTranslated   = true;
@@ -177,7 +177,11 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
                     $this->_parts[$pos]     = (isset($reqs[$name]) ? $reqs[$name] : $this->_defaultRegex);
                     $this->_variables[$pos] = $name;
                 } else {
-                    if (substr($part, 0, 1) === '@') {
+                    if (substr($part, 0, 1) == $this->_urlVariable) {
+                        $part = substr($part, 1);
+                    }
+                    
+                    if (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@') {
                         $this->_isTranslated = true;
                     }
                     
@@ -244,15 +248,19 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
 
                 // Translate value if required
                 $part = $this->_parts[$pos];
-                if ($this->_isTranslated && (substr($part, 0, 1) === '@' && $name === null) || $name !== null && in_array($name, $this->_translatable)) {
+                if ($this->_isTranslated && (substr($part, 0, 1) === '@' && substr($part, 1, 1) !== '@' && $name === null) || $name !== null && in_array($name, $this->_translatable)) {
                     if (substr($part, 0, 1) === '@') {
                         $part = substr($part, 1);
                     }
-
+                    
                     if (($originalPathPart = array_search($pathPart, $translateMessages)) !== false) {
                         $pathPart = $originalPathPart;
                     }
                 }
+                
+                if (substr($part, 0, 2) === '@@') {
+                    $part = substr($part, 1);
+                }
 
                 // If it's a static part, match directly
                 if ($name === null && $part != $pathPart) {
@@ -348,8 +356,16 @@ class Zend_Controller_Router_Route extends Zend_Controller_Router_Route_Abstract
                 } 
             } elseif ($part != '*') {
                 if ($this->_isTranslated && substr($part, 0, 1) === '@') {
-                    $url[$key] = $translator->translate(substr($part, 1), $locale);
+                    if (substr($part, 1, 1) !== '@') {
+                        $url[$key] = $translator->translate(substr($part, 1), $locale);
+                    } else {
+                        $url[$key] = substr($part, 1);
+                    }
                 } else {
+                    if (substr($part, 0, 2) === '@@') {
+                        $part = substr($part, 1);
+                    }
+                    
                     $url[$key] = $part;
                 }
             } else {

+ 22 - 0
tests/Zend/Controller/Router/RouteTest.php

@@ -744,6 +744,28 @@ class Zend_Controller_Router_RouteTest extends PHPUnit_Framework_TestCase
             $this->assertEquals('Could not find a translator', $e->getMessage());
         }
     }
+    
+    public function testEscapedSpecialCharsWithoutTranslation()
+    {
+        $route = new Zend_Controller_Router_Route('::foo/@@bar/:foo');
+        
+        $path = $route->assemble(array('foo' => 'bar'));
+        $this->assertEquals($path, ':foo/@bar/bar');
+        
+        $values = $route->match(':foo/@bar/bar');
+        $this->assertEquals($values['foo'], 'bar');
+    }
+    
+    public function testEscapedSpecialCharsWithTranslation()
+    {
+        $route = new Zend_Controller_Router_Route('::foo/@@bar/:@myvar');
+        
+        $path = $route->assemble(array('myvar' => 'foo'));
+        $this->assertEquals($path, ':foo/@bar/en_foo');
+        
+        $values = $route->match(':foo/@bar/en_foo');
+        $this->assertEquals($values['myvar'], 'foo');
+    }
 }
 
 if (PHPUnit_MAIN_METHOD == 'Zend_Controller_Router_RouteTests::main') {