From baf6792e1e5880cc9b6ec77d815b504d2b6d2e19 Mon Sep 17 00:00:00 2001 From: Tomas Votruba Date: Wed, 31 Jul 2024 15:16:44 +0000 Subject: [PATCH] Updated Rector to commit 71ae13a461e3225c63d095597a4145d8851d555e https://github.com/rectorphp/rector-src/commit/71ae13a461e3225c63d095597a4145d8851d555e Carbon use parse method (#6183) --- .../Carbon/NodeFactory/CarbonCallFactory.php | 181 +++++++++++------- src/Application/VersionResolver.php | 4 +- 2 files changed, 116 insertions(+), 69 deletions(-) diff --git a/rules/Carbon/NodeFactory/CarbonCallFactory.php b/rules/Carbon/NodeFactory/CarbonCallFactory.php index 764928bafb6..a1306f79aaa 100644 --- a/rules/Carbon/NodeFactory/CarbonCallFactory.php +++ b/rules/Carbon/NodeFactory/CarbonCallFactory.php @@ -15,84 +15,131 @@ final class CarbonCallFactory { /** * @var string - * @see https://regex101.com/r/9vGt8r/1 + * @see https://regex101.com/r/LLMrFw/1 */ - private const PLUS_DAY_COUNT_REGEX = '#\\+(\\s+)?(?\\d+)(\\s+)?(day|days)#'; + private const PLUS_MINUS_COUNT_REGEX = '#(?\\+|-)(\\s+)?(?\\d+)(\\s+)?(?seconds|second|sec|minutes|minute|min|hours|hour|days|day|weeks|week|months|month|years|year)#'; /** * @var string - * @see https://regex101.com/r/pqOPg6/1 + * @see https://regex101.com/r/IhxHTO/1 */ - private const MINUS_DAY_COUNT_REGEX = '#-(\\s+)?(?\\d+)(\\s+)?(day|days)#'; - /** - * @var string - * @see https://regex101.com/r/6VUUQF/1 - */ - private const PLUS_MONTH_COUNT_REGEX = '#\\+(\\s+)?(?\\d+)(\\s+)?(month|months)#'; - /** - * @var string - * @see https://regex101.com/r/dWRjk5/1 - */ - private const PLUS_HOUR_COUNT_REGEX = '#\\+(\\s+)?(?\\d+)(\\s+)?(hour|hours)#'; - /** - * @var string - * @see https://regex101.com/r/dfK0Ri/1 - */ - private const PLUS_MINUTE_COUNT_REGEX = '#\\+(\\s+)?(?\\d+)(\\s+)?(minute|minuts)#'; - /** - * @var string - * @see https://regex101.com/r/o7QDYL/1 - */ - private const PLUS_SECOND_COUNT_REGEX = '#\\+(\\s+)?(?\\d+)(\\s+)?(second|seconds)#'; - /** - * @var string - * @see https://regex101.com/r/IvyT7w/1 - */ - private const MINUS_MONTH_COUNT_REGEX = '#-(\\s+)?(?\\d+)(\\s+)?(month|months)#'; - /** - * @var string - * @see https://regex101.com/r/bICKg6/1 - */ - private const MINUS_HOUR_COUNT_REGEX = '#-(\\s+)?(?\\d+)(\\s+)?(hour|hours)#'; - /** - * @var string - * @see https://regex101.com/r/WILFvX/1 - */ - private const MINUS_MINUTE_COUNT_REGEX = '#-(\\s+)?(?\\d+)(\\s+)?(minute|minutes)#'; - /** - * @var string - * @see https://regex101.com/r/FwCUup/1 - */ - private const MINUS_SECOND_COUNT_REGEX = '#-(\\s+)?(?\\d+)(\\s+)?(second|seconds)#'; - /** - * @var array - */ - private const REGEX_TO_METHOD_NAME_MAP = [self::PLUS_DAY_COUNT_REGEX => 'addDays', self::MINUS_DAY_COUNT_REGEX => 'subDays', self::PLUS_MONTH_COUNT_REGEX => 'addMonths', self::MINUS_MONTH_COUNT_REGEX => 'subMonths', self::PLUS_HOUR_COUNT_REGEX => 'addHours', self::MINUS_HOUR_COUNT_REGEX => 'subHours', self::PLUS_MINUTE_COUNT_REGEX => 'addMinutes', self::MINUS_MINUTE_COUNT_REGEX => 'subMinutes', self::PLUS_SECOND_COUNT_REGEX => 'addSeconds', self::MINUS_SECOND_COUNT_REGEX => 'subSeconds']; + private const STATIC_DATE_REGEX = '#now|yesterday|today|tomorrow#'; /** * @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall */ public function createFromDateTimeString(FullyQualified $carbonFullyQualified, String_ $string) { - $dateTimeValue = $string->value; - if ($dateTimeValue === 'now') { - return new StaticCall($carbonFullyQualified, new Identifier('now')); - } - if ($dateTimeValue === 'today') { - return new StaticCall($carbonFullyQualified, new Identifier('today')); - } - $hasToday = Strings::match($dateTimeValue, '#today#'); - if ($hasToday !== null) { - $carbonCall = new StaticCall($carbonFullyQualified, new Identifier('today')); - } else { - $carbonCall = new StaticCall($carbonFullyQualified, new Identifier('now')); - } - foreach (self::REGEX_TO_METHOD_NAME_MAP as $regex => $methodName) { - $match = Strings::match($dateTimeValue, $regex); - if ($match === null) { - continue; + $carbonCall = $this->createStaticCall($carbonFullyQualified, $string); + $string->value = Strings::replace($string->value, self::STATIC_DATE_REGEX); + // Handle add/sub multiple times + while ($match = Strings::match($string->value, self::PLUS_MINUS_COUNT_REGEX)) { + $methodCall = $this->createModifyMethodCall($carbonCall, new LNumber((int) $match['count']), $match['unit'], $match['operator']); + if ($methodCall) { + $carbonCall = $methodCall; + $string->value = Strings::replace($string->value, self::PLUS_MINUS_COUNT_REGEX, '', 1); } - $countLNumber = new LNumber((int) $match['count']); - $carbonCall = new MethodCall($carbonCall, new Identifier($methodName), [new Arg($countLNumber)]); + } + // If we still have something in the string, we go back to the first method and replace this with a parse + if (($rest = Strings::trim($string->value)) !== '') { + $currentCall = $carbonCall; + $callStack = []; + while ($currentCall instanceof MethodCall) { + $callStack[] = $currentCall; + $currentCall = $currentCall->var; + } + if (!$currentCall instanceof StaticCall) { + return $carbonCall; + } + // If we fallback to a parse we want to include tomorrow/today/yesterday etc + if ($currentCall->name instanceof Identifier) { + if ($currentCall->name->name != 'now') { + $rest .= ' ' . $currentCall->name->name; + } + } + $currentCall->name = new Identifier('parse'); + $currentCall->args = [new Arg(new String_($rest))]; + // Rebuild original call from callstack + $carbonCall = $this->rebuildCallStack($currentCall, $callStack); } return $carbonCall; } + private function createStaticCall(FullyQualified $carbonFullyQualified, String_ $string) : StaticCall + { + $startDate = Strings::match($string->value, self::STATIC_DATE_REGEX)[0] ?? 'now'; + $carbonCall = new StaticCall($carbonFullyQualified, new Identifier($startDate)); + return $carbonCall; + } + /** + * @param \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall $carbonCall + */ + private function createModifyMethodCall($carbonCall, LNumber $countLNumber, string $unit, string $operator) : ?MethodCall + { + switch ($unit) { + case 'sec': + case 'second': + case 'seconds': + $unit = 'seconds'; + break; + case 'min': + case 'minute': + case 'minutes': + $unit = 'minutes'; + break; + case 'hour': + case 'hours': + $unit = 'hours'; + break; + case 'day': + case 'days': + $unit = 'days'; + break; + case 'week': + case 'weeks': + $unit = 'weeks'; + break; + case 'month': + case 'months': + $unit = 'months'; + break; + case 'year': + case 'years': + $unit = 'years'; + break; + default: + $unit = null; + break; + } + switch ($operator) { + case '+': + $operator = 'add'; + break; + case '-': + $operator = 'sub'; + break; + default: + $operator = null; + break; + } + if ($unit === null || $operator === null) { + return null; + } + $methodName = $operator . \ucfirst($unit); + return new MethodCall($carbonCall, new Identifier($methodName), [new Arg($countLNumber)]); + } + /** + * @param MethodCall[] $callStack + * @return \PhpParser\Node\Expr\MethodCall|\PhpParser\Node\Expr\StaticCall + */ + private function rebuildCallStack(StaticCall $carbonCall, array $callStack) + { + if (\count($callStack) === 0) { + return $carbonCall; + } + $currentCall = $carbonCall; + $callStack = \array_reverse($callStack); + foreach ($callStack as $call) { + $call->var = $currentCall; + $currentCall = $call; + } + return $currentCall; + } } diff --git a/src/Application/VersionResolver.php b/src/Application/VersionResolver.php index 6b46439f6c7..2d80df19a69 100644 --- a/src/Application/VersionResolver.php +++ b/src/Application/VersionResolver.php @@ -19,12 +19,12 @@ final class VersionResolver * @api * @var string */ - public const PACKAGE_VERSION = '97653a96da462aecddd02306557e811ccc38d6cb'; + public const PACKAGE_VERSION = '71ae13a461e3225c63d095597a4145d8851d555e'; /** * @api * @var string */ - public const RELEASE_DATE = '2024-07-30 13:29:46'; + public const RELEASE_DATE = '2024-07-31 17:13:54'; /** * @var int */