diff --git a/composer.json b/composer.json index fd4b62cef1..5fdafcae10 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "league/glide": "^2.3", "maennchen/zipstream-php": "^3.1", "michelf/php-smartypants": "^1.8.1", - "nesbot/carbon": "^2.62.1", + "nesbot/carbon": "^2.62.1 || ^3.0", "pixelfear/composer-dist-plugin": "^0.1.4", "rebing/graphql-laravel": "^9.7", "rhukster/dom-sanitizer": "^1.0.6", diff --git a/src/Http/Middleware/Localize.php b/src/Http/Middleware/Localize.php index 17a3ecdca0..745df44a61 100644 --- a/src/Http/Middleware/Localize.php +++ b/src/Http/Middleware/Localize.php @@ -5,8 +5,10 @@ use Carbon\Carbon; use Closure; use Illuminate\Support\Facades\Date; +use ReflectionClass; use Statamic\Facades\Site; use Statamic\Statamic; +use Statamic\Support\Arr; class Localize { @@ -29,10 +31,7 @@ public function handle($request, Closure $next) app()->setLocale($site->lang()); // Get original Carbon format so it can be restored later. - // There's no getter for it, so we'll use reflection. - $format = (new \ReflectionClass(Carbon::class))->getProperty('toStringFormat'); - $format->setAccessible(true); - $originalToStringFormat = $format->getValue(); + $originalToStringFormat = $this->getToStringFormat(); Date::setToStringFormat(Statamic::dateFormat()); $response = $next($request); @@ -45,4 +44,29 @@ public function handle($request, Closure $next) return $response; } + + /** + * This method is used to get the current toStringFormat for Carbon, in order for us + * to restore it later. There's no getter for it, so we need to use reflection. + * + * @throws \ReflectionException + */ + private function getToStringFormat(): ?string + { + $reflection = new ReflectionClass($date = Date::now()); + + // Carbon 2.x + if ($reflection->hasProperty('toStringFormat')) { + $format = $reflection->getProperty('toStringFormat'); + $format->setAccessible(true); + + return $format->getValue(); + } + + // Carbon 3.x + $factory = $reflection->getMethod('getFactory'); + $factory->setAccessible(true); + + return Arr::get($factory->invoke($date)->getSettings(), 'toStringFormat'); + } } diff --git a/src/Licensing/LicenseManager.php b/src/Licensing/LicenseManager.php index 94ca85e7c0..5c8f392204 100644 --- a/src/Licensing/LicenseManager.php +++ b/src/Licensing/LicenseManager.php @@ -35,7 +35,7 @@ public function requestRateLimited() public function failedRequestRetrySeconds() { return $this->requestRateLimited() - ? Carbon::createFromTimestamp($this->response('expiry'))->diffInSeconds() + ? (int) Carbon::createFromTimestamp($this->response('expiry'))->diffInSeconds(absolute: true) : null; } diff --git a/src/Licensing/Outpost.php b/src/Licensing/Outpost.php index 32ffba1daa..4385a2c078 100644 --- a/src/Licensing/Outpost.php +++ b/src/Licensing/Outpost.php @@ -199,7 +199,7 @@ private function cacheAndReturnValidationResponse($e) private function cacheAndReturnRateLimitResponse($e) { - $seconds = $e->getResponse()->getHeader('Retry-After')[0]; + $seconds = (int) $e->getResponse()->getHeader('Retry-After')[0]; return $this->cacheResponse(now()->addSeconds($seconds), ['error' => 429]); } diff --git a/src/Modifiers/CoreModifiers.php b/src/Modifiers/CoreModifiers.php index dca01d2c57..ddda779b21 100644 --- a/src/Modifiers/CoreModifiers.php +++ b/src/Modifiers/CoreModifiers.php @@ -546,7 +546,7 @@ public function dashify($value) */ public function daysAgo($value, $params) { - return $this->carbon($value)->diffInDays(Arr::get($params, 0)); + return (int) $this->carbon($value)->diffInDays(Arr::get($params, 0)); } /** @@ -1055,7 +1055,7 @@ public function hexToRgb($value) */ public function hoursAgo($value, $params) { - return $this->carbon($value)->diffInHours(Arr::get($params, 0)); + return (int) $this->carbon($value)->diffInHours(Arr::get($params, 0)); } /** @@ -1652,7 +1652,7 @@ public function modifyDate($value, $params) */ public function monthsAgo($value, $params) { - return $this->carbon($value)->diffInMonths(Arr::get($params, 0)); + return (int) $this->carbon($value)->diffInMonths(Arr::get($params, 0)); } /** @@ -2234,7 +2234,7 @@ public function segment($value, $params, $context) */ public function secondsAgo($value, $params) { - return $this->carbon($value)->diffInSeconds(Arr::get($params, 0)); + return (int) $this->carbon($value)->diffInSeconds(Arr::get($params, 0)); } /** @@ -2933,7 +2933,7 @@ public function values($value) */ public function weeksAgo($value, $params) { - return $this->carbon($value)->diffInWeeks(Arr::get($params, 0)); + return (int) $this->carbon($value)->diffInWeeks(Arr::get($params, 0)); } /** diff --git a/tests/Feature/GraphQL/Fieldtypes/DateFieldtypeTest.php b/tests/Feature/GraphQL/Fieldtypes/DateFieldtypeTest.php index 4cf18632ce..776cfee9b2 100644 --- a/tests/Feature/GraphQL/Fieldtypes/DateFieldtypeTest.php +++ b/tests/Feature/GraphQL/Fieldtypes/DateFieldtypeTest.php @@ -5,6 +5,8 @@ use Illuminate\Support\Carbon; use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\Test; +use ReflectionClass; +use Statamic\Support\Arr; #[Group('graphql')] class DateFieldtypeTest extends FieldtypeTestCase @@ -14,7 +16,17 @@ public function setUp(): void parent::setUp(); Carbon::macro('getToStringFormat', function () { - return static::$toStringFormat; + // Carbon 2.x + if (property_exists(static::this(), 'toStringFormat')) { + return static::$toStringFormat; + } + + // Carbon 3.x + $reflection = new ReflectionClass(self::this()); + $factory = $reflection->getMethod('getFactory'); + $factory->setAccessible(true); + + return Arr::get($factory->invoke(self::this())->getSettings(), 'toStringFormat'); }); }