mirror of
https://github.com/twigphp/Twig.git
synced 2026-08-30 20:16:45 +00:00
Fix IntlExtension ignoring explicit formats when a date formatter prototype is set
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
# 3.29.0 (2026-XX-XX)
|
||||
|
||||
* Fix `IntlExtension` ignoring explicit date/time formats and the `format_date`/`format_time` filters when a date formatter prototype is configured
|
||||
* Add a `format_list` filter to `IntlExtension` to format a list of strings using PHP 8.5's `IntlListFormatter`
|
||||
* Fix array access with a `Stringable` key coercing the key to string for `ArrayAccess` objects that use object keys (such as `SplObjectStorage`)
|
||||
* Fix duplicated macro argument names triggering a PHP fatal error instead of a `SyntaxError`
|
||||
|
||||
@@ -405,7 +405,7 @@ final class IntlExtension extends AbstractExtension
|
||||
* @param \DateTimeInterface|string|null $date A date or null to use the current time
|
||||
* @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
|
||||
*/
|
||||
public function formatDateTime(Environment $env, $date, ?string $dateFormat = 'medium', ?string $timeFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
public function formatDateTime(Environment $env, $date, ?string $dateFormat = null, ?string $timeFormat = null, string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
{
|
||||
$date = $env->getExtension(CoreExtension::class)->convertDate($date, $timezone);
|
||||
|
||||
@@ -428,7 +428,7 @@ final class IntlExtension extends AbstractExtension
|
||||
* @param \DateTimeInterface|string|null $date A date or null to use the current time
|
||||
* @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
|
||||
*/
|
||||
public function formatDate(Environment $env, $date, ?string $dateFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
public function formatDate(Environment $env, $date, ?string $dateFormat = null, string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
{
|
||||
return $this->formatDateTime($env, $date, $dateFormat, 'none', $pattern, $timezone, $calendar, $locale);
|
||||
}
|
||||
@@ -437,7 +437,7 @@ final class IntlExtension extends AbstractExtension
|
||||
* @param \DateTimeInterface|string|null $date A date or null to use the current time
|
||||
* @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged
|
||||
*/
|
||||
public function formatTime(Environment $env, $date, ?string $timeFormat = 'medium', string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
public function formatTime(Environment $env, $date, ?string $timeFormat = null, string $pattern = '', $timezone = null, string $calendar = 'gregorian', ?string $locale = null): string
|
||||
{
|
||||
return $this->formatDateTime($env, $date, 'none', $timeFormat, $pattern, $timezone, $calendar, $locale);
|
||||
}
|
||||
@@ -475,17 +475,24 @@ final class IntlExtension extends AbstractExtension
|
||||
|
||||
$calendar = 'gregorian' === $calendar ? \IntlDateFormatter::GREGORIAN : \IntlDateFormatter::TRADITIONAL;
|
||||
|
||||
$dateFormatValue = $dateFormats[$dateFormat] ?? null;
|
||||
$timeFormatValue = self::TIME_FORMATS[$timeFormat] ?? null;
|
||||
$dateFormatValue = null === $dateFormat ? null : $dateFormats[$dateFormat];
|
||||
$timeFormatValue = null === $timeFormat ? null : self::TIME_FORMATS[$timeFormat];
|
||||
|
||||
if ($this->dateFormatterPrototype) {
|
||||
$dateFormatValue = $dateFormatValue ?: $this->dateFormatterPrototype->getDateType();
|
||||
$timeFormatValue = $timeFormatValue ?: $this->dateFormatterPrototype->getTimeType();
|
||||
$dateFormatValue ??= $this->dateFormatterPrototype->getDateType();
|
||||
$timeFormatValue ??= $this->dateFormatterPrototype->getTimeType();
|
||||
$timezone = $timezone ?: $this->dateFormatterPrototype->getTimeZone()->toDateTimeZone();
|
||||
$calendar = $calendar ?: $this->dateFormatterPrototype->getCalendar();
|
||||
$pattern = $pattern ?: $this->dateFormatterPrototype->getPattern();
|
||||
// fall back to the prototype's pattern only when nothing else was given, else it would override the explicit date/time formats;
|
||||
// a pattern describes a full datetime rendering, so it cannot be honored by format_date/format_time, which pass 'none' for the other part
|
||||
if ('' === $pattern && null === $dateFormat && null === $timeFormat) {
|
||||
$pattern = $this->dateFormatterPrototype->getPattern();
|
||||
}
|
||||
}
|
||||
|
||||
$dateFormatValue ??= \IntlDateFormatter::MEDIUM;
|
||||
$timeFormatValue ??= \IntlDateFormatter::MEDIUM;
|
||||
|
||||
$timezoneName = $timezone ? $timezone->getName() : '(none)';
|
||||
|
||||
$hash = $locale.'|'.$dateFormatValue.'|'.$timeFormatValue.'|'.$timezoneName.'|'.$calendar.'|'.$pattern;
|
||||
|
||||
@@ -97,6 +97,32 @@ class IntlExtensionTest extends TestCase
|
||||
);
|
||||
}
|
||||
|
||||
public function testFormatterProtoDoesNotOverrideExplicitFormats(): void
|
||||
{
|
||||
$dateFormatterProto = new \IntlDateFormatter('nl_NL', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::MEDIUM, new \DateTimeZone('Europe/Amsterdam'));
|
||||
$ext = new IntlExtension($dateFormatterProto);
|
||||
$env = new Environment(new ArrayLoader());
|
||||
$date = new \DateTime('2020-02-20T22:22:00+00:00', new \DateTimeZone('UTC'));
|
||||
|
||||
$this->assertSame('20 feb 2020', $ext->formatDate($env, $date));
|
||||
$this->assertSame('22:22:00', $ext->formatTime($env, $date));
|
||||
$this->assertSame('donderdag 20 februari 2020', $ext->formatDateTime($env, $date, 'full', 'none'));
|
||||
}
|
||||
|
||||
public function testFormatterProtoWithCustomPatternIsUsedByDefault(): void
|
||||
{
|
||||
$dateFormatterProto = new \IntlDateFormatter('nl_NL', \IntlDateFormatter::MEDIUM, \IntlDateFormatter::MEDIUM, new \DateTimeZone('Europe/Amsterdam'), \IntlDateFormatter::GREGORIAN, 'yyyy-MM-dd');
|
||||
$ext = new IntlExtension($dateFormatterProto);
|
||||
$env = new Environment(new ArrayLoader());
|
||||
$date = new \DateTime('2020-02-20T22:22:00+00:00', new \DateTimeZone('UTC'));
|
||||
|
||||
$this->assertSame('2020-02-20', $ext->formatDateTime($env, $date));
|
||||
$this->assertSame('20 feb 2020', $ext->formatDate($env, $date, 'medium'));
|
||||
// the prototype pattern describes a full datetime rendering, so format_date/format_time ignore it
|
||||
$this->assertSame('20 feb 2020', $ext->formatDate($env, $date));
|
||||
$this->assertSame('22:22:00', $ext->formatTime($env, $date));
|
||||
}
|
||||
|
||||
public function testDateFormatterCacheIsBounded(): void
|
||||
{
|
||||
$ext = new IntlExtension();
|
||||
|
||||
Reference in New Issue
Block a user