Ver Fonte

Fixing ZF-4249: Zend_XmlRpc_Value_DateTime returns false after 2038 year

  - Allowing Zend_Date and DateTime as values to create XML/RPC dateTime types from


git-svn-id: http://framework.zend.com/svn/framework/standard/trunk@19606 44c647ce-9c0f-0410-b52a-842ac1e357ba
lars há 16 anos atrás
pai
commit
39993fdba7

+ 8 - 0
documentation/manual/en/module_specs/Zend_XmlRpc_Client.xml

@@ -160,6 +160,14 @@ $result = $client->call('test.sayHello', array($arg1, $arg2));
                             <entry>object</entry>
                             <entry>array</entry>
                         </row>
+                        <row>
+                            <entry>Zend_Date</entry>
+                            <entry>dateTime.iso8601</entry>
+                        </row>
+                        <row>
+                            <entry>DateTime</entry>
+                            <entry>dateTime.iso8601</entry>
+                        </row>
                     </tbody>
                 </tgroup>
             </table>

+ 3 - 0
library/Zend/XmlRpc/Server.php

@@ -148,6 +148,7 @@ class Zend_XmlRpc_Server extends Zend_Server_Abstract
         'i4'               => 'i4',
         'int'              => 'int',
         'integer'          => 'int',
+        'i8'               => 'Zend_Crypt_Math_BigInteger',
         'double'           => 'double',
         'float'            => 'double',
         'real'             => 'double',
@@ -162,6 +163,8 @@ class Zend_XmlRpc_Server extends Zend_Server_Abstract
         'date'             => 'dateTime.iso8601',
         'time'             => 'dateTime.iso8601',
         'time'             => 'dateTime.iso8601',
+        'Zend_Date'        => 'dateTime.iso8601',
+        'DateTime'         => 'dateTime.iso8601',
         'array'            => 'array',
         'struct'           => 'struct',
         'null'             => 'nil',

+ 5 - 0
library/Zend/XmlRpc/Value.php

@@ -271,6 +271,11 @@ abstract class Zend_XmlRpc_Value
                     return new Zend_XmlRpc_Value_BigInteger($value);
                 }
 
+                if ($value instanceof Zend_Date or $value instanceof DateTime) {
+                    require_once 'Zend/XmlRpc/Value/DateTime.php';
+                    return new Zend_XmlRpc_Value_DateTime($value);
+                }
+
                 // Otherwise, we convert the object into a struct
                 $value = get_object_vars($value);
                 // Break intentionally omitted

+ 22 - 11
library/Zend/XmlRpc/Value/DateTime.php

@@ -37,6 +37,20 @@ require_once 'Zend/XmlRpc/Value/Scalar.php';
 class Zend_XmlRpc_Value_DateTime extends Zend_XmlRpc_Value_Scalar
 {
     /**
+     * PHP compatible format string for XML/RPC datetime values
+     *
+     * @var string
+     */
+    protected $_phpFormatString = 'Ymd\\TH:i:s';
+
+    /**
+     * ISO compatible format string for XML/RPC datetime values
+     *
+     * @var string
+     */
+    protected $_isoFormatString = 'YYYYMMddTHH:mm:ss';
+
+    /**
      * Set the value of a dateTime.iso8601 native type
      *
      * The value is in iso8601 format, minus any timezone information or dashes
@@ -48,23 +62,20 @@ class Zend_XmlRpc_Value_DateTime extends Zend_XmlRpc_Value_Scalar
     {
         $this->_type = self::XMLRPC_TYPE_DATETIME;
 
-        // If the value is not numeric, we try to convert it to a timestamp (using the strtotime function)
-        if (is_numeric($value)) {   // The value is numeric, we make sure it is an integer
-            $timestamp = (int)$value;
+        if ($value instanceof Zend_Date) {
+            $this->_value = $value->toString($this->_isoFormatString);
+        } elseif ($value instanceof DateTime) {
+            $this->_value = $value->format($this->_phpFormatString);
+        } elseif (is_numeric($value)) { // The value is numeric, we make sure it is an integer
+            $this->_value = date($this->_phpFormatString, (int)$value);
         } else {
             $timestamp = strtotime($value);
             if ($timestamp === false || $timestamp == -1) { // cannot convert the value to a timestamp
                 throw new Zend_XmlRpc_Value_Exception('Cannot convert given value \''. $value .'\' to a timestamp');
             }
-        }
 
-        $date = date('c', $timestamp); // Convert the timestamp to iso8601 format
-
-        // Strip out TZ information and dashes
-        $date = preg_replace('/(\+|-)\d{2}:\d{2}$/', '', $date);
-        $date = str_replace('-', '', $date);
-
-        $this->_value = $date;
+            $this->_value = date($this->_phpFormatString, $timestamp); // Convert the timestamp to iso8601 format
+        }
     }
 
     /**

+ 78 - 0
tests/Zend/XmlRpc/ValueTest.php

@@ -39,6 +39,7 @@ require_once 'Zend/Crypt/Math/BigInteger.php';
 require_once 'Zend/XmlRpc/Generator/DOMDocument.php';
 require_once 'Zend/XmlRpc/Generator/XMLWriter.php';
 require_once 'Zend/XmlRpc/TestProvider.php';
+require_once 'Zend/Date.php';
 
 /**
  * Test case for Zend_XmlRpc_Value
@@ -659,6 +660,83 @@ class Zend_XmlRpc_ValueTest extends PHPUnit_Framework_TestCase
         $this->assertEquals($this->wrapXml($xml), $val->saveXml());
     }
 
+    /**
+     * @dataProvider Zend_XmlRpc_TestProvider::provideGenerators
+     * @group ZF-4249
+     */
+    public function testMarshalDateTimeFromFromZendDate(Zend_XmlRpc_Generator_Abstract $generator)
+    {
+        Zend_XmlRpc_Value::setGenerator($generator);
+        $date = new Zend_Date(array('year' => 2039, 'month' => 4, 'day' => 18,
+                                    'hour' => 13, 'minute' => 14, 'second' => 15));
+        $dateString = '20390418T13:14:15';
+        $xml = "<value><dateTime.iso8601>$dateString</dateTime.iso8601></value>";
+
+        $val = Zend_XmlRpc_Value::getXmlRpcValue($date, Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME);
+        $this->assertXmlRpcType('dateTime', $val);
+        $this->assertEquals('dateTime.iso8601', $val->getType());
+        $this->assertSame($dateString, $val->getValue());
+        $this->assertEquals(trim($xml), trim($val->saveXml()));
+
+    }
+
+    /**
+     * @dataProvider Zend_XmlRpc_TestProvider::provideGenerators
+     * @group ZF-4249
+     */
+    public function testMarshalDateTimeFromZendDateAndAutodetectingType(Zend_XmlRpc_Generator_Abstract $generator)
+    {
+        Zend_XmlRpc_Value::setGenerator($generator);
+        $date = new Zend_Date(array('year' => 2039, 'month' => 4, 'day' => 18,
+                                    'hour' => 13, 'minute' => 14, 'second' => 15));
+        $dateString = '20390418T13:14:15';
+        $xml = "<value><dateTime.iso8601>$dateString</dateTime.iso8601></value>";
+
+        $val = Zend_XmlRpc_Value::getXmlRpcValue($date, Zend_XmlRpc_Value::AUTO_DETECT_TYPE);
+        $this->assertXmlRpcType('dateTime', $val);
+        $this->assertEquals('dateTime.iso8601', $val->getType());
+        $this->assertSame($dateString, $val->getValue());
+        $this->assertEquals(trim($xml), trim($val->saveXml()));
+    }
+
+    /**
+     * @dataProvider Zend_XmlRpc_TestProvider::provideGenerators
+     * @group ZF-4249
+     */
+    public function testMarshalDateTimeFromFromDateTime(Zend_XmlRpc_Generator_Abstract $generator)
+    {
+        Zend_XmlRpc_Value::setGenerator($generator);
+        $dateString = '20390418T13:14:15';
+        $date = new DateTime($dateString);
+        $dateString = '20390418T13:14:15';
+        $xml = "<value><dateTime.iso8601>$dateString</dateTime.iso8601></value>";
+
+        $val = Zend_XmlRpc_Value::getXmlRpcValue($date, Zend_XmlRpc_Value::XMLRPC_TYPE_DATETIME);
+        $this->assertXmlRpcType('dateTime', $val);
+        $this->assertEquals('dateTime.iso8601', $val->getType());
+        $this->assertSame($dateString, $val->getValue());
+        $this->assertEquals(trim($xml), trim($val->saveXml()));
+
+    }
+
+    /**
+     * @dataProvider Zend_XmlRpc_TestProvider::provideGenerators
+     * @group ZF-4249
+     */
+    public function testMarshalDateTimeFromDateTimeAndAutodetectingType(Zend_XmlRpc_Generator_Abstract $generator)
+    {
+        Zend_XmlRpc_Value::setGenerator($generator);
+        $dateString = '20390418T13:14:15';
+        $date = new DateTime($dateString);
+        $xml = "<value><dateTime.iso8601>$dateString</dateTime.iso8601></value>";
+
+        $val = Zend_XmlRpc_Value::getXmlRpcValue($date, Zend_XmlRpc_Value::AUTO_DETECT_TYPE);
+        $this->assertXmlRpcType('dateTime', $val);
+        $this->assertEquals('dateTime.iso8601', $val->getType());
+        $this->assertSame($dateString, $val->getValue());
+        $this->assertEquals(trim($xml), trim($val->saveXml()));
+    }
+
     // Base64
 
     public function testMarshalBase64FromString()