From 143da6feb11a31565d4d7863908c84521e239c68 Mon Sep 17 00:00:00 2001 From: Tim Kelty Date: Sat, 25 May 2024 00:01:49 -0400 Subject: [PATCH] Share relative date parsing --- src/helpers/DateTimeHelper.php | 51 +++++++++++++++++++ src/web/twig/nodes/CacheNode.php | 15 ++---- src/web/twig/nodes/ExpiresNode.php | 21 +------- .../twig/tokenparsers/CacheTokenParser.php | 27 +--------- .../twig/tokenparsers/ExpiresTokenParser.php | 27 +--------- 5 files changed, 60 insertions(+), 81 deletions(-) diff --git a/src/helpers/DateTimeHelper.php b/src/helpers/DateTimeHelper.php index 14e1f2d026d..e36a38d1af5 100644 --- a/src/helpers/DateTimeHelper.php +++ b/src/helpers/DateTimeHelper.php @@ -56,6 +56,31 @@ class DateTimeHelper */ public const SECONDS_YEAR = 31556874; + public const DURATION_UNITS = [ + 'sec', + 'secs', + 'second', + 'seconds', + 'min', + 'mins', + 'minute', + 'minutes', + 'hour', + 'hours', + 'day', + 'days', + 'fortnight', + 'fortnights', + 'forthnight', + 'forthnights', + 'month', + 'months', + 'year', + 'years', + 'week', + 'weeks', + ]; + /** * @var DateTime[] * @see pause() @@ -809,6 +834,32 @@ public static function humanDurationFromInterval(DateInterval $dateInterval, boo return static::humanDuration($dateInterval, $showSeconds); } + /** + * Converts a human-friendly duration (number and unit) to seconds. + * + * @param int $number + * @param string $unit + * @return int + * @since 4.10.0 + */ + public static function humanDurationToSeconds(int $number, string $unit): int + { + // So silly that PHP doesn't support "+1 week" http://www.php.net/manual/en/datetime.formats.relative.php + if ($unit === 'week') { + if ($number == 1) { + $number = 7; + $unit = 'days'; + } else { + $unit = 'weeks'; + } + } + + $now = new DateTimeImmutable(); + $then = $now->modify("+$number $unit"); + + return $then->getTimestamp() - $now->getTimestamp(); + } + /** * Normalizes and returns a date string along with the format it was set in. * diff --git a/src/web/twig/nodes/CacheNode.php b/src/web/twig/nodes/CacheNode.php index 8b49beb55f4..98adde3d9dd 100644 --- a/src/web/twig/nodes/CacheNode.php +++ b/src/web/twig/nodes/CacheNode.php @@ -8,6 +8,7 @@ namespace craft\web\twig\nodes; use Craft; +use craft\helpers\DateTimeHelper; use craft\helpers\StringHelper; use Twig\Compiler; use Twig\Node\Node; @@ -95,18 +96,8 @@ public function compile(Compiler $compiler): void ->write("\$cacheService->endTemplateCache(\$cacheKey$n, $global, "); if ($durationNum) { - // So silly that PHP doesn't support "+1 week" http://www.php.net/manual/en/datetime.formats.relative.php - - if ($durationUnit === 'week') { - if ($durationNum == 1) { - $durationNum = 7; - $durationUnit = 'days'; - } else { - $durationUnit = 'weeks'; - } - } - - $compiler->raw("'+$durationNum $durationUnit'"); + $durationSeconds = DateTimeHelper::humanDurationToSeconds($durationNum, $durationUnit); + $compiler->raw("'+$durationSeconds seconds'"); } else { $compiler->raw('null'); } diff --git a/src/web/twig/nodes/ExpiresNode.php b/src/web/twig/nodes/ExpiresNode.php index 4b50312b1b8..b78af55dc03 100644 --- a/src/web/twig/nodes/ExpiresNode.php +++ b/src/web/twig/nodes/ExpiresNode.php @@ -7,7 +7,7 @@ namespace craft\web\twig\nodes; -use DateTimeImmutable; +use craft\helpers\DateTimeHelper; use Twig\Compiler; use Twig\Node\Node; @@ -26,7 +26,7 @@ public function compile(Compiler $compiler): void { $durationNum = $this->getAttribute('durationNum'); - $duration = $durationNum === null ? null : self::durationInSeconds( + $duration = $durationNum === null ? null : DateTimeHelper::humanDurationToSeconds( $durationNum, $this->getAttribute('durationUnit'), ); @@ -37,21 +37,4 @@ public function compile(Compiler $compiler): void $compiler->write("$line\n"); } - - private static function durationInSeconds($number, $unit): int - { - if ($unit === 'week') { - if ($number == 1) { - $number = 7; - $unit = 'days'; - } else { - $unit = 'weeks'; - } - } - - $now = new DateTimeImmutable(); - $then = $now->modify("+$number $unit"); - - return $then->getTimestamp() - $now->getTimestamp(); - } } diff --git a/src/web/twig/tokenparsers/CacheTokenParser.php b/src/web/twig/tokenparsers/CacheTokenParser.php index 4147aaa119c..bc56be109f5 100644 --- a/src/web/twig/tokenparsers/CacheTokenParser.php +++ b/src/web/twig/tokenparsers/CacheTokenParser.php @@ -7,6 +7,7 @@ namespace craft\web\twig\tokenparsers; +use craft\helpers\DateTimeHelper; use craft\web\twig\nodes\CacheNode; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; @@ -58,31 +59,7 @@ public function parse(Token $token): CacheNode if ($stream->test(Token::NAME_TYPE, 'for')) { $stream->next(); $attributes['durationNum'] = $stream->expect(Token::NUMBER_TYPE)->getValue(); - $attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, - [ - 'sec', - 'secs', - 'second', - 'seconds', - 'min', - 'mins', - 'minute', - 'minutes', - 'hour', - 'hours', - 'day', - 'days', - 'fortnight', - 'fortnights', - 'forthnight', - 'forthnights', - 'month', - 'months', - 'year', - 'years', - 'week', - 'weeks', - ])->getValue(); + $attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, DateTimeHelper::DURATION_UNITS)->getValue(); } elseif ($stream->test(Token::NAME_TYPE, 'until')) { $stream->next(); $nodes['expiration'] = $parser->getExpressionParser()->parseExpression(); diff --git a/src/web/twig/tokenparsers/ExpiresTokenParser.php b/src/web/twig/tokenparsers/ExpiresTokenParser.php index 5af40f5e19e..142b65f5885 100644 --- a/src/web/twig/tokenparsers/ExpiresTokenParser.php +++ b/src/web/twig/tokenparsers/ExpiresTokenParser.php @@ -7,6 +7,7 @@ namespace craft\web\twig\tokenparsers; +use craft\helpers\DateTimeHelper; use craft\web\twig\nodes\ExpiresNode; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; @@ -41,31 +42,7 @@ public function parse(Token $token): ExpiresNode } elseif ($stream->test(Token::NAME_TYPE, 'for')) { $stream->next(); $attributes['durationNum'] = $stream->expect(Token::NUMBER_TYPE)->getValue(); - $attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, - [ - 'sec', - 'secs', - 'second', - 'seconds', - 'min', - 'mins', - 'minute', - 'minutes', - 'hour', - 'hours', - 'day', - 'days', - 'fortnight', - 'fortnights', - 'forthnight', - 'forthnights', - 'month', - 'months', - 'year', - 'years', - 'week', - 'weeks', - ])->getValue(); + $attributes['durationUnit'] = $stream->expect(Token::NAME_TYPE, DateTimeHelper::DURATION_UNITS)->getValue(); } $stream->expect(Token::BLOCK_END_TYPE);