[Form] fix support for years outside of the 32b range on x86 arch

This commit is contained in:
Nicolas Grekas 2021-05-24 09:57:42 +02:00
parent 53d9b105a0
commit 2353f19cc2
6 changed files with 27 additions and 25 deletions

View File

@ -381,9 +381,7 @@ class DateType extends AbstractType
$result = []; $result = [];
foreach ($years as $year) { foreach ($years as $year) {
if (false !== $y = gmmktime(0, 0, 0, 6, 15, $year)) { $result[\PHP_INT_SIZE === 4 ? \DateTime::createFromFormat('Y e', $year.' UTC')->format('U') : gmmktime(0, 0, 0, 6, 15, $year)] = $year;
$result[$y] = $year;
}
} }
return $result; return $result;

View File

@ -927,19 +927,15 @@ class DateTypeTest extends BaseTypeTest
$this->assertSame([$error], iterator_to_array($form->getErrors())); $this->assertSame([$error], iterator_to_array($form->getErrors()));
} }
public function testYearsFor32BitsMachines() public function testYears()
{ {
if (4 !== \PHP_INT_SIZE) {
$this->markTestSkipped('PHP 32 bit is required.');
}
$view = $this->factory->create(static::TESTED_TYPE, null, [ $view = $this->factory->create(static::TESTED_TYPE, null, [
'years' => range(1900, 2040), 'years' => [1900, 2000, 2040],
]) ])
->createView(); ->createView();
$listChoices = []; $listChoices = [];
foreach (range(1902, 2037) as $y) { foreach ([1900, 2000, 2040] as $y) {
$listChoices[] = new ChoiceView($y, $y, $y); $listChoices[] = new ChoiceView($y, $y, $y);
} }

View File

@ -180,7 +180,7 @@ abstract class IntlDateFormatter
/** /**
* Format the date/time value (timestamp) as a string. * Format the date/time value (timestamp) as a string.
* *
* @param int|\DateTimeInterface $timestamp The timestamp to format * @param int|string|\DateTimeInterface $timestamp The timestamp to format
* *
* @return string|bool The formatted value or false if formatting failed * @return string|bool The formatted value or false if formatting failed
* *
@ -192,11 +192,15 @@ abstract class IntlDateFormatter
{ {
// intl allows timestamps to be passed as arrays - we don't // intl allows timestamps to be passed as arrays - we don't
if (\is_array($timestamp)) { if (\is_array($timestamp)) {
$message = 'Only integer Unix timestamps and DateTime objects are supported'; $message = 'Only Unix timestamps and DateTime objects are supported';
throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, $message); throw new MethodArgumentValueNotImplementedException(__METHOD__, 'timestamp', $timestamp, $message);
} }
if (\is_string($timestamp) && $dt = \DateTime::createFromFormat('U', $timestamp)) {
$timestamp = $dt;
}
// behave like the intl extension // behave like the intl extension
$argumentError = null; $argumentError = null;
if (!\is_int($timestamp) && !$timestamp instanceof \DateTimeInterface) { if (!\is_int($timestamp) && !$timestamp instanceof \DateTimeInterface) {
@ -212,7 +216,7 @@ abstract class IntlDateFormatter
} }
if ($timestamp instanceof \DateTimeInterface) { if ($timestamp instanceof \DateTimeInterface) {
$timestamp = $timestamp->getTimestamp(); $timestamp = $timestamp->format('U');
} }
$transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId()); $transformer = new FullTransformer($this->getPattern(), $this->getTimeZoneId());
@ -586,8 +590,7 @@ abstract class IntlDateFormatter
*/ */
protected function createDateTime($timestamp) protected function createDateTime($timestamp)
{ {
$dateTime = new \DateTime(); $dateTime = \DateTime::createFromFormat('U', $timestamp);
$dateTime->setTimestamp($timestamp);
$dateTime->setTimezone($this->dateTimeZone); $dateTime->setTimezone($this->dateTimeZone);
return $dateTime; return $dateTime;

View File

@ -72,7 +72,7 @@ class IntlDateFormatterTest extends AbstractIntlDateFormatterTest
} catch (\Exception $e) { } catch (\Exception $e) {
$this->assertInstanceOf(MethodArgumentValueNotImplementedException::class, $e); $this->assertInstanceOf(MethodArgumentValueNotImplementedException::class, $e);
$this->assertStringEndsWith('Only integer Unix timestamps and DateTime objects are supported. Please install the "intl" extension for full localization capabilities.', $e->getMessage()); $this->assertStringEndsWith('Only Unix timestamps and DateTime objects are supported. Please install the "intl" extension for full localization capabilities.', $e->getMessage());
} }
} }

View File

@ -674,17 +674,22 @@ class Inline
case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar):
return (float) str_replace('_', '', $scalar); return (float) str_replace('_', '', $scalar);
case Parser::preg_match(self::getTimestampRegex(), $scalar): case Parser::preg_match(self::getTimestampRegex(), $scalar):
// When no timezone is provided in the parsed date, YAML spec says we must assume UTC.
$time = new \DateTime($scalar, new \DateTimeZone('UTC'));
if (Yaml::PARSE_DATETIME & $flags) { if (Yaml::PARSE_DATETIME & $flags) {
// When no timezone is provided in the parsed date, YAML spec says we must assume UTC. return $time;
return new \DateTime($scalar, new \DateTimeZone('UTC'));
} }
$timeZone = date_default_timezone_get(); try {
date_default_timezone_set('UTC'); if (false !== $scalar = $time->getTimestamp()) {
$time = strtotime($scalar); return $scalar;
date_default_timezone_set($timeZone); }
} catch (\ValueError $e) {
// no-op
}
return $time; return $time->format('U');
} }
} }

View File

@ -323,7 +323,7 @@ class InlineTest extends TestCase
['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)], ['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)],
['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)], ['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)],
['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)], ['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)],
['1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)], ['1730-10-30T02:59:43Z', \PHP_INT_SIZE === 4 ? '-7547547617' : gmmktime(2, 59, 43, 10, 30, 1730)],
['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''], ['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''],
["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''], ["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''],
@ -394,7 +394,7 @@ class InlineTest extends TestCase
['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)], ['2007-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 2007)],
['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)], ['2007-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 2007)],
['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)], ['1960-10-30 02:59:43 Z', gmmktime(2, 59, 43, 10, 30, 1960)],
['1730-10-30T02:59:43Z', gmmktime(2, 59, 43, 10, 30, 1730)], ['1730-10-30T02:59:43Z', \PHP_INT_SIZE === 4 ? '-7547547617' : gmmktime(2, 59, 43, 10, 30, 1730)],
['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''], ['"a \\"string\\" with \'quoted strings inside\'"', 'a "string" with \'quoted strings inside\''],
["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''], ["'a \"string\" with ''quoted strings inside'''", 'a "string" with \'quoted strings inside\''],