Преглед изворни кода

[Locale] Improved error reporting and added stubs for intl_is_failure(), intl_get_error_code() and intl_get_error_message()

Bernhard Schussek пре 14 година
родитељ
комит
829aa4dc0b

+ 45 - 0
src/Symfony/Component/Locale/Resources/stubs/functions.php

@@ -0,0 +1,45 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+/**
+ * Stub implementation for the intl_is_failure function of the intl extension
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ * @param  integer $errorCode  The error code returned by intl_get_error_code()
+ * @return Boolean Whether the error code indicates an error
+ * @see    Symfony\Component\Locale\Stub\StubIntl::isFailure
+ */
+function intl_is_failure($errorCode) {
+    return \Symfony\Component\Locale\Stub\StubIntl::isFailure($errorCode);
+}
+
+/**
+ * Stub implementation for the intl_get_error_code function of the intl extension
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ * @return Boolean The error code of the last intl function call or
+ *                 StubIntl::U_ZERO_ERROR if no error occurred
+ * @see    Symfony\Component\Locale\Stub\StubIntl::getErrorCode
+ */
+function intl_get_error_code() {
+    return \Symfony\Component\Locale\Stub\StubIntl::getErrorCode();
+}
+/**
+ * Stub implementation for the intl_get_error_code function of the intl extension
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ * @return Boolean The error message of the last intl function call or
+ *                 "U_ZERO_ERROR" if no error occurred
+ * @see    Symfony\Component\Locale\Stub\StubIntl::getErrorMessage
+ */
+function intl_get_error_message() {
+    return \Symfony\Component\Locale\Stub\StubIntl::getErrorMessage();
+}

+ 3 - 0
src/Symfony/Component/Locale/Stub/DateFormat/FullTransformer.php

@@ -12,6 +12,7 @@
 namespace Symfony\Component\Locale\Stub\DateFormat;
 
 use Symfony\Component\Locale\Exception\NotImplementedException;
+use Symfony\Component\Locale\Stub\StubIntl;
 use Symfony\Component\Locale\Stub\DateFormat\MonthTransformer;
 
 /**
@@ -275,6 +276,8 @@ class FullTransformer
 
         // If month is false, return immediately (intl behavior)
         if (false === $month) {
+            StubIntl::setErrorCode(StubIntl::U_PARSE_ERROR);
+
             return false;
         }
 

+ 112 - 0
src/Symfony/Component/Locale/Stub/StubIntl.php

@@ -0,0 +1,112 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (c) Fabien Potencier <fabien@symfony.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Locale\Stub;
+
+/**
+ * Provides fake static versions of the global functions in the intl extension
+ *
+ * @author Bernhard Schussek <bernhard.schussek@symfony.com>
+ */
+abstract class StubIntl
+{
+    /**
+     * Indicates that no error occurred
+     * @var integer
+     */
+    const U_ZERO_ERROR = 0;
+
+    /**
+     * Indicates that an invalid argument was passed
+     * @var integer
+     */
+    const U_ILLEGAL_ARGUMENT_ERROR = 1;
+
+    /**
+     * Indicates that the parse() operation failed
+     * @var integer
+     */
+    const U_PARSE_ERROR = 9;
+
+    /**
+     * All known error codes
+     * @var array
+     */
+    private static $errorCodes = array(
+        self::U_ZERO_ERROR,
+        self::U_ILLEGAL_ARGUMENT_ERROR,
+        self::U_PARSE_ERROR,
+    );
+
+    /**
+     * The error messages of all known error codes
+     * @var array
+     */
+    private static $errorMessages = array(
+        self::U_ZERO_ERROR => 'U_ZERO_ERROR',
+        self::U_ILLEGAL_ARGUMENT_ERROR => 'datefmt_format: takes either an array  or an integer timestamp value : U_ILLEGAL_ARGUMENT_ERROR',
+        self::U_PARSE_ERROR => 'Date parsing failed: U_PARSE_ERROR',
+    );
+
+    /**
+     * The error code of the last operation
+     * @var integer
+     */
+    private static $errorCode = self::U_ZERO_ERROR;
+
+    /**
+     * Returns whether the error code indicates a failure
+     *
+     * @param  integer $errorCode The error code returned by StubIntl::getErrorCode()
+     * @return Boolean
+     */
+    public static function isFailure($errorCode) {
+        return in_array($errorCode, static::$errorCodes, true)
+            && $errorCode !== self::U_ZERO_ERROR;
+    }
+
+    /**
+     * Returns the error code of the last operation
+     *
+     * Returns StubIntl::U_ZERO_ERROR if no error occurred.
+     *
+     * @return integer
+     */
+    public static function getErrorCode() {
+        return static::$errorCode;
+    }
+
+    /**
+     * Returns the error message of the last operation
+     *
+     * Returns "U_ZERO_ERROR" if no error occurred.
+     *
+     * @return string
+     */
+    public static function getErrorMessage() {
+        return static::$errorMessages[static::$errorCode];
+    }
+
+    /**
+     * Sets the current error code
+     *
+     * @param  integer $code  One of the error constants in this class
+     * @throws \InvalidArgumentException  If the code is not one of the error
+     *                                    constants in this class
+     */
+    public static function setErrorCode($code) {
+        if (!isset(static::$errorMessages[$code])) {
+            throw new \InvalidArgumentException(sprintf('No such error code: "%s"', $code));
+        }
+
+        static::$errorCode = $code;
+    }
+}

+ 11 - 1
src/Symfony/Component/Locale/Stub/StubIntlDateFormatter.php

@@ -160,10 +160,18 @@ class StubIntlDateFormatter
      */
     public function format($timestamp)
     {
-        if (!is_int($timestamp)) {
+        // intl allows timestamps to be passed as arrays - we don't
+        if (is_array($timestamp)) {
             throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, 'Only integer unix timestamps are supported');
         }
 
+        if (!is_int($timestamp)) {
+            // behave like the intl extension
+            StubIntl::setErrorCode(StubIntl::U_ILLEGAL_ARGUMENT_ERROR);
+
+            return false;
+        }
+
         $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
         $formatted = $transformer->format($this->createDateTime($timestamp));
 
@@ -311,6 +319,8 @@ class StubIntlDateFormatter
             throw new MethodArgumentNotImplementedException(__METHOD__, 'position');
         }
 
+        StubIntl::setErrorCode(StubIntl::U_ZERO_ERROR);
+
         $dateTime = $this->createDateTime(0);
         $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
         return $transformer->parse($dateTime, $value);

+ 25 - 8
tests/Symfony/Tests/Component/Locale/Stub/StubIntlDateFormatterTest.php

@@ -14,6 +14,7 @@ namespace Symfony\Tests\Component\Locale\Stub;
 require_once __DIR__.'/../TestCase.php';
 
 use Symfony\Component\Locale\Locale;
+use Symfony\Component\Locale\Stub\StubIntl;
 use Symfony\Component\Locale\Stub\StubIntlDateFormatter;
 use Symfony\Tests\Component\Locale\TestCase as LocaleTestCase;
 
@@ -55,21 +56,27 @@ class StubIntlDateFormatterTest extends LocaleTestCase
     /**
      * @dataProvider formatProvider
      */
-    public function testFormatStub($pattern, $timestamp, $expected)
+    public function testFormatStub($pattern, $timestamp, $expected, $errorCode = 0, $errorMessage = 'U_ZERO_ERROR')
     {
         $formatter = $this->createStubFormatter($pattern);
         $this->assertSame($expected, $formatter->format($timestamp));
+        $this->assertSame($errorMessage, StubIntl::getErrorMessage());
+        $this->assertSame($errorCode, StubIntl::getErrorCode());
+        $this->assertSame($errorCode != 0, StubIntl::isFailure(StubIntl::getErrorCode()));
     }
 
     /**
     * @dataProvider formatProvider
     */
-    public function testFormatIntl($pattern, $timestamp, $expected)
+    public function testFormatIntl($pattern, $timestamp, $expected, $errorCode = 0, $errorMessage = 'U_ZERO_ERROR')
     {
         $this->skipIfIntlExtensionIsNotLoaded();
         $this->skipIfICUVersionIsTooOld();
         $formatter = $this->createIntlFormatter($pattern);
         $this->assertSame($expected, $formatter->format($timestamp));
+        $this->assertSame($errorMessage, intl_get_error_message());
+        $this->assertSame($errorCode, intl_get_error_code());
+        $this->assertSame($errorCode != 0, intl_is_failure(intl_get_error_code()));
     }
 
     public function formatProvider()
@@ -248,6 +255,10 @@ class StubIntlDateFormatterTest extends LocaleTestCase
             array('zzz', 0, 'GMT+00:00'),
             array('zzzz', 0, 'GMT+00:00'),
             array('zzzzz', 0, 'GMT+00:00'),
+
+            /* errors */
+            array('y-M-d', '0', false, 1, 'datefmt_format: takes either an array  or an integer timestamp value : U_ILLEGAL_ARGUMENT_ERROR'),
+            array('y-M-d', 'foobar', false, 1, 'datefmt_format: takes either an array  or an integer timestamp value : U_ILLEGAL_ARGUMENT_ERROR'),
         );
 
         return $formatData;
@@ -481,20 +492,26 @@ class StubIntlDateFormatterTest extends LocaleTestCase
     /**
      * @dataProvider parseProvider
      */
-    public function testParseIntl($pattern, $value, $expected)
+    public function testParseIntl($pattern, $value, $expected, $errorCode = 0, $errorMessage = 'U_ZERO_ERROR')
     {
         $this->skipIfIntlExtensionIsNotLoaded();
         $formatter = $this->createIntlFormatter($pattern);
         $this->assertSame($expected, $formatter->parse($value));
+        $this->assertSame($errorMessage, intl_get_error_message());
+        $this->assertSame($errorCode, intl_get_error_code());
+        $this->assertSame($errorCode != 0, intl_is_failure(intl_get_error_code()));
     }
 
     /**
      * @dataProvider parseProvider
      */
-    public function testParseStub($pattern, $value, $expected)
+    public function testParseStub($pattern, $value, $expected, $errorCode = 0, $errorMessage = 'U_ZERO_ERROR')
     {
         $formatter = $this->createStubFormatter($pattern);
         $this->assertSame($expected, $formatter->parse($value));
+        $this->assertSame($errorMessage, StubIntl::getErrorMessage());
+        $this->assertSame($errorCode, StubIntl::getErrorCode());
+        $this->assertSame($errorCode != 0, StubIntl::isFailure(StubIntl::getErrorCode()));
     }
 
     public function parseProvider()
@@ -511,8 +528,8 @@ class StubIntlDateFormatterTest extends LocaleTestCase
             array('y-MMMM-d', '1970-January-1', 0),
 
             // 1 char month
-            array('y-MMMMM-d', '1970-J-1', false),
-            array('y-MMMMM-d', '1970-S-1', false),
+            array('y-MMMMM-d', '1970-J-1', false, 9, 'Date parsing failed: U_PARSE_ERROR'),
+            array('y-MMMMM-d', '1970-S-1', false, 9, 'Date parsing failed: U_PARSE_ERROR'),
 
             // standalone months
             array('y-L-d', '1970-1-1', 0),
@@ -520,8 +537,8 @@ class StubIntlDateFormatterTest extends LocaleTestCase
             array('y-LLLL-d', '1970-January-1', 0),
 
             // standalone 1 char month
-            array('y-LLLLL-d', '1970-J-1', false),
-            array('y-LLLLL-d', '1970-S-1', false),
+            array('y-LLLLL-d', '1970-J-1', false, 9, 'Date parsing failed: U_PARSE_ERROR'),
+            array('y-LLLLL-d', '1970-S-1', false, 9, 'Date parsing failed: U_PARSE_ERROR'),
 
             // days
             array('y-M-d', '1970-1-1', 0),