diff --git a/composer.json b/composer.json index 030f911c01dc..8f1324117c08 100644 --- a/composer.json +++ b/composer.json @@ -47,7 +47,6 @@ "psr/container": "^1.1.1 || ^2.0.1", "psr/log": "^1.0 || ^2.0 || ^3.0", "psr/simple-cache": "^1.0 || ^2.0 || ^3.0", - "ramsey/uuid": "^4.7", "symfony/console": "^7.4.0 || ^8.0.0", "symfony/error-handler": "^7.4.0 || ^8.0.0", "symfony/finder": "^7.4.0 || ^8.0.0", diff --git a/src/Illuminate/Queue/composer.json b/src/Illuminate/Queue/composer.json index 5d73849c7328..ec3c396f21f3 100644 --- a/src/Illuminate/Queue/composer.json +++ b/src/Illuminate/Queue/composer.json @@ -24,7 +24,6 @@ "illuminate/pipeline": "^13.0", "illuminate/support": "^13.0", "laravel/serializable-closure": "^2.0.10", - "ramsey/uuid": "^4.7", "symfony/process": "^7.4.5 || ^8.0.5" }, "suggest": { diff --git a/src/Illuminate/Support/BinaryCodec.php b/src/Illuminate/Support/BinaryCodec.php index 81c94299f698..5a9a57391cea 100644 --- a/src/Illuminate/Support/BinaryCodec.php +++ b/src/Illuminate/Support/BinaryCodec.php @@ -3,13 +3,12 @@ namespace Illuminate\Support; use InvalidArgumentException; -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\UuidInterface; use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; class BinaryCodec { - /** @var array */ + /** @var array */ protected static array $customCodecs = []; /** @@ -28,7 +27,7 @@ public static function register(string $name, callable $encode, callable $decode * * @throws \InvalidArgumentException */ - public static function encode(UuidInterface|Ulid|string|null $value, string $format): ?string + public static function encode(Uuid|Ulid|string|null $value, string $format): ?string { if (blank($value)) { return null; @@ -40,9 +39,9 @@ public static function encode(UuidInterface|Ulid|string|null $value, string $for return match ($format) { 'uuid' => match (true) { - $value instanceof UuidInterface => $value->getBytes(), + $value instanceof Uuid => $value->toBinary(), self::isBinary($value) => $value, - default => Uuid::fromString($value)->getBytes(), + default => Uuid::fromString($value)->toBinary(), }, 'ulid' => match (true) { $value instanceof Ulid => $value->toBinary(), @@ -69,7 +68,7 @@ public static function decode(?string $value, string $format): ?string } return match ($format) { - 'uuid' => (self::isBinary($value) ? Uuid::fromBytes($value) : Uuid::fromString($value))->toString(), + 'uuid' => (string) (self::isBinary($value) ? Uuid::fromBinary($value) : Uuid::fromString($value)), 'ulid' => (self::isBinary($value) ? Ulid::fromBinary($value) : Ulid::fromString($value))->toString(), default => throw new InvalidArgumentException("Format [$format] is invalid."), }; diff --git a/src/Illuminate/Support/Carbon.php b/src/Illuminate/Support/Carbon.php index 81f9fce89733..9122eaa7576b 100644 --- a/src/Illuminate/Support/Carbon.php +++ b/src/Illuminate/Support/Carbon.php @@ -4,10 +4,13 @@ use Carbon\Carbon as BaseCarbon; use Carbon\CarbonImmutable as BaseCarbonImmutable; +use Exception; use Illuminate\Support\Traits\Conditionable; use Illuminate\Support\Traits\Dumpable; -use Ramsey\Uuid\Uuid; +use Symfony\Component\Uid\BinaryUtil; +use Symfony\Component\Uid\TimeBasedUidInterface; use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; class Carbon extends BaseCarbon { @@ -31,6 +34,16 @@ public static function createFromId(Uuid|Ulid|string $id): static $id = Ulid::isValid($id) ? Ulid::fromString($id) : Uuid::fromString($id); } + if (Str::isUuid($uuid = $id->toString(), 2)) { + return static::createFromInterface( + BinaryUtil::hexToDateTime('0'.substr($uuid, 15, 3).substr($uuid, 9, 4).'00000000') + ); + } + + if (! $id instanceof TimeBasedUidInterface) { + throw new Exception("Not a time-based UUID or ULID: [{$id->toString()}]."); + } + return static::createFromInterface($id->getDateTime()); } diff --git a/src/Illuminate/Support/Str.php b/src/Illuminate/Support/Str.php index cc3874e9c976..f153fec42bed 100644 --- a/src/Illuminate/Support/Str.php +++ b/src/Illuminate/Support/Str.php @@ -9,13 +9,12 @@ use League\CommonMark\Extension\InlinesOnly\InlinesOnlyExtension; use League\CommonMark\GithubFlavoredMarkdownConverter; use League\CommonMark\MarkdownConverter; -use Ramsey\Uuid\Codec\TimestampFirstCombCodec; -use Ramsey\Uuid\Exception\InvalidUuidStringException; -use Ramsey\Uuid\Generator\CombGenerator; -use Ramsey\Uuid\Rfc4122\FieldsInterface; -use Ramsey\Uuid\Uuid; -use Ramsey\Uuid\UuidFactory; +use Symfony\Component\Uid\Exception\InvalidArgumentException; +use Symfony\Component\Uid\MaxUuid; +use Symfony\Component\Uid\NilUuid; use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; +use Symfony\Component\Uid\UuidV7; use Throwable; use Traversable; use voku\helper\ASCII; @@ -55,7 +54,7 @@ class Str /** * The callback that should be used to generate UUIDs. * - * @var (callable(): \Ramsey\Uuid\UuidInterface)|null + * @var (callable(): \Symfony\Component\Uid\Uuid)|null */ protected static $uuidFactory; @@ -652,33 +651,25 @@ public static function isUuid($value, $version = null) return false; } - if ($version === null) { - return preg_match('/^[\da-fA-F]{8}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{4}-[\da-fA-F]{12}$/D', $value) > 0; + if (is_null($version)) { + return Uuid::isValid($value); } - $factory = new UuidFactory; - try { - $factoryUuid = $factory->fromString($value); - } catch (InvalidUuidStringException) { - return false; - } - - $fields = $factoryUuid->getFields(); - - if (! ($fields instanceof FieldsInterface)) { + $uuid = Uuid::fromString($value); + } catch (InvalidArgumentException) { return false; } - if ($version === 0 || $version === 'nil') { - return $fields->isNil(); + if ($version === 'nil' || $version === 0) { + return $uuid instanceof NilUuid; } if ($version === 'max') { - return $fields->isMax(); + return $uuid instanceof MaxUuid; } - return $fields->getVersion() === $version; + return $version === (int) $uuid->toString()[14]; } /** @@ -1922,32 +1913,32 @@ public static function wordWrap($string, $characters = 75, $break = "\n", $cutLo /** * Generate a UUID (version 4). * - * @return \Ramsey\Uuid\UuidInterface + * @return \Symfony\Component\Uid\Uuid */ public static function uuid() { return static::$uuidFactory ? call_user_func(static::$uuidFactory) - : Uuid::uuid4(); + : Uuid::v4(); } /** * Generate a UUID (version 7). * * @param \DateTimeInterface|null $time - * @return \Ramsey\Uuid\UuidInterface + * @return \Symfony\Component\Uid\Uuid */ public static function uuid7($time = null) { return static::$uuidFactory ? call_user_func(static::$uuidFactory) - : Uuid::uuid7($time); + : new UuidV7(UuidV7::generate($time)); } /** * Generate a time-ordered UUID. * - * @return \Ramsey\Uuid\UuidInterface + * @return \Symfony\Component\Uid\Uuid */ public static function orderedUuid() { @@ -1955,24 +1946,13 @@ public static function orderedUuid() return call_user_func(static::$uuidFactory); } - $factory = new UuidFactory; - - $factory->setRandomGenerator(new CombGenerator( - $factory->getRandomGenerator(), - $factory->getNumberConverter() - )); - - $factory->setCodec(new TimestampFirstCombCodec( - $factory->getUuidBuilder() - )); - - return $factory->uuid4(); + return static::uuid7(); } /** * Set the callable that will be used to generate UUIDs. * - * @param (callable(): \Ramsey\Uuid\UuidInterface)|null $factory + * @param (callable(): \Symfony\Component\Uid\Uuid)|null $factory * @return void */ public static function createUuidsUsing(?callable $factory = null) @@ -1983,8 +1963,8 @@ public static function createUuidsUsing(?callable $factory = null) /** * Set the sequence that will be used to generate UUIDs. * - * @param \Ramsey\Uuid\UuidInterface[] $sequence - * @param (callable(): \Ramsey\Uuid\UuidInterface)|null $whenMissing + * @param \Symfony\Component\Uid\Uuid[] $sequence + * @param (callable(): \Symfony\Component\Uid\Uuid)|null $whenMissing * @return void */ public static function createUuidsUsingSequence(array $sequence, $whenMissing = null) @@ -2017,8 +1997,8 @@ public static function createUuidsUsingSequence(array $sequence, $whenMissing = /** * Always return the same UUID when generating new UUIDs. * - * @param (\Closure(\Ramsey\Uuid\UuidInterface): mixed)|null $callback - * @return \Ramsey\Uuid\UuidInterface + * @param (\Closure(\Symfony\Component\Uid\Uuid): mixed)|null $callback + * @return \Symfony\Component\Uid\Uuid */ public static function freezeUuids(?Closure $callback = null) { diff --git a/src/Illuminate/Support/composer.json b/src/Illuminate/Support/composer.json index eb8bd0c66b6e..2455bf70d18d 100644 --- a/src/Illuminate/Support/composer.json +++ b/src/Illuminate/Support/composer.json @@ -39,9 +39,8 @@ "laravel/serializable-closure": "Required to use the once function (^2.0.10).", "league/commonmark": "Required to use Str::markdown() and Stringable::markdown() (^2.7).", "league/uri": "Required to use the Uri class (^7.5.1).", - "ramsey/uuid": "Required to use Str::uuid() (^4.7).", "symfony/process": "Required to use the Composer class (^7.4 || ^8.0).", - "symfony/uid": "Required to use Str::ulid() (^7.4 || ^8.0).", + "symfony/uid": "Required to use Str::uuid() or Str::ulid() (^7.4 || ^8.0).", "symfony/var-dumper": "Required to use the dd function (^7.4 || ^8.0).", "vlucas/phpdotenv": "Required to use the Env class and env helper (^5.6.1)." }, diff --git a/src/Illuminate/Validation/composer.json b/src/Illuminate/Validation/composer.json index da5f98f5d829..8eeebefe62a9 100755 --- a/src/Illuminate/Validation/composer.json +++ b/src/Illuminate/Validation/composer.json @@ -30,7 +30,7 @@ }, "suggest": { "illuminate/database": "Required to use the database presence verifier (^13.0).", - "ramsey/uuid": "Required to use Validator::validateUuid() (^4.7)." + "symfony/uid": "Required to use Validator::validateUuid() or Validator::validateUlid() (^7.4 || ^8.0." }, "minimum-stability": "dev", "autoload": { diff --git a/tests/Database/DatabaseEloquentAsBinaryCastTest.php b/tests/Database/DatabaseEloquentAsBinaryCastTest.php index 6a955cfb5c5d..dc0fd5c4763a 100644 --- a/tests/Database/DatabaseEloquentAsBinaryCastTest.php +++ b/tests/Database/DatabaseEloquentAsBinaryCastTest.php @@ -7,8 +7,8 @@ use Illuminate\Support\BinaryCodec; use InvalidArgumentException; use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Uuid; use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; class DatabaseEloquentAsBinaryCastTest extends TestCase { @@ -45,7 +45,7 @@ public function testGetDecodesUuidFromBinary() { $uuid = '550e8400-e29b-41d4-a716-446655440000'; $model = new AsBinaryTestModel; - $model->setRawAttributes(['uuid' => Uuid::fromString($uuid)->getBytes()]); + $model->setRawAttributes(['uuid' => Uuid::fromString($uuid)->toBinary()]); $this->assertSame($uuid, $model->uuid); } @@ -56,7 +56,7 @@ public function testSetEncodesUuidToBinary() $model = new AsBinaryTestModel; $model->uuid = $uuid; - $this->assertSame(Uuid::fromString($uuid)->getBytes(), $model->getAttributes()['uuid']); + $this->assertSame(Uuid::fromString($uuid)->toBinary(), $model->getAttributes()['uuid']); } public function testGetDecodesUlidFromBinary() diff --git a/tests/Integration/Database/EloquentModelDecimalCastingTest.php b/tests/Integration/Database/EloquentModelDecimalCastingTest.php index 105b328b0020..af72adac74d5 100644 --- a/tests/Integration/Database/EloquentModelDecimalCastingTest.php +++ b/tests/Integration/Database/EloquentModelDecimalCastingTest.php @@ -71,7 +71,10 @@ public function testItWrapsThrownExceptions() } catch (MathException $e) { $this->assertSame('Unable to cast value to a decimal.', $e->getMessage()); $this->assertInstanceOf(NumberFormatException::class, $e->getPrevious()); - $this->assertSame('The given value "foo" does not represent a valid number.', $e->getPrevious()->getMessage()); + $this->assertTrue(in_array($e->getPrevious()->getMessage(), [ + 'The given value "foo" does not represent a valid number.', + 'Value "foo" does not represent a valid number.', + ], true)); } } diff --git a/tests/Support/SupportBinaryCodecTest.php b/tests/Support/SupportBinaryCodecTest.php index de8e36c87635..3c24fa7f9cdb 100644 --- a/tests/Support/SupportBinaryCodecTest.php +++ b/tests/Support/SupportBinaryCodecTest.php @@ -6,8 +6,8 @@ use InvalidArgumentException; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\Uuid; use Symfony\Component\Uid\Ulid; +use Symfony\Component\Uid\Uuid; class SupportBinaryCodecTest extends TestCase { @@ -85,12 +85,12 @@ public function testUuidEncodeFromString() { $uuid = '550e8400-e29b-41d4-a716-446655440000'; - $this->assertSame(Uuid::fromString($uuid)->getBytes(), BinaryCodec::encode($uuid, 'uuid')); + $this->assertSame(Uuid::fromString($uuid)->toBinary(), BinaryCodec::encode($uuid, 'uuid')); } public function testUuidEncodeFromBinary() { - $bytes = Uuid::fromString('550e8400-e29b-41d4-a716-446655440000')->getBytes(); + $bytes = Uuid::fromString('550e8400-e29b-41d4-a716-446655440000')->toBinary(); $this->assertSame($bytes, BinaryCodec::encode($bytes, 'uuid')); } @@ -99,13 +99,13 @@ public function testUuidEncodeFromInstance() { $uuid = Uuid::fromString('550e8400-e29b-41d4-a716-446655440000'); - $this->assertSame($uuid->getBytes(), BinaryCodec::encode($uuid, 'uuid')); + $this->assertSame($uuid->toBinary(), BinaryCodec::encode($uuid, 'uuid')); } public function testUuidDecodeFromBinary() { $uuid = '550e8400-e29b-41d4-a716-446655440000'; - $bytes = Uuid::fromString($uuid)->getBytes(); + $bytes = Uuid::fromString($uuid)->toBinary(); $this->assertSame($uuid, BinaryCodec::decode($bytes, 'uuid')); } diff --git a/tests/Support/SupportCarbonTest.php b/tests/Support/SupportCarbonTest.php index 9500e2559469..d551fb48856e 100644 --- a/tests/Support/SupportCarbonTest.php +++ b/tests/Support/SupportCarbonTest.php @@ -139,7 +139,7 @@ public function testCreateFromUid() $this->assertEquals('2023-05-12 03:23:43.347428', $uuidv6->toDateTimeString('microsecond')); $uuidv7 = Carbon::createFromId('01880dfa-2825-72e4-acbb-b1e4981cf8af'); - $this->assertEquals('2023-05-12 03:21:18.117000', $uuidv7->toDateTimeString('microsecond')); + $this->assertEquals('2023-05-12 03:21:18.117185', $uuidv7->toDateTimeString('microsecond')); } public function testPlus(): void diff --git a/tests/Support/SupportStrTest.php b/tests/Support/SupportStrTest.php index 6bfec03405af..6def5633f48f 100755 --- a/tests/Support/SupportStrTest.php +++ b/tests/Support/SupportStrTest.php @@ -7,8 +7,8 @@ use Illuminate\Tests\Support\Fixtures\StringableObjectStub; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\TestCase; -use Ramsey\Uuid\UuidInterface; use ReflectionClass; +use Symfony\Component\Uid\Uuid; use ValueError; class SupportStrTest extends TestCase @@ -1366,9 +1366,9 @@ public function testUcsplit() public function testUuid() { - $this->assertInstanceOf(UuidInterface::class, Str::uuid()); - $this->assertInstanceOf(UuidInterface::class, Str::orderedUuid()); - $this->assertInstanceOf(UuidInterface::class, Str::uuid7()); + $this->assertInstanceOf(Uuid::class, Str::uuid()); + $this->assertInstanceOf(Uuid::class, Str::orderedUuid()); + $this->assertInstanceOf(Uuid::class, Str::uuid7()); } public function testAsciiNull()