Skip to content

Commit

Permalink
[Locale] Improved error reporting and added stubs for intl_is_failure…
Browse files Browse the repository at this point in the history
…(), intl_get_error_code() and intl_get_error_message()
  • Loading branch information
webmozart committed May 18, 2011
1 parent c3e8569 commit 829aa4d
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 9 deletions.
45 changes: 45 additions & 0 deletions 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();
}
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -275,6 +276,8 @@ protected function calculateUnixTimestamp(\DateTime $dateTime, array $options)

// If month is false, return immediately (intl behavior)
if (false === $month) {
StubIntl::setErrorCode(StubIntl::U_PARSE_ERROR);

return false;
}

Expand Down
112 changes: 112 additions & 0 deletions 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',

This comment has been minimized.

Copy link
@pborreli

pborreli May 22, 2011

Contributor

this error message has changed on Nov, 11 2010: http://svn.php.net/viewvc/php/php-src/branches/PHP_5_3/ext/intl/dateformat/dateformat_format.c?r1=265868&r2=305580
So now assertion will fail on recent Intl.

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;
}
}
12 changes: 11 additions & 1 deletion src/Symfony/Component/Locale/Stub/StubIntlDateFormatter.php
Expand Up @@ -160,10 +160,18 @@ static public function create($locale, $datetype, $timetype, $timezone = null, $
*/
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));

Expand Down Expand Up @@ -311,6 +319,8 @@ public function parse($value, &$position = null)
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);
Expand Down
Expand Up @@ -14,6 +14,7 @@
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;

Expand Down Expand Up @@ -55,21 +56,27 @@ public function testConstructorDefaultTimeZoneIntl()
/**
* @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()
Expand Down Expand Up @@ -248,6 +255,10 @@ public function formatProvider()
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;
Expand Down Expand Up @@ -481,20 +492,26 @@ public function testLocaltime()
/**
* @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()
Expand All @@ -511,17 +528,17 @@ public function parseProvider()
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),
array('y-LLL-d', '1970-Jan-1', 0),
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),
Expand Down

0 comments on commit 829aa4d

Please sign in to comment.