diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml
index bf15cab..d375d20 100644
--- a/.github/workflows/continuous-integration.yml
+++ b/.github/workflows/continuous-integration.yml
@@ -76,6 +76,7 @@ jobs:
matrix:
php-version:
- "8.1"
+ - "8.2"
steps:
- name: "Checkout repository"
@@ -90,7 +91,7 @@ jobs:
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
- extensions: bcmath, ctype, gmp, sodium, uuid
+ extensions: bcmath, gmp, sodium, uuid
coverage: "none"
ini-values: "memory_limit=-1"
@@ -117,7 +118,7 @@ jobs:
uses: "shivammathur/setup-php@v2"
with:
php-version: "latest"
- extensions: bcmath, ctype, gmp, sodium, uuid
+ extensions: bcmath, gmp, sodium, uuid
coverage: "pcov"
ini-values: "memory_limit=-1"
@@ -130,7 +131,7 @@ jobs:
run: "./vendor/bin/phpunit --verbose --colors=always --coverage-text --coverage-clover build/logs/clover.xml"
- name: "Publish coverage report to Codecov"
- uses: "codecov/codecov-action@v3.1.0"
+ uses: "codecov/codecov-action@v3.1.1"
unit-tests:
name: "Unit Tests"
@@ -142,6 +143,7 @@ jobs:
matrix:
php-version:
- "8.1"
+ - "8.2"
operating-system:
- "ubuntu-latest"
- "windows-latest"
@@ -166,7 +168,7 @@ jobs:
uses: "shivammathur/setup-php@v2"
with:
php-version: "${{ matrix.php-version }}"
- extensions: bcmath, ctype, gmp, sodium, uuid
+ extensions: bcmath, gmp, sodium, uuid
coverage: "none"
ini-values: "memory_limit=-1"
diff --git a/.github/workflows/merge-dependabot-upgrades.yml b/.github/workflows/merge-dependabot-upgrades.yml
index 574d7dd..cf1cb90 100644
--- a/.github/workflows/merge-dependabot-upgrades.yml
+++ b/.github/workflows/merge-dependabot-upgrades.yml
@@ -17,7 +17,7 @@ jobs:
steps:
- name: Auto-Merge
if: ${{ github.event.workflow_run.conclusion == 'success' }}
- uses: ridedott/merge-me-action@v2.10.20
+ uses: ridedott/merge-me-action@v2.10.39
with:
# This must be used as GitHub Actions token does not support pushing
# to protected branches.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e269e1c..85e485a 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -72,6 +72,92 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Remove dependency on ramsey/collection package.
+## 4.7.1 - 2022-12-31
+
+### Fixed
+
+* Allow the use of ramsey/collection ^2.0 with ramsey/uuid.
+
+
+## 4.7.0 - 2022-12-19
+
+### Added
+
+* Add `Uuid::fromHexadecimal()` and `UuidFactory::fromHexadecimal()`. These
+ methods are not required by the interfaces.
+
+### Fixed
+
+* Ignore MAC addresses consisting of all zeroes (i.e., `00:00:00:00:00:00`).
+
+
+## 4.6.0 - 2022-11-05
+
+### Added
+
+* Add support for version 8, Unix Epoch time UUIDs, as defined in
+ [draft-ietf-uuidrev-rfc4122bis-00, section 5.8][version8]. While still an
+ Internet-Draft, version 8 is stable and unlikely to change in any way that
+ breaks compatibility.
+ * Use `Ramsey\Uuid\Uuid::uuid8()` to generate version 8 UUIDs.
+ * Version 8 UUIDs are of type `Ramsey\Uuid\Rfc4122\UuidV8`.
+ * The constant `Ramsey\Uuid\Uuid::UUID_TYPE_CUSTOM` exists for version 8 UUIDs.
+
+### Fixed
+
+* Ensure monotonicity of version 7 UUIDs.
+
+
+## 4.5.1 - 2022-09-16
+
+### Fixed
+
+* Update RFC 4122 validator to recognize version 6 and 7 UUIDs.
+
+
+## 4.5.0 - 2022-09-15
+
+### Added
+
+* Promote version 6, reordered time UUIDs from the `Nonstandard` namespace to
+ the `Rfc4122` namespace. Version 6 UUIDs are defined in
+ [draft-ietf-uuidrev-rfc4122bis-00, section 5.6][version6]. While still an
+ Internet-Draft version 6 is stable and unlikely to change in any way that
+ breaks compatibility.
+* Add support for version 7, Unix Epoch time UUIDs, as defined in
+ [draft-ietf-uuidrev-rfc4122bis-00, section 5.7][version7]. While still an
+ Internet-Draft, version 7 is stable and unlikely to change in any way that
+ breaks compatibility.
+ * Use `Ramsey\Uuid\Uuid::uuid7()` to generate version 7 UUIDs.
+ * Version 7 UUIDs are of type `Ramsey\Uuid\Rfc4122\UuidV7`.
+ * The constant `Ramsey\Uuid\Uuid::UUID_TYPE_UNIX_TIME` exists for version
+ 7 UUIDs.
+* Add `Ramsey\Uuid\Converter\Time\UnixTimeConverter` and
+ `Ramsey\Uuid\Generator\UnixTimeGenerator` to support version 7 UUID generation.
+* Add support for [max UUIDs][] through `Ramsey\Uuid\Uuid::MAX` and
+ `Ramsey\Uuid\Rfc4122\MaxUuid`.
+
+### Changed
+
+* The lowest version of brick/math allowed is now `^0.8.8`.
+
+### Deprecated
+
+The following will be removed in ramsey/uuid 5.0.0:
+
+* `Ramsey\Uuid\Nonstandard\UuidV6` is deprecated in favor of
+ `Ramsey\Uuid\Rfc4122\UuidV6`.
+* `Ramsey\Uuid\Uuid::UUID_TYPE_PEABODY`; use
+ `Ramsey\Uuid\Uuid::UUID_TYPE_REORDERED_TIME` instead.
+
+### Fixed
+
+* For `Ramsey\Uuid\Uuid::isValid()`, Psalm now asserts the UUID is a
+ non-empty-string when it is valid.
+* Nil UUIDs are properly treated as RFC 4122 variants, and `getVariant()` now
+ returns a `2` when called on a nil UUID.
+
+
## 4.4.0 - 2022-08-05
### Changed
@@ -774,6 +860,13 @@ The following functionality is deprecated and will be removed in ramsey/uuid
throws this exception.
+## 3.9.7 - 2022-12-19
+
+### Fixed
+
+* Add `#[ReturnTypeWillChange]` to `Uuid::jsonSerialize()` method.
+
+
## 3.9.6 - 2021-09-25
### Fixed
@@ -1381,3 +1474,7 @@ versions leading up to this release.*
[doctrine field type]: http://doctrine-dbal.readthedocs.org/en/latest/reference/types.html
[ramsey/uuid-doctrine]: https://github.com/ramsey/uuid-doctrine
[ramsey/uuid-console]: https://github.com/ramsey/uuid-console
+[version6]: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.6
+[version7]: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.7
+[version8]: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.8
+[max uuids]: https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#section-5.4
diff --git a/README.md b/README.md
index f3f4498..2720a41 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,7 @@
-
+
diff --git a/composer.json b/composer.json
index 73d45ca..632c1d2 100644
--- a/composer.json
+++ b/composer.json
@@ -30,6 +30,7 @@
"phpstan/phpstan-phpunit": "^1.1",
"phpunit/phpunit": "^9.5",
"psalm/plugin-phpunit": "^0.16.1",
+ "ramsey/composer-repl": "^1.4",
"slevomat/coding-standard": "^8.4",
"squizlabs/php_codesniffer": "^3.5",
"vimeo/psalm": "^4.22"
@@ -65,7 +66,8 @@
"captainhook/plugin-composer": true,
"ergebnis/composer-normalize": true,
"phpstan/extension-installer": true,
- "dealerdirect/phpcodesniffer-composer-installer": true
+ "dealerdirect/phpcodesniffer-composer-installer": true,
+ "ramsey/composer-repl": true
},
"sort-packages": true
},
@@ -86,8 +88,8 @@
"phpcbf": "phpcbf -vpw --cache=build/cache/phpcs.cache",
"phpcs": "phpcs --cache=build/cache/phpcs.cache",
"phpstan": [
- "phpstan analyse --no-progress",
- "phpstan analyse -c phpstan-tests.neon --no-progress"
+ "phpstan analyse --no-progress --memory-limit=1G",
+ "phpstan analyse -c phpstan-tests.neon --no-progress --memory-limit=1G"
],
"phpunit": "phpunit --verbose --colors=always",
"phpunit-coverage": "phpunit --verbose --colors=always --coverage-html build/coverage",
diff --git a/composer.lock b/composer.lock
index 2639a1d..b344512 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "35ada149231c1b6e1f276b92a905cef0",
+ "content-hash": "9835fa7593485115e03f0ef91f0f2145",
"packages": [
{
"name": "brick/math",
@@ -232,16 +232,16 @@
},
{
"name": "captainhook/captainhook",
- "version": "5.10.11",
+ "version": "5.12.0",
"source": {
"type": "git",
"url": "https://github.com/captainhookphp/captainhook.git",
- "reference": "377ea566c5fb91e2fbec6ad0aadf21eb88e18cee"
+ "reference": "cc27956ef2aa831e10053a891bda99df595b674b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/captainhookphp/captainhook/zipball/377ea566c5fb91e2fbec6ad0aadf21eb88e18cee",
- "reference": "377ea566c5fb91e2fbec6ad0aadf21eb88e18cee",
+ "url": "https://api.github.com/repos/captainhookphp/captainhook/zipball/cc27956ef2aa831e10053a891bda99df595b674b",
+ "reference": "cc27956ef2aa831e10053a891bda99df595b674b",
"shasum": ""
},
"require": {
@@ -251,7 +251,7 @@
"php": ">=7.2",
"sebastianfeldmann/camino": "^0.9.2",
"sebastianfeldmann/cli": "^3.3",
- "sebastianfeldmann/git": "^3.8.1",
+ "sebastianfeldmann/git": "^3.8.5",
"symfony/console": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0",
"symfony/filesystem": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0",
"symfony/process": "^2.7 || ^3.0 || ^4.0 || ^5.0 || ^6.0"
@@ -303,7 +303,7 @@
],
"support": {
"issues": "https://github.com/captainhookphp/captainhook/issues",
- "source": "https://github.com/captainhookphp/captainhook/tree/5.10.11"
+ "source": "https://github.com/captainhookphp/captainhook/tree/5.12.0"
},
"funding": [
{
@@ -311,7 +311,7 @@
"type": "github"
}
],
- "time": "2022-07-26T20:11:41+00:00"
+ "time": "2022-12-30T20:03:02+00:00"
},
{
"name": "captainhook/plugin-composer",
@@ -368,6 +368,337 @@
},
"time": "2022-01-28T04:35:22+00:00"
},
+ {
+ "name": "composer/ca-bundle",
+ "version": "1.3.4",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/ca-bundle.git",
+ "reference": "69098eca243998b53eed7a48d82dedd28b447cd5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/69098eca243998b53eed7a48d82dedd28b447cd5",
+ "reference": "69098eca243998b53eed7a48d82dedd28b447cd5",
+ "shasum": ""
+ },
+ "require": {
+ "ext-openssl": "*",
+ "ext-pcre": "*",
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.55",
+ "psr/log": "^1.0",
+ "symfony/phpunit-bridge": "^4.2 || ^5",
+ "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0 || ^6.0"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\CaBundle\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.",
+ "keywords": [
+ "cabundle",
+ "cacert",
+ "certificate",
+ "ssl",
+ "tls"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/ca-bundle/issues",
+ "source": "https://github.com/composer/ca-bundle/tree/1.3.4"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-10-12T12:08:29+00:00"
+ },
+ {
+ "name": "composer/class-map-generator",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/class-map-generator.git",
+ "reference": "1e1cb2b791facb2dfe32932a7718cf2571187513"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/class-map-generator/zipball/1e1cb2b791facb2dfe32932a7718cf2571187513",
+ "reference": "1e1cb2b791facb2dfe32932a7718cf2571187513",
+ "shasum": ""
+ },
+ "require": {
+ "composer/pcre": "^2 || ^3",
+ "php": "^7.2 || ^8.0",
+ "symfony/finder": "^4.4 || ^5.3 || ^6"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.6",
+ "phpstan/phpstan-deprecation-rules": "^1",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.1",
+ "symfony/filesystem": "^5.4 || ^6",
+ "symfony/phpunit-bridge": "^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\ClassMapGenerator\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Utilities to scan PHP code and generate class maps.",
+ "keywords": [
+ "classmap"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/class-map-generator/issues",
+ "source": "https://github.com/composer/class-map-generator/tree/1.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-06-19T11:31:27+00:00"
+ },
+ {
+ "name": "composer/composer",
+ "version": "2.5.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/composer.git",
+ "reference": "923278ad13e1621946eb76ab2882655d2cc396a4"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/composer/zipball/923278ad13e1621946eb76ab2882655d2cc396a4",
+ "reference": "923278ad13e1621946eb76ab2882655d2cc396a4",
+ "shasum": ""
+ },
+ "require": {
+ "composer/ca-bundle": "^1.0",
+ "composer/class-map-generator": "^1.0",
+ "composer/metadata-minifier": "^1.0",
+ "composer/pcre": "^2.1 || ^3.1",
+ "composer/semver": "^3.0",
+ "composer/spdx-licenses": "^1.5.7",
+ "composer/xdebug-handler": "^2.0.2 || ^3.0.3",
+ "justinrainbow/json-schema": "^5.2.11",
+ "php": "^7.2.5 || ^8.0",
+ "psr/log": "^1.0 || ^2.0 || ^3.0",
+ "react/promise": "^2.8",
+ "seld/jsonlint": "^1.4",
+ "seld/phar-utils": "^1.2",
+ "seld/signal-handler": "^2.0",
+ "symfony/console": "^5.4.11 || ^6.0.11",
+ "symfony/filesystem": "^5.4 || ^6.0",
+ "symfony/finder": "^5.4 || ^6.0",
+ "symfony/polyfill-php73": "^1.24",
+ "symfony/polyfill-php80": "^1.24",
+ "symfony/polyfill-php81": "^1.24",
+ "symfony/process": "^5.4 || ^6.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1.9.3",
+ "phpstan/phpstan-deprecation-rules": "^1",
+ "phpstan/phpstan-phpunit": "^1.0",
+ "phpstan/phpstan-strict-rules": "^1",
+ "phpstan/phpstan-symfony": "^1.2.10",
+ "symfony/phpunit-bridge": "^6.0"
+ },
+ "suggest": {
+ "ext-openssl": "Enabling the openssl extension allows you to access https URLs for repositories and packages",
+ "ext-zip": "Enabling the zip extension allows you to unzip archives",
+ "ext-zlib": "Allow gzip compression of HTTP requests"
+ },
+ "bin": [
+ "bin/composer"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "phpstan": {
+ "includes": [
+ "phpstan/rules.neon"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\": "src/Composer"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "https://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "https://seld.be"
+ }
+ ],
+ "description": "Composer helps you declare, manage and install dependencies of PHP projects. It ensures you have the right stack everywhere.",
+ "homepage": "https://getcomposer.org/",
+ "keywords": [
+ "autoload",
+ "dependency",
+ "package"
+ ],
+ "support": {
+ "irc": "ircs://irc.libera.chat:6697/composer",
+ "issues": "https://github.com/composer/composer/issues",
+ "source": "https://github.com/composer/composer/tree/2.5.1"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-12-22T14:33:54+00:00"
+ },
+ {
+ "name": "composer/metadata-minifier",
+ "version": "1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/metadata-minifier.git",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/c549d23829536f0d0e984aaabbf02af91f443207",
+ "reference": "c549d23829536f0d0e984aaabbf02af91f443207",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "composer/composer": "^2",
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\MetadataMinifier\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Small utility library that handles metadata minification and expansion.",
+ "keywords": [
+ "composer",
+ "compression"
+ ],
+ "support": {
+ "issues": "https://github.com/composer/metadata-minifier/issues",
+ "source": "https://github.com/composer/metadata-minifier/tree/1.0.0"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2021-04-07T13:37:33+00:00"
+ },
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.5",
@@ -443,16 +774,16 @@
},
{
"name": "composer/pcre",
- "version": "3.0.0",
+ "version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/composer/pcre.git",
- "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd"
+ "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/pcre/zipball/e300eb6c535192decd27a85bc72a9290f0d6b3bd",
- "reference": "e300eb6c535192decd27a85bc72a9290f0d6b3bd",
+ "url": "https://api.github.com/repos/composer/pcre/zipball/4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
+ "reference": "4bff79ddd77851fe3cdd11616ed3f92841ba5bd2",
"shasum": ""
},
"require": {
@@ -494,7 +825,7 @@
],
"support": {
"issues": "https://github.com/composer/pcre/issues",
- "source": "https://github.com/composer/pcre/tree/3.0.0"
+ "source": "https://github.com/composer/pcre/tree/3.1.0"
},
"funding": [
{
@@ -510,7 +841,7 @@
"type": "tidelift"
}
],
- "time": "2022-02-25T20:21:48+00:00"
+ "time": "2022-11-17T09:50:14+00:00"
},
{
"name": "composer/semver",
@@ -593,6 +924,86 @@
],
"time": "2022-04-01T19:23:25+00:00"
},
+ {
+ "name": "composer/spdx-licenses",
+ "version": "1.5.7",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/composer/spdx-licenses.git",
+ "reference": "c848241796da2abf65837d51dce1fae55a960149"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/composer/spdx-licenses/zipball/c848241796da2abf65837d51dce1fae55a960149",
+ "reference": "c848241796da2abf65837d51dce1fae55a960149",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^5.3.2 || ^7.0 || ^8.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^0.12.55",
+ "symfony/phpunit-bridge": "^4.2 || ^5"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Composer\\Spdx\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nils Adermann",
+ "email": "naderman@naderman.de",
+ "homepage": "http://www.naderman.de"
+ },
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ },
+ {
+ "name": "Rob Bast",
+ "email": "rob.bast@gmail.com",
+ "homepage": "http://robbast.nl"
+ }
+ ],
+ "description": "SPDX licenses list and validation library.",
+ "keywords": [
+ "license",
+ "spdx",
+ "validator"
+ ],
+ "support": {
+ "irc": "irc://irc.freenode.org/composer",
+ "issues": "https://github.com/composer/spdx-licenses/issues",
+ "source": "https://github.com/composer/spdx-licenses/tree/1.5.7"
+ },
+ "funding": [
+ {
+ "url": "https://packagist.com",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/composer",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/composer/composer",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-05-23T07:37:50+00:00"
+ },
{
"name": "composer/xdebug-handler",
"version": "3.0.3",
@@ -773,32 +1184,35 @@
},
{
"name": "doctrine/annotations",
- "version": "1.13.3",
+ "version": "1.14.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/annotations.git",
- "reference": "648b0343343565c4a056bfc8392201385e8d89f0"
+ "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/annotations/zipball/648b0343343565c4a056bfc8392201385e8d89f0",
- "reference": "648b0343343565c4a056bfc8392201385e8d89f0",
+ "url": "https://api.github.com/repos/doctrine/annotations/zipball/ad785217c1e9555a7d6c6c8c9f406395a5e2882b",
+ "reference": "ad785217c1e9555a7d6c6c8c9f406395a5e2882b",
"shasum": ""
},
"require": {
- "doctrine/lexer": "1.*",
+ "doctrine/lexer": "^1 || ^2",
"ext-tokenizer": "*",
"php": "^7.1 || ^8.0",
"psr/cache": "^1 || ^2 || ^3"
},
"require-dev": {
"doctrine/cache": "^1.11 || ^2.0",
- "doctrine/coding-standard": "^6.0 || ^8.1",
- "phpstan/phpstan": "^1.4.10 || ^1.8.0",
- "phpunit/phpunit": "^7.5 || ^8.0 || ^9.1.5",
- "symfony/cache": "^4.4 || ^5.2",
+ "doctrine/coding-standard": "^9 || ^10",
+ "phpstan/phpstan": "~1.4.10 || ^1.8.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "symfony/cache": "^4.4 || ^5.4 || ^6",
"vimeo/psalm": "^4.10"
},
+ "suggest": {
+ "php": "PHP 8.0 or higher comes with attributes, a native replacement for annotations"
+ },
"type": "library",
"autoload": {
"psr-4": {
@@ -840,36 +1254,79 @@
],
"support": {
"issues": "https://github.com/doctrine/annotations/issues",
- "source": "https://github.com/doctrine/annotations/tree/1.13.3"
+ "source": "https://github.com/doctrine/annotations/tree/1.14.2"
},
- "time": "2022-07-02T10:48:51+00:00"
+ "time": "2022-12-15T06:48:22+00:00"
},
{
- "name": "doctrine/instantiator",
- "version": "1.4.1",
+ "name": "doctrine/deprecations",
+ "version": "v1.0.0",
"source": {
"type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc"
+ "url": "https://github.com/doctrine/deprecations.git",
+ "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/10dcfce151b967d20fde1b34ae6640712c3891bc",
- "reference": "10dcfce151b967d20fde1b34ae6640712c3891bc",
+ "url": "https://api.github.com/repos/doctrine/deprecations/zipball/0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
+ "reference": "0e2a4f1f8cdfc7a92ec3b01c9334898c806b30de",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.1|^8.0"
+ },
+ "require-dev": {
+ "doctrine/coding-standard": "^9",
+ "phpunit/phpunit": "^7.5|^8.5|^9.5",
+ "psr/log": "^1|^2|^3"
+ },
+ "suggest": {
+ "psr/log": "Allows logging deprecations via PSR-3 logger implementation"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.",
+ "homepage": "https://www.doctrine-project.org/",
+ "support": {
+ "issues": "https://github.com/doctrine/deprecations/issues",
+ "source": "https://github.com/doctrine/deprecations/tree/v1.0.0"
+ },
+ "time": "2022-05-02T15:47:09+00:00"
+ },
+ {
+ "name": "doctrine/instantiator",
+ "version": "1.5.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/doctrine/instantiator.git",
+ "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
+ "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
- "doctrine/coding-standard": "^9",
+ "doctrine/coding-standard": "^9 || ^11",
"ext-pdo": "*",
"ext-phar": "*",
"phpbench/phpbench": "^0.16 || ^1",
"phpstan/phpstan": "^1.4",
"phpstan/phpstan-phpunit": "^1",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.22"
+ "vimeo/psalm": "^4.30 || ^5.4"
},
"type": "library",
"autoload": {
@@ -896,7 +1353,7 @@
],
"support": {
"issues": "https://github.com/doctrine/instantiator/issues",
- "source": "https://github.com/doctrine/instantiator/tree/1.4.1"
+ "source": "https://github.com/doctrine/instantiator/tree/1.5.0"
},
"funding": [
{
@@ -912,35 +1369,37 @@
"type": "tidelift"
}
],
- "time": "2022-03-03T08:28:38+00:00"
+ "time": "2022-12-30T00:15:36+00:00"
},
{
"name": "doctrine/lexer",
- "version": "1.2.3",
+ "version": "2.1.0",
"source": {
"type": "git",
"url": "https://github.com/doctrine/lexer.git",
- "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229"
+ "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/doctrine/lexer/zipball/c268e882d4dbdd85e36e4ad69e02dc284f89d229",
- "reference": "c268e882d4dbdd85e36e4ad69e02dc284f89d229",
+ "url": "https://api.github.com/repos/doctrine/lexer/zipball/39ab8fcf5a51ce4b85ca97c7a7d033eb12831124",
+ "reference": "39ab8fcf5a51ce4b85ca97c7a7d033eb12831124",
"shasum": ""
},
"require": {
+ "doctrine/deprecations": "^1.0",
"php": "^7.1 || ^8.0"
},
"require-dev": {
- "doctrine/coding-standard": "^9.0",
+ "doctrine/coding-standard": "^9 || ^10",
"phpstan/phpstan": "^1.3",
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.11"
+ "psalm/plugin-phpunit": "^0.18.3",
+ "vimeo/psalm": "^4.11 || ^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
- "Doctrine\\Common\\Lexer\\": "lib/Doctrine/Common/Lexer"
+ "Doctrine\\Common\\Lexer\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -972,7 +1431,7 @@
],
"support": {
"issues": "https://github.com/doctrine/lexer/issues",
- "source": "https://github.com/doctrine/lexer/tree/1.2.3"
+ "source": "https://github.com/doctrine/lexer/tree/2.1.0"
},
"funding": [
{
@@ -988,39 +1447,39 @@
"type": "tidelift"
}
],
- "time": "2022-02-28T11:07:21+00:00"
+ "time": "2022-12-14T08:49:07+00:00"
},
{
"name": "ergebnis/composer-normalize",
- "version": "2.28.3",
+ "version": "2.29.0",
"source": {
"type": "git",
"url": "https://github.com/ergebnis/composer-normalize.git",
- "reference": "ec75a2bf751f6fec165e9ea0262655b8ca397e5c"
+ "reference": "fad0e99b16c625817a5bfd910e4d7e31999c53b2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/ec75a2bf751f6fec165e9ea0262655b8ca397e5c",
- "reference": "ec75a2bf751f6fec165e9ea0262655b8ca397e5c",
+ "url": "https://api.github.com/repos/ergebnis/composer-normalize/zipball/fad0e99b16c625817a5bfd910e4d7e31999c53b2",
+ "reference": "fad0e99b16c625817a5bfd910e4d7e31999c53b2",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0.0",
"ergebnis/json-normalizer": "~2.1.0",
- "ergebnis/json-printer": "^3.2.0",
+ "ergebnis/json-printer": "^3.3.0",
"justinrainbow/json-schema": "^5.2.12",
"localheinz/diff": "^1.1.1",
- "php": "^7.4 || ^8.0"
+ "php": "^8.0"
},
"require-dev": {
- "composer/composer": "^2.3.9",
- "ergebnis/license": "^1.2.0",
- "ergebnis/php-cs-fixer-config": "^4.4.0",
- "fakerphp/faker": "^1.19.0",
- "phpunit/phpunit": "^9.5.21",
- "psalm/plugin-phpunit": "~0.17.0",
- "symfony/filesystem": "^5.4.9",
- "vimeo/psalm": "^4.24.0"
+ "composer/composer": "^2.4.4",
+ "ergebnis/license": "^2.1.0",
+ "ergebnis/php-cs-fixer-config": "^5.0.0",
+ "fakerphp/faker": "^1.20.0",
+ "phpunit/phpunit": "^9.5.26",
+ "psalm/plugin-phpunit": "~0.18.3",
+ "symfony/filesystem": "^6.0.13",
+ "vimeo/psalm": "^5.0.0"
},
"type": "composer-plugin",
"extra": {
@@ -1057,7 +1516,7 @@
"issues": "https://github.com/ergebnis/composer-normalize/issues",
"source": "https://github.com/ergebnis/composer-normalize"
},
- "time": "2022-07-05T16:09:10+00:00"
+ "time": "2022-12-01T11:51:19+00:00"
},
{
"name": "ergebnis/json-normalizer",
@@ -1126,31 +1585,31 @@
},
{
"name": "ergebnis/json-printer",
- "version": "3.2.0",
+ "version": "3.3.0",
"source": {
"type": "git",
"url": "https://github.com/ergebnis/json-printer.git",
- "reference": "651cab2b7604a6b338d0d16749f5ea0851a68005"
+ "reference": "18920367473b099633f644f0ca6dc8794345148f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/651cab2b7604a6b338d0d16749f5ea0851a68005",
- "reference": "651cab2b7604a6b338d0d16749f5ea0851a68005",
+ "url": "https://api.github.com/repos/ergebnis/json-printer/zipball/18920367473b099633f644f0ca6dc8794345148f",
+ "reference": "18920367473b099633f644f0ca6dc8794345148f",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
- "php": "^7.4 || ^8.0"
+ "php": "^8.0"
},
"require-dev": {
- "ergebnis/license": "^1.1.0",
- "ergebnis/php-cs-fixer-config": "^3.4.0",
- "fakerphp/faker": "^1.17.0",
- "infection/infection": "~0.25.5",
- "phpunit/phpunit": "^9.5.11",
- "psalm/plugin-phpunit": "~0.16.1",
- "vimeo/psalm": "^4.16.1"
+ "ergebnis/license": "^2.0.0",
+ "ergebnis/php-cs-fixer-config": "^4.11.0",
+ "fakerphp/faker": "^1.20.0",
+ "infection/infection": "~0.26.6",
+ "phpunit/phpunit": "^9.5.26",
+ "psalm/plugin-phpunit": "~0.18.3",
+ "vimeo/psalm": "^4.30.0"
},
"type": "library",
"autoload": {
@@ -1179,13 +1638,7 @@
"issues": "https://github.com/ergebnis/json-printer/issues",
"source": "https://github.com/ergebnis/json-printer"
},
- "funding": [
- {
- "url": "https://github.com/localheinz",
- "type": "github"
- }
- ],
- "time": "2021-12-27T12:39:13+00:00"
+ "time": "2022-11-28T10:27:43+00:00"
},
{
"name": "ergebnis/json-schema-validator",
@@ -1673,16 +2126,16 @@
},
{
"name": "netresearch/jsonmapper",
- "version": "v4.0.0",
+ "version": "v4.1.0",
"source": {
"type": "git",
"url": "https://github.com/cweiske/jsonmapper.git",
- "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d"
+ "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
- "reference": "8bbc021a8edb2e4a7ea2f8ad4fa9ec9dce2fcb8d",
+ "url": "https://api.github.com/repos/cweiske/jsonmapper/zipball/cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
+ "reference": "cfa81ea1d35294d64adb9c68aa4cb9e92400e53f",
"shasum": ""
},
"require": {
@@ -1718,22 +2171,22 @@
"support": {
"email": "cweiske@cweiske.de",
"issues": "https://github.com/cweiske/jsonmapper/issues",
- "source": "https://github.com/cweiske/jsonmapper/tree/v4.0.0"
+ "source": "https://github.com/cweiske/jsonmapper/tree/v4.1.0"
},
- "time": "2020-12-01T19:48:11+00:00"
+ "time": "2022-12-08T20:46:14+00:00"
},
{
"name": "nikic/php-parser",
- "version": "v4.15.1",
+ "version": "v4.15.2",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
- "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900"
+ "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
- "reference": "0ef6c55a3f47f89d7a374e6f835197a0b5fcf900",
+ "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
+ "reference": "f59bbe44bf7d96f24f3e2b4ddc21cd52c1d2adbc",
"shasum": ""
},
"require": {
@@ -1774,9 +2227,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
- "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.1"
+ "source": "https://github.com/nikic/PHP-Parser/tree/v4.15.2"
},
- "time": "2022-09-04T07:30:47+00:00"
+ "time": "2022-11-12T15:38:23+00:00"
},
{
"name": "openlss/lib-array2xml",
@@ -2293,16 +2746,16 @@
},
{
"name": "phpbench/phpbench",
- "version": "1.2.6",
+ "version": "1.2.7",
"source": {
"type": "git",
"url": "https://github.com/phpbench/phpbench.git",
- "reference": "c30fac992e72b505a1f131790583647f4d3255c3"
+ "reference": "dce145304abbb16c8d9af69c19d96f47e9d0e670"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpbench/phpbench/zipball/c30fac992e72b505a1f131790583647f4d3255c3",
- "reference": "c30fac992e72b505a1f131790583647f4d3255c3",
+ "url": "https://api.github.com/repos/phpbench/phpbench/zipball/dce145304abbb16c8d9af69c19d96f47e9d0e670",
+ "reference": "dce145304abbb16c8d9af69c19d96f47e9d0e670",
"shasum": ""
},
"require": {
@@ -2323,14 +2776,16 @@
"symfony/finder": "^4.2 || ^5.0 || ^6.0",
"symfony/options-resolver": "^4.2 || ^5.0 || ^6.0",
"symfony/process": "^4.2 || ^5.0 || ^6.0",
- "webmozart/path-util": "^2.3"
+ "webmozart/glob": "^4.6"
},
"require-dev": {
"dantleech/invoke": "^2.0",
"friendsofphp/php-cs-fixer": "^3.0",
- "jangregor/phpstan-prophecy": "^0.8.1",
+ "jangregor/phpstan-prophecy": "^1.0",
"phpspec/prophecy": "^1.12",
- "phpstan/phpstan": "^0.12.7",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.0",
+ "phpstan/phpstan-phpunit": "^1.0",
"phpunit/phpunit": "^8.5.8 || ^9.0",
"symfony/error-handler": "^5.2 || ^6.0",
"symfony/var-dumper": "^4.0 || ^5.0 || ^6.0"
@@ -2369,7 +2824,7 @@
"description": "PHP Benchmarking Framework",
"support": {
"issues": "https://github.com/phpbench/phpbench/issues",
- "source": "https://github.com/phpbench/phpbench/tree/1.2.6"
+ "source": "https://github.com/phpbench/phpbench/tree/1.2.7"
},
"funding": [
{
@@ -2377,7 +2832,7 @@
"type": "github"
}
],
- "time": "2022-07-19T19:52:39+00:00"
+ "time": "2022-10-15T09:57:51+00:00"
},
{
"name": "phpdocumentor/reflection-common",
@@ -2491,25 +2946,30 @@
},
{
"name": "phpdocumentor/type-resolver",
- "version": "1.6.1",
+ "version": "1.6.2",
"source": {
"type": "git",
"url": "https://github.com/phpDocumentor/TypeResolver.git",
- "reference": "77a32518733312af16a44300404e945338981de3"
+ "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/77a32518733312af16a44300404e945338981de3",
- "reference": "77a32518733312af16a44300404e945338981de3",
+ "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
+ "reference": "48f445a408c131e38cab1c235aa6d2bb7a0bb20d",
"shasum": ""
},
"require": {
- "php": "^7.2 || ^8.0",
+ "php": "^7.4 || ^8.0",
"phpdocumentor/reflection-common": "^2.0"
},
"require-dev": {
"ext-tokenizer": "*",
- "psalm/phar": "^4.8"
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.8",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "phpunit/phpunit": "^9.5",
+ "rector/rector": "^0.13.9",
+ "vimeo/psalm": "^4.25"
},
"type": "library",
"extra": {
@@ -2535,34 +2995,33 @@
"description": "A PSR-5 based resolver of Class names, Types and Structural Element Names",
"support": {
"issues": "https://github.com/phpDocumentor/TypeResolver/issues",
- "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1"
+ "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.2"
},
- "time": "2022-03-15T21:29:03+00:00"
+ "time": "2022-10-14T12:47:21+00:00"
},
{
"name": "phpstan/extension-installer",
- "version": "1.1.0",
+ "version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
- "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051"
+ "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/66c7adc9dfa38b6b5838a9fb728b68a7d8348051",
- "reference": "66c7adc9dfa38b6b5838a9fb728b68a7d8348051",
+ "url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
+ "reference": "f06dbb052ddc394e7896fcd1cfcd533f9f6ace40",
"shasum": ""
},
"require": {
- "composer-plugin-api": "^1.1 || ^2.0",
- "php": "^7.1 || ^8.0",
- "phpstan/phpstan": ">=0.11.6"
+ "composer-plugin-api": "^2.0",
+ "php": "^7.2 || ^8.0",
+ "phpstan/phpstan": "^1.8.0"
},
"require-dev": {
- "composer/composer": "^1.8",
- "phing/phing": "^2.16.3",
+ "composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
- "phpstan/phpstan-strict-rules": "^0.11 || ^0.12"
+ "phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"type": "composer-plugin",
"extra": {
@@ -2580,22 +3039,22 @@
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
- "source": "https://github.com/phpstan/extension-installer/tree/1.1.0"
+ "source": "https://github.com/phpstan/extension-installer/tree/1.2.0"
},
- "time": "2020-12-13T13:06:13+00:00"
+ "time": "2022-10-17T12:59:16+00:00"
},
{
"name": "phpstan/phpdoc-parser",
- "version": "1.7.0",
+ "version": "1.15.3",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpdoc-parser.git",
- "reference": "367a8d9d5f7da2a0136422d27ce8840583926955"
+ "reference": "61800f71a5526081d1b5633766aa88341f1ade76"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/367a8d9d5f7da2a0136422d27ce8840583926955",
- "reference": "367a8d9d5f7da2a0136422d27ce8840583926955",
+ "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/61800f71a5526081d1b5633766aa88341f1ade76",
+ "reference": "61800f71a5526081d1b5633766aa88341f1ade76",
"shasum": ""
},
"require": {
@@ -2625,22 +3084,22 @@
"description": "PHPDoc parser with support for nullable, intersection and generic types",
"support": {
"issues": "https://github.com/phpstan/phpdoc-parser/issues",
- "source": "https://github.com/phpstan/phpdoc-parser/tree/1.7.0"
+ "source": "https://github.com/phpstan/phpdoc-parser/tree/1.15.3"
},
- "time": "2022-08-09T12:23:23+00:00"
+ "time": "2022-12-20T20:56:55+00:00"
},
{
"name": "phpstan/phpstan",
- "version": "1.8.5",
+ "version": "1.9.4",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20"
+ "reference": "d03bccee595e2146b7c9d174486b84f4dc61b0f2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/f6598a5ff12ca4499a836815e08b4d77a2ddeb20",
- "reference": "f6598a5ff12ca4499a836815e08b4d77a2ddeb20",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d03bccee595e2146b7c9d174486b84f4dc61b0f2",
+ "reference": "d03bccee595e2146b7c9d174486b84f4dc61b0f2",
"shasum": ""
},
"require": {
@@ -2670,7 +3129,7 @@
],
"support": {
"issues": "https://github.com/phpstan/phpstan/issues",
- "source": "https://github.com/phpstan/phpstan/tree/1.8.5"
+ "source": "https://github.com/phpstan/phpstan/tree/1.9.4"
},
"funding": [
{
@@ -2686,7 +3145,7 @@
"type": "tidelift"
}
],
- "time": "2022-09-07T16:05:32+00:00"
+ "time": "2022-12-17T13:33:52+00:00"
},
{
"name": "phpstan/phpstan-mockery",
@@ -2740,21 +3199,21 @@
},
{
"name": "phpstan/phpstan-phpunit",
- "version": "1.1.1",
+ "version": "1.3.3",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
- "reference": "4a3c437c09075736285d1cabb5c75bf27ed0bc84"
+ "reference": "54a24bd23e9e80ee918cdc24f909d376c2e273f7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/4a3c437c09075736285d1cabb5c75bf27ed0bc84",
- "reference": "4a3c437c09075736285d1cabb5c75bf27ed0bc84",
+ "url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/54a24bd23e9e80ee918cdc24f909d376c2e273f7",
+ "reference": "54a24bd23e9e80ee918cdc24f909d376c2e273f7",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0",
- "phpstan/phpstan": "^1.5.0"
+ "phpstan/phpstan": "^1.9.3"
},
"conflict": {
"phpunit/phpunit": "<7.0"
@@ -2786,22 +3245,22 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
- "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.1.1"
+ "source": "https://github.com/phpstan/phpstan-phpunit/tree/1.3.3"
},
- "time": "2022-04-20T15:24:25+00:00"
+ "time": "2022-12-21T15:25:00+00:00"
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.17",
+ "version": "9.2.23",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8"
+ "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/aa94dc41e8661fe90c7316849907cba3007b10d8",
- "reference": "aa94dc41e8661fe90c7316849907cba3007b10d8",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
+ "reference": "9f1f0f9a2fbb680b26d1cf9b61b6eac43a6e4e9c",
"shasum": ""
},
"require": {
@@ -2857,7 +3316,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.17"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.23"
},
"funding": [
{
@@ -2865,7 +3324,7 @@
"type": "github"
}
],
- "time": "2022-08-30T12:24:04+00:00"
+ "time": "2022-12-28T12:41:10+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -3110,16 +3569,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "9.5.24",
+ "version": "9.5.27",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5"
+ "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
- "reference": "d0aa6097bef9fd42458a9b3c49da32c6ce6129c5",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a2bc7ffdca99f92d959b3f2270529334030bba38",
+ "reference": "a2bc7ffdca99f92d959b3f2270529334030bba38",
"shasum": ""
},
"require": {
@@ -3141,14 +3600,14 @@
"phpunit/php-timer": "^5.0.2",
"sebastian/cli-parser": "^1.0.1",
"sebastian/code-unit": "^1.0.6",
- "sebastian/comparator": "^4.0.5",
+ "sebastian/comparator": "^4.0.8",
"sebastian/diff": "^4.0.3",
"sebastian/environment": "^5.1.3",
- "sebastian/exporter": "^4.0.3",
+ "sebastian/exporter": "^4.0.5",
"sebastian/global-state": "^5.0.1",
"sebastian/object-enumerator": "^4.0.3",
"sebastian/resource-operations": "^3.0.3",
- "sebastian/type": "^3.1",
+ "sebastian/type": "^3.2",
"sebastian/version": "^3.0.2"
},
"suggest": {
@@ -3192,7 +3651,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.24"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.27"
},
"funding": [
{
@@ -3202,9 +3661,13 @@
{
"url": "https://github.com/sebastianbergmann",
"type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
+ "type": "tidelift"
}
],
- "time": "2022-08-30T07:42:16+00:00"
+ "time": "2022-12-09T07:31:23+00:00"
},
{
"name": "psalm/plugin-phpunit",
@@ -3418,6 +3881,322 @@
},
"time": "2021-07-14T16:46:02+00:00"
},
+ {
+ "name": "psy/psysh",
+ "version": "v0.11.10",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/bobthecow/psysh.git",
+ "reference": "e9eadffbed9c9deb5426fd107faae0452bf20a36"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/bobthecow/psysh/zipball/e9eadffbed9c9deb5426fd107faae0452bf20a36",
+ "reference": "e9eadffbed9c9deb5426fd107faae0452bf20a36",
+ "shasum": ""
+ },
+ "require": {
+ "ext-json": "*",
+ "ext-tokenizer": "*",
+ "nikic/php-parser": "^4.0 || ^3.1",
+ "php": "^8.0 || ^7.0.8",
+ "symfony/console": "^6.0 || ^5.0 || ^4.0 || ^3.4",
+ "symfony/var-dumper": "^6.0 || ^5.0 || ^4.0 || ^3.4"
+ },
+ "conflict": {
+ "symfony/console": "4.4.37 || 5.3.14 || 5.3.15 || 5.4.3 || 5.4.4 || 6.0.3 || 6.0.4"
+ },
+ "require-dev": {
+ "bamarni/composer-bin-plugin": "^1.2"
+ },
+ "suggest": {
+ "ext-pcntl": "Enabling the PCNTL extension makes PsySH a lot happier :)",
+ "ext-pdo-sqlite": "The doc command requires SQLite to work.",
+ "ext-posix": "If you have PCNTL, you'll want the POSIX extension as well.",
+ "ext-readline": "Enables support for arrow-key history navigation, and showing and manipulating command history."
+ },
+ "bin": [
+ "bin/psysh"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "0.11.x-dev"
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/functions.php"
+ ],
+ "psr-4": {
+ "Psy\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Justin Hileman",
+ "email": "justin@justinhileman.info",
+ "homepage": "http://justinhileman.com"
+ }
+ ],
+ "description": "An interactive shell for modern PHP.",
+ "homepage": "http://psysh.org",
+ "keywords": [
+ "REPL",
+ "console",
+ "interactive",
+ "shell"
+ ],
+ "support": {
+ "issues": "https://github.com/bobthecow/psysh/issues",
+ "source": "https://github.com/bobthecow/psysh/tree/v0.11.10"
+ },
+ "time": "2022-12-23T17:47:18+00:00"
+ },
+ {
+ "name": "ramsey/composer-repl",
+ "version": "1.4.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/composer-repl.git",
+ "reference": "24553610c07df626c7dfd44ef328b7ae3349366f"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/composer-repl/zipball/24553610c07df626c7dfd44ef328b7ae3349366f",
+ "reference": "24553610c07df626c7dfd44ef328b7ae3349366f",
+ "shasum": ""
+ },
+ "require": {
+ "composer-plugin-api": "^2",
+ "php": "^7.4 || ^8",
+ "ramsey/composer-repl-lib": "^1.1"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.10",
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.25",
+ "roave/security-advisories": "dev-latest"
+ },
+ "type": "composer-plugin",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ },
+ "captainhook": {
+ "force-install": true
+ },
+ "class": "Ramsey\\Dev\\Repl\\Composer\\ReplPlugin",
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ },
+ "ramsey/devtools": {
+ "command-prefix": "dev"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "description": "A REPL for PHP built into Composer.",
+ "keywords": [
+ "REPL",
+ "psysh",
+ "shell"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/composer-repl/issues",
+ "source": "https://github.com/ramsey/composer-repl/tree/1.4.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/ramsey",
+ "type": "github"
+ }
+ ],
+ "time": "2022-04-17T02:07:54+00:00"
+ },
+ {
+ "name": "ramsey/composer-repl-lib",
+ "version": "1.1.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/ramsey/composer-repl-lib.git",
+ "reference": "53f7666f1f4b49711741ad22b633671a312a6fdc"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/ramsey/composer-repl-lib/zipball/53f7666f1f4b49711741ad22b633671a312a6fdc",
+ "reference": "53f7666f1f4b49711741ad22b633671a312a6fdc",
+ "shasum": ""
+ },
+ "require": {
+ "composer/composer": "^2.1.9",
+ "php": "^7.4 || ^8",
+ "phpunit/phpunit": "^6 || ^7 || ^8 || ^9",
+ "psy/psysh": "^0.11.0",
+ "symfony/console": "^4.4.30 || ^5.3.7 || ^6",
+ "symfony/process": "^4.4.30 || ^5.3.7 || ^6"
+ },
+ "require-dev": {
+ "captainhook/captainhook": "^5.10",
+ "captainhook/plugin-composer": "^5.3",
+ "ergebnis/composer-normalize": "^2.25",
+ "hamcrest/hamcrest-php": "^2.0",
+ "mockery/mockery": "^1.5",
+ "php-parallel-lint/php-console-highlighter": "^1.0",
+ "php-parallel-lint/php-parallel-lint": "^1.3",
+ "phpstan/extension-installer": "^1.1",
+ "phpstan/phpstan": "^1.5",
+ "phpstan/phpstan-mockery": "^1.0",
+ "phpstan/phpstan-phpunit": "^1.1",
+ "psalm/plugin-mockery": "^0.9.1",
+ "psalm/plugin-phpunit": "^0.16.1",
+ "ramsey/coding-standard": "^2.0.3",
+ "roave/security-advisories": "dev-latest",
+ "vimeo/psalm": "^4.22"
+ },
+ "bin": [
+ "bin/repl"
+ ],
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.x-dev"
+ },
+ "captainhook": {
+ "force-install": true
+ },
+ "ramsey/composer-repl": {
+ "includes": [
+ "repl.php"
+ ]
+ },
+ "ramsey/conventional-commits": {
+ "configFile": "conventional-commits.json"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Ramsey\\Dev\\Repl\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Ben Ramsey",
+ "email": "ben@benramsey.com",
+ "homepage": "https://benramsey.com"
+ }
+ ],
+ "description": "The library behind ramsey/composer-repl, allowing for extension of the ramsey/composer-repl Composer plugin and non-plugin use of the repl command.",
+ "keywords": [
+ "REPL",
+ "psysh",
+ "shell"
+ ],
+ "support": {
+ "issues": "https://github.com/ramsey/composer-repl-lib/issues",
+ "source": "https://github.com/ramsey/composer-repl-lib/tree/1.1.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/ramsey",
+ "type": "github"
+ }
+ ],
+ "time": "2022-04-17T01:54:57+00:00"
+ },
+ {
+ "name": "react/promise",
+ "version": "v2.9.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/reactphp/promise.git",
+ "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/reactphp/promise/zipball/234f8fd1023c9158e2314fa9d7d0e6a83db42910",
+ "reference": "234f8fd1023c9158e2314fa9d7d0e6a83db42910",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.4.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.3 || ^5.7 || ^4.8.36"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/functions_include.php"
+ ],
+ "psr-4": {
+ "React\\Promise\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jan Sorgalla",
+ "email": "jsorgalla@gmail.com",
+ "homepage": "https://sorgalla.com/"
+ },
+ {
+ "name": "Christian Lück",
+ "email": "christian@clue.engineering",
+ "homepage": "https://clue.engineering/"
+ },
+ {
+ "name": "Cees-Jan Kiewiet",
+ "email": "reactphp@ceesjankiewiet.nl",
+ "homepage": "https://wyrihaximus.net/"
+ },
+ {
+ "name": "Chris Boden",
+ "email": "cboden@gmail.com",
+ "homepage": "https://cboden.dev/"
+ }
+ ],
+ "description": "A lightweight implementation of CommonJS Promises/A for PHP",
+ "keywords": [
+ "promise",
+ "promises"
+ ],
+ "support": {
+ "issues": "https://github.com/reactphp/promise/issues",
+ "source": "https://github.com/reactphp/promise/tree/v2.9.0"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/WyriHaximus",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/clue",
+ "type": "github"
+ }
+ ],
+ "time": "2022-02-11T10:27:51+00:00"
+ },
{
"name": "sebastian/cli-parser",
"version": "1.0.1",
@@ -3587,16 +4366,16 @@
},
{
"name": "sebastian/comparator",
- "version": "4.0.6",
+ "version": "4.0.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382"
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55f4261989e546dc112258c7a75935a81a7ce382",
- "reference": "55f4261989e546dc112258c7a75935a81a7ce382",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
+ "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
"shasum": ""
},
"require": {
@@ -3649,7 +4428,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.6"
+ "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
},
"funding": [
{
@@ -3657,7 +4436,7 @@
"type": "github"
}
],
- "time": "2020-10-26T15:49:45+00:00"
+ "time": "2022-09-14T12:41:17+00:00"
},
{
"name": "sebastian/complexity",
@@ -3847,16 +4626,16 @@
},
{
"name": "sebastian/exporter",
- "version": "4.0.4",
+ "version": "4.0.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9"
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/65e8b7db476c5dd267e65eea9cab77584d3cfff9",
- "reference": "65e8b7db476c5dd267e65eea9cab77584d3cfff9",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
+ "reference": "ac230ed27f0f98f597c8a2b6eb7ac563af5e5b9d",
"shasum": ""
},
"require": {
@@ -3912,7 +4691,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.4"
+ "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.5"
},
"funding": [
{
@@ -3920,7 +4699,7 @@
"type": "github"
}
],
- "time": "2021-11-11T14:18:36+00:00"
+ "time": "2022-09-14T06:03:37+00:00"
},
{
"name": "sebastian/global-state",
@@ -4498,16 +5277,16 @@
},
{
"name": "sebastianfeldmann/git",
- "version": "3.8.4",
+ "version": "3.8.5",
"source": {
"type": "git",
"url": "https://github.com/sebastianfeldmann/git.git",
- "reference": "b324b6ba21871709812e34ad278a82c2e1c2965b"
+ "reference": "14de823cba82e30a3759e9eab1ebbd0d6f5d542c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/b324b6ba21871709812e34ad278a82c2e1c2965b",
- "reference": "b324b6ba21871709812e34ad278a82c2e1c2965b",
+ "url": "https://api.github.com/repos/sebastianfeldmann/git/zipball/14de823cba82e30a3759e9eab1ebbd0d6f5d542c",
+ "reference": "14de823cba82e30a3759e9eab1ebbd0d6f5d542c",
"shasum": ""
},
"require": {
@@ -4547,7 +5326,7 @@
],
"support": {
"issues": "https://github.com/sebastianfeldmann/git/issues",
- "source": "https://github.com/sebastianfeldmann/git/tree/3.8.4"
+ "source": "https://github.com/sebastianfeldmann/git/tree/3.8.5"
},
"funding": [
{
@@ -4555,7 +5334,7 @@
"type": "github"
}
],
- "time": "2022-08-26T07:03:13+00:00"
+ "time": "2022-10-23T11:29:41+00:00"
},
{
"name": "seld/jsonlint",
@@ -4622,33 +5401,142 @@
"time": "2022-04-01T13:37:23+00:00"
},
{
- "name": "slevomat/coding-standard",
- "version": "8.4.0",
+ "name": "seld/phar-utils",
+ "version": "1.2.1",
"source": {
"type": "git",
- "url": "https://github.com/slevomat/coding-standard.git",
- "reference": "02f27326be19633a1b6ba76745390bbf9a4be0b6"
+ "url": "https://github.com/Seldaek/phar-utils.git",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/02f27326be19633a1b6ba76745390bbf9a4be0b6",
- "reference": "02f27326be19633a1b6ba76745390bbf9a4be0b6",
+ "url": "https://api.github.com/repos/Seldaek/phar-utils/zipball/ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
+ "reference": "ea2f4014f163c1be4c601b9b7bd6af81ba8d701c",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=5.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Seld\\PharUtils\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be"
+ }
+ ],
+ "description": "PHAR file format utilities, for when PHP phars you up",
+ "keywords": [
+ "phar"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/phar-utils/issues",
+ "source": "https://github.com/Seldaek/phar-utils/tree/1.2.1"
+ },
+ "time": "2022-08-31T10:31:18+00:00"
+ },
+ {
+ "name": "seld/signal-handler",
+ "version": "2.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/Seldaek/signal-handler.git",
+ "reference": "f69d119511dc0360440cdbdaa71829c149b7be75"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/Seldaek/signal-handler/zipball/f69d119511dc0360440cdbdaa71829c149b7be75",
+ "reference": "f69d119511dc0360440cdbdaa71829c149b7be75",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.2.0"
+ },
+ "require-dev": {
+ "phpstan/phpstan": "^1",
+ "phpstan/phpstan-deprecation-rules": "^1.0",
+ "phpstan/phpstan-phpunit": "^1",
+ "phpstan/phpstan-strict-rules": "^1.3",
+ "phpunit/phpunit": "^7.5.20 || ^8.5.23",
+ "psr/log": "^1 || ^2 || ^3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.x-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Seld\\Signal\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Jordi Boggiano",
+ "email": "j.boggiano@seld.be",
+ "homepage": "http://seld.be"
+ }
+ ],
+ "description": "Simple unix signal handler that silently fails where signals are not supported for easy cross-platform development",
+ "keywords": [
+ "posix",
+ "sigint",
+ "signal",
+ "sigterm",
+ "unix"
+ ],
+ "support": {
+ "issues": "https://github.com/Seldaek/signal-handler/issues",
+ "source": "https://github.com/Seldaek/signal-handler/tree/2.0.1"
+ },
+ "time": "2022-07-20T18:31:45+00:00"
+ },
+ {
+ "name": "slevomat/coding-standard",
+ "version": "8.7.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/slevomat/coding-standard.git",
+ "reference": "c51edb898bebd36aac70a190c6a41a7c056bb5b9"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/c51edb898bebd36aac70a190c6a41a7c056bb5b9",
+ "reference": "c51edb898bebd36aac70a190c6a41a7c056bb5b9",
"shasum": ""
},
"require": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7",
"php": "^7.2 || ^8.0",
- "phpstan/phpdoc-parser": ">=1.7.0 <1.8.0",
+ "phpstan/phpdoc-parser": ">=1.15.0 <1.16.0",
"squizlabs/php_codesniffer": "^3.7.1"
},
"require-dev": {
"phing/phing": "2.17.4",
"php-parallel-lint/php-parallel-lint": "1.3.2",
- "phpstan/phpstan": "1.4.10|1.8.2",
- "phpstan/phpstan-deprecation-rules": "1.0.0",
- "phpstan/phpstan-phpunit": "1.0.0|1.1.1",
- "phpstan/phpstan-strict-rules": "1.3.0",
- "phpunit/phpunit": "7.5.20|8.5.21|9.5.21"
+ "phpstan/phpstan": "1.4.10|1.9.3",
+ "phpstan/phpstan-deprecation-rules": "1.1.0",
+ "phpstan/phpstan-phpunit": "1.0.0|1.3.1",
+ "phpstan/phpstan-strict-rules": "1.4.4",
+ "phpunit/phpunit": "7.5.20|8.5.21|9.5.27"
},
"type": "phpcodesniffer-standard",
"extra": {
@@ -4666,9 +5554,13 @@
"MIT"
],
"description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.",
+ "keywords": [
+ "dev",
+ "phpcs"
+ ],
"support": {
"issues": "https://github.com/slevomat/coding-standard/issues",
- "source": "https://github.com/slevomat/coding-standard/tree/8.4.0"
+ "source": "https://github.com/slevomat/coding-standard/tree/8.7.1"
},
"funding": [
{
@@ -4680,7 +5572,7 @@
"type": "tidelift"
}
],
- "time": "2022-08-09T19:03:45+00:00"
+ "time": "2022-12-14T08:49:18+00:00"
},
{
"name": "squizlabs/php_codesniffer",
@@ -4740,16 +5632,16 @@
},
{
"name": "symfony/console",
- "version": "v6.1.4",
+ "version": "v6.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d"
+ "reference": "0f579613e771dba2dbb8211c382342a641f5da06"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/7fccea8728aa2d431a6725b02b3ce759049fc84d",
- "reference": "7fccea8728aa2d431a6725b02b3ce759049fc84d",
+ "url": "https://api.github.com/repos/symfony/console/zipball/0f579613e771dba2dbb8211c382342a641f5da06",
+ "reference": "0f579613e771dba2dbb8211c382342a641f5da06",
"shasum": ""
},
"require": {
@@ -4816,7 +5708,7 @@
"terminal"
],
"support": {
- "source": "https://github.com/symfony/console/tree/v6.1.4"
+ "source": "https://github.com/symfony/console/tree/v6.2.3"
},
"funding": [
{
@@ -4832,20 +5724,20 @@
"type": "tidelift"
}
],
- "time": "2022-08-26T10:32:31+00:00"
+ "time": "2022-12-28T14:26:22+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.1.1",
+ "version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918"
+ "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
- "reference": "07f1b9cc2ffee6aaafcf4b710fbc38ff736bd918",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/1ee04c65529dea5d8744774d474e7cbd2f1206d3",
+ "reference": "1ee04c65529dea5d8744774d474e7cbd2f1206d3",
"shasum": ""
},
"require": {
@@ -4854,7 +5746,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.1-dev"
+ "dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -4883,7 +5775,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.1.1"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.2.0"
},
"funding": [
{
@@ -4899,20 +5791,20 @@
"type": "tidelift"
}
],
- "time": "2022-02-25T11:15:52+00:00"
+ "time": "2022-11-25T10:21:52+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v6.1.4",
+ "version": "v6.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "3f39c04d2630c34019907b02f85672dac99f8659"
+ "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/3f39c04d2630c34019907b02f85672dac99f8659",
- "reference": "3f39c04d2630c34019907b02f85672dac99f8659",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/50b2523c874605cf3d4acf7a9e2b30b6a440a016",
+ "reference": "50b2523c874605cf3d4acf7a9e2b30b6a440a016",
"shasum": ""
},
"require": {
@@ -4946,7 +5838,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.1.4"
+ "source": "https://github.com/symfony/filesystem/tree/v6.2.0"
},
"funding": [
{
@@ -4962,20 +5854,20 @@
"type": "tidelift"
}
],
- "time": "2022-08-02T16:17:38+00:00"
+ "time": "2022-11-20T13:01:27+00:00"
},
{
"name": "symfony/finder",
- "version": "v6.1.3",
+ "version": "v6.2.3",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
- "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709"
+ "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/finder/zipball/39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
- "reference": "39696bff2c2970b3779a5cac7bf9f0b88fc2b709",
+ "url": "https://api.github.com/repos/symfony/finder/zipball/81eefbddfde282ee33b437ba5e13d7753211ae8e",
+ "reference": "81eefbddfde282ee33b437ba5e13d7753211ae8e",
"shasum": ""
},
"require": {
@@ -5010,7 +5902,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/finder/tree/v6.1.3"
+ "source": "https://github.com/symfony/finder/tree/v6.2.3"
},
"funding": [
{
@@ -5026,20 +5918,20 @@
"type": "tidelift"
}
],
- "time": "2022-07-29T07:42:06+00:00"
+ "time": "2022-12-22T17:55:15+00:00"
},
{
"name": "symfony/options-resolver",
- "version": "v6.1.0",
+ "version": "v6.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
- "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4"
+ "reference": "d28f02acde71ff75e957082cd36e973df395f626"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/options-resolver/zipball/a3016f5442e28386ded73c43a32a5b68586dd1c4",
- "reference": "a3016f5442e28386ded73c43a32a5b68586dd1c4",
+ "url": "https://api.github.com/repos/symfony/options-resolver/zipball/d28f02acde71ff75e957082cd36e973df395f626",
+ "reference": "d28f02acde71ff75e957082cd36e973df395f626",
"shasum": ""
},
"require": {
@@ -5077,7 +5969,7 @@
"options"
],
"support": {
- "source": "https://github.com/symfony/options-resolver/tree/v6.1.0"
+ "source": "https://github.com/symfony/options-resolver/tree/v6.2.0"
},
"funding": [
{
@@ -5093,20 +5985,20 @@
"type": "tidelift"
}
],
- "time": "2022-02-25T11:15:52+00:00"
+ "time": "2022-11-02T09:08:04+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.26.0",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
- "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4"
+ "reference": "5bbc823adecdae860bb64756d639ecfec17b050a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
- "reference": "6fd1b9a79f6e3cf65f9e679b23af304cd9e010d4",
+ "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a",
+ "reference": "5bbc823adecdae860bb64756d639ecfec17b050a",
"shasum": ""
},
"require": {
@@ -5121,7 +6013,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.26-dev"
+ "dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -5159,7 +6051,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.26.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0"
},
"funding": [
{
@@ -5175,20 +6067,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-24T11:49:31+00:00"
+ "time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-grapheme",
- "version": "v1.26.0",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
- "reference": "433d05519ce6990bf3530fba6957499d327395c2"
+ "reference": "511a08c03c1960e08a883f4cffcacd219b758354"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/433d05519ce6990bf3530fba6957499d327395c2",
- "reference": "433d05519ce6990bf3530fba6957499d327395c2",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354",
+ "reference": "511a08c03c1960e08a883f4cffcacd219b758354",
"shasum": ""
},
"require": {
@@ -5200,7 +6092,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.26-dev"
+ "dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -5240,7 +6132,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.26.0"
+ "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0"
},
"funding": [
{
@@ -5256,20 +6148,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-24T11:49:31+00:00"
+ "time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-intl-normalizer",
- "version": "v1.26.0",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git",
- "reference": "219aa369ceff116e673852dce47c3a41794c14bd"
+ "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/219aa369ceff116e673852dce47c3a41794c14bd",
- "reference": "219aa369ceff116e673852dce47c3a41794c14bd",
+ "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6",
+ "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6",
"shasum": ""
},
"require": {
@@ -5281,7 +6173,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.26-dev"
+ "dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -5324,7 +6216,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.26.0"
+ "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0"
},
"funding": [
{
@@ -5340,20 +6232,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-24T11:49:31+00:00"
+ "time": "2022-11-03T14:55:06+00:00"
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.26.0",
+ "version": "v1.27.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e"
+ "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
- "reference": "9344f9cb97f3b19424af1a21a3b0e75b0a7d8d7e",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
+ "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534",
"shasum": ""
},
"require": {
@@ -5368,7 +6260,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.26-dev"
+ "dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -5407,7 +6299,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.26.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0"
},
"funding": [
{
@@ -5423,20 +6315,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-24T11:49:31+00:00"
+ "time": "2022-11-03T14:55:06+00:00"
},
{
- "name": "symfony/polyfill-php80",
- "version": "v1.26.0",
+ "name": "symfony/polyfill-php73",
+ "version": "v1.27.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/polyfill-php80.git",
- "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace"
+ "url": "https://github.com/symfony/polyfill-php73.git",
+ "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/cfa0ae98841b9e461207c13ab093d76b0fa7bace",
- "reference": "cfa0ae98841b9e461207c13ab093d76b0fa7bace",
+ "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
+ "reference": "9e8ecb5f92152187c4799efd3c96b78ccab18ff9",
"shasum": ""
},
"require": {
@@ -5445,7 +6337,86 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "1.26-dev"
+ "dev-main": "1.27-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php73\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php73/tree/v1.27.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-11-03T14:55:06+00:00"
+ },
+ {
+ "name": "symfony/polyfill-php80",
+ "version": "v1.27.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/polyfill-php80.git",
+ "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
+ "reference": "7a6ff3f1959bb01aefccb463a0f2cd3d3d2fd936",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.27-dev"
},
"thanks": {
"name": "symfony/polyfill",
@@ -5490,7 +6461,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-php80/tree/v1.26.0"
+ "source": "https://github.com/symfony/polyfill-php80/tree/v1.27.0"
},
"funding": [
{
@@ -5506,20 +6477,99 @@
"type": "tidelift"
}
],
- "time": "2022-05-10T07:21:04+00:00"
+ "time": "2022-11-03T14:55:06+00:00"
},
{
- "name": "symfony/process",
- "version": "v6.1.3",
+ "name": "symfony/polyfill-php81",
+ "version": "v1.27.0",
"source": {
"type": "git",
- "url": "https://github.com/symfony/process.git",
- "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292"
+ "url": "https://github.com/symfony/polyfill-php81.git",
+ "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/process/zipball/a6506e99cfad7059b1ab5cab395854a0a0c21292",
- "reference": "a6506e99cfad7059b1ab5cab395854a0a0c21292",
+ "url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/707403074c8ea6e2edaf8794b0157a0bfa52157a",
+ "reference": "707403074c8ea6e2edaf8794b0157a0bfa52157a",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=7.1"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "1.27-dev"
+ },
+ "thanks": {
+ "name": "symfony/polyfill",
+ "url": "https://github.com/symfony/polyfill"
+ }
+ },
+ "autoload": {
+ "files": [
+ "bootstrap.php"
+ ],
+ "psr-4": {
+ "Symfony\\Polyfill\\Php81\\": ""
+ },
+ "classmap": [
+ "Resources/stubs"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "compatibility",
+ "polyfill",
+ "portable",
+ "shim"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/polyfill-php81/tree/v1.27.0"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-11-03T14:55:06+00:00"
+ },
+ {
+ "name": "symfony/process",
+ "version": "v6.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/process.git",
+ "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/process/zipball/ba6e55359f8f755fe996c58a81e00eaa67a35877",
+ "reference": "ba6e55359f8f755fe996c58a81e00eaa67a35877",
"shasum": ""
},
"require": {
@@ -5551,7 +6601,7 @@
"description": "Executes commands in sub-processes",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/process/tree/v6.1.3"
+ "source": "https://github.com/symfony/process/tree/v6.2.0"
},
"funding": [
{
@@ -5567,20 +6617,20 @@
"type": "tidelift"
}
],
- "time": "2022-06-27T17:24:16+00:00"
+ "time": "2022-11-02T09:08:04+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.1.1",
+ "version": "v3.2.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239"
+ "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/925e713fe8fcacf6bc05e936edd8dd5441a21239",
- "reference": "925e713fe8fcacf6bc05e936edd8dd5441a21239",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/aac98028c69df04ee77eb69b96b86ee51fbf4b75",
+ "reference": "aac98028c69df04ee77eb69b96b86ee51fbf4b75",
"shasum": ""
},
"require": {
@@ -5596,7 +6646,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "3.1-dev"
+ "dev-main": "3.3-dev"
},
"thanks": {
"name": "symfony/contracts",
@@ -5636,7 +6686,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.1.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.2.0"
},
"funding": [
{
@@ -5652,20 +6702,20 @@
"type": "tidelift"
}
],
- "time": "2022-05-30T19:18:58+00:00"
+ "time": "2022-11-25T10:21:52+00:00"
},
{
"name": "symfony/string",
- "version": "v6.1.4",
+ "version": "v6.2.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "290972cad7b364e3befaa74ba0ec729800fb161c"
+ "reference": "863219fd713fa41cbcd285a79723f94672faff4d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/290972cad7b364e3befaa74ba0ec729800fb161c",
- "reference": "290972cad7b364e3befaa74ba0ec729800fb161c",
+ "url": "https://api.github.com/repos/symfony/string/zipball/863219fd713fa41cbcd285a79723f94672faff4d",
+ "reference": "863219fd713fa41cbcd285a79723f94672faff4d",
"shasum": ""
},
"require": {
@@ -5681,6 +6731,7 @@
"require-dev": {
"symfony/error-handler": "^5.4|^6.0",
"symfony/http-client": "^5.4|^6.0",
+ "symfony/intl": "^6.2",
"symfony/translation-contracts": "^2.0|^3.0",
"symfony/var-exporter": "^5.4|^6.0"
},
@@ -5721,7 +6772,7 @@
"utf8"
],
"support": {
- "source": "https://github.com/symfony/string/tree/v6.1.4"
+ "source": "https://github.com/symfony/string/tree/v6.2.2"
},
"funding": [
{
@@ -5737,7 +6788,95 @@
"type": "tidelift"
}
],
- "time": "2022-08-12T18:05:43+00:00"
+ "time": "2022-12-14T16:11:27+00:00"
+ },
+ {
+ "name": "symfony/var-dumper",
+ "version": "v6.2.3",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/symfony/var-dumper.git",
+ "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/symfony/var-dumper/zipball/fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0",
+ "reference": "fdbadd4803bc3c96ef89238c9c9e2ebe424ec2e0",
+ "shasum": ""
+ },
+ "require": {
+ "php": ">=8.1",
+ "symfony/polyfill-mbstring": "~1.0"
+ },
+ "conflict": {
+ "phpunit/phpunit": "<5.4.3",
+ "symfony/console": "<5.4"
+ },
+ "require-dev": {
+ "ext-iconv": "*",
+ "symfony/console": "^5.4|^6.0",
+ "symfony/process": "^5.4|^6.0",
+ "symfony/uid": "^5.4|^6.0",
+ "twig/twig": "^2.13|^3.0.4"
+ },
+ "suggest": {
+ "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).",
+ "ext-intl": "To show region name in time zone dump",
+ "symfony/console": "To use the ServerDumpCommand and/or the bin/var-dump-server script"
+ },
+ "bin": [
+ "Resources/bin/var-dump-server"
+ ],
+ "type": "library",
+ "autoload": {
+ "files": [
+ "Resources/functions/dump.php"
+ ],
+ "psr-4": {
+ "Symfony\\Component\\VarDumper\\": ""
+ },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "description": "Provides mechanisms for walking through any arbitrary PHP variable",
+ "homepage": "https://symfony.com",
+ "keywords": [
+ "debug",
+ "dump"
+ ],
+ "support": {
+ "source": "https://github.com/symfony/var-dumper/tree/v6.2.3"
+ },
+ "funding": [
+ {
+ "url": "https://symfony.com/sponsor",
+ "type": "custom"
+ },
+ {
+ "url": "https://github.com/fabpot",
+ "type": "github"
+ },
+ {
+ "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+ "type": "tidelift"
+ }
+ ],
+ "time": "2022-12-22T17:55:15+00:00"
},
{
"name": "theseer/tokenizer",
@@ -5791,16 +6930,16 @@
},
{
"name": "vimeo/psalm",
- "version": "4.27.0",
+ "version": "4.30.0",
"source": {
"type": "git",
"url": "https://github.com/vimeo/psalm.git",
- "reference": "faf106e717c37b8c81721845dba9de3d8deed8ff"
+ "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/vimeo/psalm/zipball/faf106e717c37b8c81721845dba9de3d8deed8ff",
- "reference": "faf106e717c37b8c81721845dba9de3d8deed8ff",
+ "url": "https://api.github.com/repos/vimeo/psalm/zipball/d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
+ "reference": "d0bc6e25d89f649e4f36a534f330f8bb4643dd69",
"shasum": ""
},
"require": {
@@ -5839,6 +6978,7 @@
"phpdocumentor/reflection-docblock": "^5",
"phpmyadmin/sql-parser": "5.1.0||dev-master",
"phpspec/prophecy": ">=1.9.0",
+ "phpstan/phpdoc-parser": "1.2.* || 1.6.4",
"phpunit/phpunit": "^9.0",
"psalm/plugin-phpunit": "^0.16",
"slevomat/coding-standard": "^7.0",
@@ -5892,9 +7032,9 @@
],
"support": {
"issues": "https://github.com/vimeo/psalm/issues",
- "source": "https://github.com/vimeo/psalm/tree/4.27.0"
+ "source": "https://github.com/vimeo/psalm/tree/4.30.0"
},
- "time": "2022-08-31T13:47:09+00:00"
+ "time": "2022-11-06T20:37:08+00:00"
},
{
"name": "webmozart/assert",
@@ -5954,6 +7094,55 @@
},
"time": "2022-06-03T18:03:27+00:00"
},
+ {
+ "name": "webmozart/glob",
+ "version": "4.6.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/webmozarts/glob.git",
+ "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/webmozarts/glob/zipball/3c17f7dec3d9d0e87b575026011f2e75a56ed655",
+ "reference": "3c17f7dec3d9d0e87b575026011f2e75a56ed655",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.3 || ^8.0.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^9.5",
+ "symfony/filesystem": "^5.3"
+ },
+ "type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "4.1-dev"
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Webmozart\\Glob\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Bernhard Schussek",
+ "email": "bschussek@gmail.com"
+ }
+ ],
+ "description": "A PHP implementation of Ant's glob.",
+ "support": {
+ "issues": "https://github.com/webmozarts/glob/issues",
+ "source": "https://github.com/webmozarts/glob/tree/4.6.0"
+ },
+ "time": "2022-05-24T19:45:58+00:00"
+ },
{
"name": "webmozart/path-util",
"version": "2.3.0",
@@ -6016,5 +7205,5 @@
"ext-json": "*"
},
"platform-dev": [],
- "plugin-api-version": "2.2.0"
+ "plugin-api-version": "2.3.0"
}
diff --git a/docs/customize.rst b/docs/customize.rst
index 47c030f..a5f0911 100644
--- a/docs/customize.rst
+++ b/docs/customize.rst
@@ -22,8 +22,8 @@ to replace just about any `builder`_, `codec`_, `converter`_, `generator`_,
Ordered-time Codec
The ordered-time codec exists to rearrange the bytes of a version 1,
- time-based UUID so that the timestamp portion of the UUID is monotonically
- increasing. To learn more, see :ref:`customize.ordered-time-codec`.
+ Gregorian time UUID so that the timestamp portion of the UUID is
+ monotonically increasing. To learn more, see :ref:`customize.ordered-time-codec`.
Timestamp-first COMB Codec
The timestamp-first COMB codec replaces part of a version 4, random UUID
diff --git a/docs/customize/ordered-time-codec.rst b/docs/customize/ordered-time-codec.rst
index 39df127..a41bb7a 100644
--- a/docs/customize/ordered-time-codec.rst
+++ b/docs/customize/ordered-time-codec.rst
@@ -4,10 +4,12 @@
Ordered-time Codec
==================
-.. hint::
+.. attention::
- :ref:`Version 6, ordered-time UUIDs ` are a proposed
- new version of UUID that take the place of ordered time UUIDs.
+ :ref:`Version 6, reordered time UUIDs ` are a new version
+ of UUID that eliminate the need for the ordered-time codec. If you aren't
+ currently using the ordered-time codec, and you need time-based, sortable
+ UUIDs, consider using version 6 UUIDs.
UUIDs arrange their bytes according to the standard recommended by `RFC 4122`_.
Unfortunately, this means the bytes aren't in an arrangement that supports
@@ -15,9 +17,9 @@ sorting by creation time or an otherwise incrementing value. The Percona
article, "`Storing UUID Values in MySQL`_," explains at length the problems this
can cause. It also recommends a solution: the *ordered-time UUID*.
-RFC 4122 version 1, time-based UUIDs rearrange the bytes of the time fields so
-that the lowest bytes appear first, the middle bytes are next, and the highest
-bytes come last. Logical sorting is not possible with this arrangement.
+RFC 4122 version 1, Gregorian time UUIDs rearrange the bytes of the time fields
+so that the lowest bytes appear first, the middle bytes are next, and the
+highest bytes come last. Logical sorting is not possible with this arrangement.
An ordered-time UUID is a version 1 UUID with the time fields arranged in
logical order so that the UUIDs can be sorted by creation time. These UUIDs are
diff --git a/docs/customize/timestamp-first-comb-codec.rst b/docs/customize/timestamp-first-comb-codec.rst
index 448e2ef..e49c921 100644
--- a/docs/customize/timestamp-first-comb-codec.rst
+++ b/docs/customize/timestamp-first-comb-codec.rst
@@ -4,6 +4,13 @@
Timestamp-first COMB Codec
==========================
+.. attention::
+
+ :ref:`Version 7, Unix Epoch time UUIDs ` are a new version
+ of UUID that eliminate the need for the timestamp-first COMB codec. If you
+ aren't currently using the timestamp-first COMB codec, and you need
+ time-based, sortable UUIDs, consider using version 7 UUIDs.
+
:ref:`Version 4, random UUIDs ` are doubly problematic when it
comes to sorting and storing to databases (see :ref:`database.order`), since
their values are random, and there is no timestamp associated with them that may
diff --git a/docs/database.rst b/docs/database.rst
index 3607dfd..ee401e3 100644
--- a/docs/database.rst
+++ b/docs/database.rst
@@ -229,29 +229,28 @@ small.
Insertion Order and Sorting
###########################
-UUIDs are not *monotonically increasing*. Even time-based UUIDs are not. If
-using UUIDs as primary keys, the inserts will be random, and the data will be
+UUID versions 1, 2, 3, 4, and 5 are not *monotonically increasing*. If using
+these versions as primary keys, the inserts will be random, and the data will be
scattered on disk (for InnoDB). Over time, as the database size grows, lookups
will become slower and slower.
-.. note::
+.. tip::
See Percona's "`Storing UUID Values in MySQL`_" post, for more details on
the performance of UUIDs as primary keys.
To minimize these problems, two solutions have been devised:
-1. Timestamp first COMBs
-2. Ordered Time UUIDs
+1. :ref:`rfc4122.version6` UUIDs
+2. :ref:`rfc4122.version7` UUIDs
-:ref:`customize.timestamp-first-comb-codec` explains the first solution and how
-to use ramsey/uuid to implement it, while :ref:`customize.ordered-time-codec`
-explains how to use ramsey/uuid to implement the second solution.
+.. note::
-.. hint::
-
- :ref:`Version 6, ordered-time UUIDs ` are a proposed
- new version of UUID that take the place of ordered time UUIDs.
+ We previously recommended the use of the :ref:`timestamp-first COMB
+ ` or :ref:`ordered-time
+ ` codecs to solve these problems. However,
+ UUID versions 6 and 7 were defined to provide these solutions in a
+ standardized way.
.. _ramsey/uuid-doctrine: https://github.com/ramsey/uuid-doctrine
@@ -259,4 +258,3 @@ explains how to use ramsey/uuid to implement the second solution.
.. _MariaDB: https://mariadb.org
.. _PHP Data Objects (PDO): https://www.php.net/pdo
.. _Storing UUID Values in MySQL: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
-.. _Version 6, ordered-time UUIDs: nonstandard.version6
diff --git a/docs/introduction.rst b/docs/introduction.rst
index 380f66b..5cb2dbd 100644
--- a/docs/introduction.rst
+++ b/docs/introduction.rst
@@ -5,9 +5,9 @@ Introduction
============
ramsey/uuid is a PHP library for generating and working with `RFC 4122`_ version
-1, 2, 3, 4, and 5 universally unique identifiers (UUID). ramsey/uuid also
-supports optional and non-standard features, such as `version 6 UUIDs`_,
-GUIDs, and other approaches for encoding/decoding UUIDs.
+1, 2, 3, 4, 5, 6, and 7 universally unique identifiers (UUID). ramsey/uuid also
+supports optional and non-standard features, such as GUIDs and other approaches
+for encoding/decoding UUIDs.
What Is a UUID?
###############
@@ -29,4 +29,3 @@ UUIDs can also be stored in binary format, as a string of 16 bytes.
.. _RFC 4122: https://tools.ietf.org/html/rfc4122
-.. _version 6 UUIDs: http://gh.peabody.io/uuidv6/
diff --git a/docs/nonstandard.rst b/docs/nonstandard.rst
index b35002e..83ed900 100644
--- a/docs/nonstandard.rst
+++ b/docs/nonstandard.rst
@@ -20,8 +20,8 @@ completely random and do not follow any rules.
For these cases, ramsey/uuid provides a special functionality to handle these
alternate, nonstandard forms.
-Version 6: Ordered-time
- This is a proposed version of UUID that combines the features of a
+Version 6: Reordered Time
+ This is a new version of UUID that combines the features of a
:ref:`version 1 UUID ` with a *monotonically increasing*
UUID. For more details, see :ref:`nonstandard.version6`.
diff --git a/docs/nonstandard/version6.rst b/docs/nonstandard/version6.rst
index 7fc8065..c45482e 100644
--- a/docs/nonstandard/version6.rst
+++ b/docs/nonstandard/version6.rst
@@ -1,209 +1,17 @@
.. _nonstandard.version6:
-=======================
-Version 6: Ordered-Time
-=======================
+=========================
+Version 6: Reordered Time
+=========================
-.. admonition:: Experimental
- :class: warning
+.. attention::
- Version 6, ordered-time UUIDs are an experimental feature based on an
- `Internet-Draft under review`_ at the IETF. While the basic layout is not
- expected to change, be aware that the draft is a moving target. If there
- are significant changes to the layout, ramsey/uuid will attempt to maintain
- backward compatibility but cannot guarantee it.
+ This documentation has moved to :ref:`RFC 4122 UUIDs: Version 6: Reordered
+ Time `.
-Version 6 UUIDs solve `two problems that have long existed`_ with the use of
-:ref:`version 1 ` UUIDs:
+ Version 6 UUIDs have been promoted to the ``Rfc4122`` namespace. While still
+ in draft form, the version 6 format is not expected to change in any way
+ that breaks compatibility.
-1. Scattered database records
-2. Inability to sort by an identifier in a meaningful way (i.e., insert order)
-
-To overcome these issues, we need the ability to generate UUIDs that are
-*monotonically increasing* while still providing all the benefits of version
-1 UUIDs.
-
-Version 6 UUIDs do this by storing the time in standard byte order, instead of
-breaking it up and rearranging the time bytes, according to the `RFC 4122`_
-definition. All other fields remain the same, and the version maintains its
-position, according to RFC 4122.
-
-In all other ways, version 6 UUIDs function like version 1 UUIDs.
-
-.. tip::
-
- Prior to version 4.0.0, ramsey/uuid provided a solution for this with the
- :ref:`ordered-time codec `. Use of the
- ordered-time codec is still valid and acceptable. However, you may replace
- UUIDs generated using the ordered-time codec with version 6 UUIDs. Keep
- reading to find out how.
-
-.. code-block:: php
- :caption: Generate a version 6, ordered-time UUID
- :name: nonstandard.version6.example
-
- use Ramsey\Uuid\Uuid;
-
- $uuid = Uuid::uuid6();
-
- printf(
- "UUID: %s\nVersion: %d\nDate: %s\nNode: %s\n",
- $uuid->toString(),
- $uuid->getFields()->getVersion()?->value,
- $uuid->getDateTime()->format('r'),
- $uuid->getFields()->getNode()->toString()
- );
-
-This will generate a version 6 UUID and print out its string representation, the
-time the UUID was created, and the node used to create the UUID.
-
-It will look something like this:
-
-.. code-block:: text
-
- UUID: 1ea60f56-b67b-61fc-829a-0242ac130003
- Version: 6
- Date: Sun, 08 Mar 2020 04:29:37 +0000
- Node: 0242ac130003
-
-You may provide custom values for version 6 UUIDs, including node and clock
-sequence.
-
-.. code-block:: php
- :caption: Provide custom node and clock sequence to create a version 6,
- ordered-time UUID
- :name: nonstandard.version6.custom-example
-
- use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
- use Ramsey\Uuid\Type\Hexadecimal;
- use Ramsey\Uuid\Uuid;
-
- $nodeProvider = new StaticNodeProvider(new Hexadecimal('121212121212'));
- $clockSequence = 16383;
-
- $uuid = Uuid::uuid6($nodeProvider->getNode(), $clockSequence);
-
-.. tip::
-
- Version 6 UUIDs generated in ramsey/uuid are instances of UuidV6. Check out
- the :php:class:`Ramsey\\Uuid\\Nonstandard\\UuidV6` API documentation to
- learn more about what you can do with a UuidV6 instance.
-
-
-.. _nonstandard.version6.nodes:
-
-Custom and Random Nodes
-#######################
-
-In the :ref:`example above `, we provided a
-custom node when generating a version 6 UUID. You may also generate random
-node values.
-
-To learn more, see the :ref:`rfc4122.version1.custom` and
-:ref:`rfc4122.version1.random` sections under :ref:`rfc4122.version1`.
-
-
-.. _nonstandard.version6.clock:
-
-Clock Sequence
-##############
-
-In a version 6 UUID, the clock sequence serves the same purpose as in a version
-1 UUID. See :ref:`rfc4122.version1.clock` to learn more.
-
-
-.. _nonstandard.version6.version1-conversion:
-
-Version 1-to-6 Conversion
-#########################
-
-It is possible to convert back-and-forth between version 6 and version 1 UUIDs.
-
-.. code-block:: php
- :caption: Convert a version 1 UUID to a version 6 UUID
- :name: nonstandard.version6.convert-version1-example
-
- use Ramsey\Uuid\Nonstandard\UuidV6;
- use Ramsey\Uuid\Rfc4122\UuidV1;
- use Ramsey\Uuid\Uuid;
-
- $uuid1 = Uuid::fromString('3960c5d8-60f8-11ea-bc55-0242ac130003');
-
- if ($uuid1 instanceof UuidV1) {
- $uuid6 = UuidV6::fromUuidV1($uuid1);
- }
-
-.. code-block:: php
- :caption: Convert a version 6 UUID to a version 1 UUID
- :name: nonstandard.version6.convert-version6-example
-
- use Ramsey\Uuid\Nonstandard\UuidV6;
- use Ramsey\Uuid\Uuid;
-
- $uuid6 = Uuid::fromString('1ea60f83-960c-65d8-bc55-0242ac130003');
-
- if ($uuid6 instanceof UuidV6) {
- $uuid1 = $uuid6->toUuidV1();
- }
-
-
-.. _nonstandard.version6.ordered-time-conversion:
-
-Ordered-time to Version 6 Conversion
-####################################
-
-You may convert UUIDs previously generated and stored using the
-:ref:`ordered-time codec ` into version 6 UUIDs.
-
-.. caution::
-
- If you perform this conversion, the bytes and string representation of your
- UUIDs will change. This will break any software that expects your
- identifiers to be fixed.
-
-.. code-block:: php
- :caption: Convert an ordered-time codec encoded UUID to a version 6 UUID
- :name: nonstandard.version6.convert-ordered-time-example
-
- use Ramsey\Uuid\Codec\OrderedTimeCodec;
- use Ramsey\Uuid\Nonstandard\UuidV6;
- use Ramsey\Uuid\Rfc4122\UuidV1;
- use Ramsey\Uuid\UuidFactory;
-
- // The bytes of a version 1 UUID previously stored in some datastore
- // after encoding to bytes with the OrderedTimeCodec.
- $bytes = hex2bin('11ea60faf17c8af6ad23acde48001122');
-
- $factory = new UuidFactory();
- $codec = new OrderedTimeCodec($factory->getUuidBuilder());
-
- $factory->setCodec($codec);
-
- $orderedTimeUuid = $factory->fromBytes($bytes);
-
- if ($orderedTimeUuid instanceof UuidV1) {
- $uuid6 = UuidV6::fromUuidV1($orderedTimeUuid);
- }
-
-
-.. _nonstandard.version6.privacy:
-
-Privacy Concerns
-################
-
-Like :ref:`version 1 UUIDs `, version 6 UUIDs use a MAC
-address from a local hardware network interface. This means it is possible to
-uniquely identify the machine on which a version 6 UUID was created.
-
-If the value provided by the timestamp of a version 6 UUID is important to you,
-but you do not wish to expose the interface address of any of your local
-machines, see :ref:`nonstandard.version6.nodes`.
-
-If you do not need an identifier with a node value embedded in it, but you still
-need the benefit of a monotonically increasing unique identifier, see
-:ref:`customize.timestamp-first-comb-codec`.
-
-
-.. _Internet-Draft under review: https://tools.ietf.org/html/draft-peabody-dispatch-new-uuid-format
-.. _two problems that have long existed: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
-.. _RFC 4122: https://tools.ietf.org/html/rfc4122
+ The :php:class:`Ramsey\\Uuid\\Nonstandard\\UuidV6` class is deprecated in
+ favor of :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV6`.
diff --git a/docs/quickstart.rst b/docs/quickstart.rst
index c66f356..35b0e6d 100644
--- a/docs/quickstart.rst
+++ b/docs/quickstart.rst
@@ -11,9 +11,6 @@ Requirements
ramsey/uuid |version| requires the following:
* PHP 8.0+
-* `ext-ctype `_ or a polyfill that
- provides ext-ctype, such as `symfony/polyfill-ctype
- `_
* `ext-json `_
The JSON extension is normally enabled by default, but it is possible to disable
@@ -96,7 +93,9 @@ library.
* - :php:meth:`Uuid::uuid5() `
- This generates a :ref:`rfc4122.version5` UUID.
* - :php:meth:`Uuid::uuid6() `
- - This generates a :ref:`nonstandard.version6` UUID.
+ - This generates a :ref:`rfc4122.version6` UUID.
+ * - :php:meth:`Uuid::uuid7() `
+ - This generates a :ref:`rfc4122.version7` UUID.
* - :php:meth:`Uuid::isValid() `
- Checks whether a string is a valid UUID.
* - :php:meth:`Uuid::fromString() `
diff --git a/docs/reference.rst b/docs/reference.rst
index 7ddcb47..f5443b9 100644
--- a/docs/reference.rst
+++ b/docs/reference.rst
@@ -18,12 +18,15 @@ Reference
reference/rfc4122-uuidv3
reference/rfc4122-uuidv4
reference/rfc4122-uuidv5
+ reference/rfc4122-uuidv6
+ reference/rfc4122-uuidv7
+ reference/rfc4122-uuidv8
reference/rfc4122-version
- reference/nonstandard-uuidv6
reference/guid-fields
reference/guid-guid
reference/nonstandard-fields
reference/nonstandard-uuid
+ reference/nonstandard-uuidv6
reference/uuidfactoryinterface
reference/types
reference/exceptions
diff --git a/docs/reference/helper.rst b/docs/reference/helper.rst
index 560bc72..a30d1b7 100644
--- a/docs/reference/helper.rst
+++ b/docs/reference/helper.rst
@@ -9,7 +9,7 @@ only the string standard representation of a UUID.
.. php:function:: Ramsey\Uuid\v1([$node[, $clockSeq]])
- Generates a string standard representation of a version 1, time-based UUID.
+ Generates a string standard representation of a version 1, Gregorian time UUID.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
@@ -54,7 +54,7 @@ only the string standard representation of a UUID.
.. php:function:: Ramsey\Uuid\v6([$node[, $clockSeq]])
- Generates a string standard representation of a version 6, ordered-time UUID.
+ Generates a string standard representation of a version 6, reordered time UUID.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
diff --git a/docs/reference/nonstandard-uuidv6.rst b/docs/reference/nonstandard-uuidv6.rst
index 5cb9e14..fafb0b3 100644
--- a/docs/reference/nonstandard-uuidv6.rst
+++ b/docs/reference/nonstandard-uuidv6.rst
@@ -8,14 +8,17 @@ Nonstandard\\UuidV6
.. php:class:: UuidV6
+ .. attention::
+
+ :php:class:`Ramsey\\Uuid\\Nonstandard\\UuidV6` is deprecated in favor of
+ :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV6`. Please migrate any code
+ using ``Nonstandard\UuidV6`` to ``Rfc4122\UuidV6``. The interface is
+ otherwise identical.
+
Implements :php:interface:`Ramsey\\Uuid\\Rfc4122\\UuidInterface` and
:php:interface:`Ramsey\\Uuid\\TimeBasedUuidInterface`.
- While in the Nonstandard sub-namespace, UuidV6 implements the same interface
- as the RFC 4122 UUIDs. This is because the definition for version 6 UUIDs is
- `currently in draft form`_, with the intent to update RFC 4122.
-
- UuidV6 represents a :ref:`version 6, ordered-time UUID
+ UuidV6 represents a :ref:`version 6, reordered time UUID
`. In addition to providing the methods defined on the
interface, this class additionally provides the following methods.
@@ -28,7 +31,4 @@ Nonstandard\\UuidV6
:param Ramsey\\Uuid\\Rfc4122\\UuidV1 $uuidV1: A version 1 UUID
:returns: A version 6 UUID, converted from the given version 1 UUID
- :returntype: Ramsey\\Uuid\\Nonstandard\\UuidV6
-
-
-.. _currently in draft form: https://tools.ietf.org/html/draft-peabody-dispatch-new-uuid-format-00
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV6
diff --git a/docs/reference/rfc4122-uuidv1.rst b/docs/reference/rfc4122-uuidv1.rst
index 55b8248..694cee2 100644
--- a/docs/reference/rfc4122-uuidv1.rst
+++ b/docs/reference/rfc4122-uuidv1.rst
@@ -11,4 +11,11 @@ Rfc4122\\UuidV1
Implements :php:interface:`Ramsey\\Uuid\\Rfc4122\\UuidInterface` and
:php:interface:`Ramsey\\Uuid\\TimeBasedUuidInterface`.
- UuidV1 represents a :ref:`version 1, time-based UUID `.
+ UuidV1 represents a :ref:`version 1, Gregorian time UUID `.
+ In addition to providing the methods defined on the interface, this class
+ additionally provides the following methods.
+
+ .. php:method:: getDateTime()
+
+ :returns: A date object representing the timestamp associated with the UUID.
+ :returntype: ``\DateTimeInterface``
diff --git a/docs/reference/rfc4122-uuidv6.rst b/docs/reference/rfc4122-uuidv6.rst
new file mode 100644
index 0000000..0b15f7e
--- /dev/null
+++ b/docs/reference/rfc4122-uuidv6.rst
@@ -0,0 +1,31 @@
+.. _reference.rfc4122.uuidv6:
+
+===============
+Rfc4122\\UuidV6
+===============
+
+.. php:namespace:: Ramsey\Uuid\Rfc4122
+
+.. php:class:: UuidV6
+
+ Implements :php:interface:`Ramsey\\Uuid\\Rfc4122\\UuidInterface`.
+
+ UuidV6 represents a :ref:`version 6, reordered time UUID
+ `. In addition to providing the methods defined on the
+ interface, this class additionally provides the following methods.
+
+ .. php:method:: getDateTime()
+
+ :returns: A date object representing the timestamp associated with the UUID
+ :returntype: ``\DateTimeInterface``
+
+ .. php:method:: toUuidV1()
+
+ :returns: A version 1 UUID, converted from this version 6 UUID
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV1
+
+ .. php:staticmethod:: fromUuidV1()
+
+ :param Ramsey\\Uuid\\Rfc4122\\UuidV1 $uuidV1: A version 1 UUID
+ :returns: A version 6 UUID, converted from the given version 1 UUID
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV6
diff --git a/docs/reference/rfc4122-uuidv7.rst b/docs/reference/rfc4122-uuidv7.rst
new file mode 100644
index 0000000..e4041a8
--- /dev/null
+++ b/docs/reference/rfc4122-uuidv7.rst
@@ -0,0 +1,20 @@
+.. _reference.rfc4122.uuidv7:
+
+===============
+Rfc4122\\UuidV7
+===============
+
+.. php:namespace:: Ramsey\Uuid\Rfc4122
+
+.. php:class:: UuidV7
+
+ Implements :php:interface:`Ramsey\\Uuid\\Rfc4122\\UuidInterface`.
+
+ UuidV7 represents a :ref:`version 7, Unix Epoch time UUID `.
+ In addition to providing the methods defined on the interface, this class
+ additionally provides the following methods.
+
+ .. php:method:: getDateTime()
+
+ :returns: A date object representing the timestamp associated with the UUID.
+ :returntype: ``\DateTimeInterface``
diff --git a/docs/reference/rfc4122-uuidv8.rst b/docs/reference/rfc4122-uuidv8.rst
new file mode 100644
index 0000000..f2465bd
--- /dev/null
+++ b/docs/reference/rfc4122-uuidv8.rst
@@ -0,0 +1,13 @@
+.. _reference.rfc4122.uuidv8:
+
+===============
+Rfc4122\\UuidV8
+===============
+
+.. php:namespace:: Ramsey\Uuid\Rfc4122
+
+.. php:class:: UuidV8
+
+ Implements :php:interface:`Ramsey\\Uuid\\Rfc4122\\UuidInterface`.
+
+ UuidV8 represents a :ref:`version 8, custom UUID `.
diff --git a/docs/reference/uuid.rst b/docs/reference/uuid.rst
index 52cf87f..dad5219 100644
--- a/docs/reference/uuid.rst
+++ b/docs/reference/uuid.rst
@@ -47,7 +47,7 @@ the ramsey/uuid library.
.. php:staticmethod:: uuid1([$node[, $clockSeq]])
- Generates a version 1, time-based UUID. See :ref:`rfc4122.version1`.
+ Generates a version 1, Gregorian time UUID. See :ref:`rfc4122.version1`.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
@@ -92,12 +92,20 @@ the ramsey/uuid library.
.. php:staticmethod:: uuid6([$node[, $clockSeq]])
- Generates a version 6, ordered-time UUID. See :ref:`nonstandard.version6`.
+ Generates a version 6, reordered time UUID. See :ref:`rfc4122.version6`.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
:returns: A version 6 UUID
- :returntype: Ramsey\\Uuid\\Nonstandard\\UuidV6
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV6
+
+ .. php:staticmethod:: uuid7([$dateTime])
+
+ Generates a version 7, Unix Epoch time UUID. See :ref:`rfc4122.version7`.
+
+ :param DateTimeInterface|null $dateTime: The date from which to create the UUID instance
+ :returns: A version 7 UUID
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV7
.. php:staticmethod:: fromString($uuid)
diff --git a/docs/reference/uuidfactoryinterface.rst b/docs/reference/uuidfactoryinterface.rst
index 842f71d..c68a61d 100644
--- a/docs/reference/uuidfactoryinterface.rst
+++ b/docs/reference/uuidfactoryinterface.rst
@@ -16,7 +16,7 @@ UuidFactoryInterface
.. php:method:: uuid1([$node[, $clockSeq]])
- Generates a version 1, time-based UUID. See :ref:`rfc4122.version1`.
+ Generates a version 1, Gregorian time UUID. See :ref:`rfc4122.version1`.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
@@ -61,12 +61,12 @@ UuidFactoryInterface
.. php:method:: uuid6([$node[, $clockSeq]])
- Generates a version 6, ordered-time UUID. See :ref:`nonstandard.version6`.
+ Generates a version 6, reordered time UUID. See :ref:`rfc4122.version6`.
:param Ramsey\\Uuid\\Type\\Hexadecimal|null $node: An optional hexadecimal node to use
:param int|null $clockSeq: An optional clock sequence to use
:returns: A version 6 UUID
- :returntype: Ramsey\\Uuid\\Nonstandard\\UuidV6
+ :returntype: Ramsey\\Uuid\\Rfc4122\\UuidV6
.. php:method:: fromString($uuid)
diff --git a/docs/rfc4122.rst b/docs/rfc4122.rst
index ec74b59..4ef53fa 100644
--- a/docs/rfc4122.rst
+++ b/docs/rfc4122.rst
@@ -13,13 +13,16 @@ RFC 4122 UUIDs
rfc4122/version3
rfc4122/version4
rfc4122/version5
+ rfc4122/version6
+ rfc4122/version7
+ rfc4122/version8
-`RFC 4122`_ defines five versions of UUID. Each version has different generation
-algorithms and properties. Which one you choose to use depends on your use-case.
-You can find out more about their applications on the specific page for that
-version.
+`RFC 4122`_ defines five versions of UUID, while a `new Internet-Draft under
+review`_ defines three new versions. Each version has different generation
+algorithms and properties. Which one you choose depends on your use-case. You
+can find out more about their applications on the specific page for that version.
-Version 1: Time-based
+Version 1: Gregorian Time
This version of UUID combines a timestamp, node value (in the form of a MAC
address from the local computer's network interface), and a clock sequence
to ensure uniqueness. For more details, see :doc:`rfc4122/version1`.
@@ -44,5 +47,21 @@ Version 5: Named-based (SHA-1)
deterministic UUID. The hashing algorithm used is SHA-1. For more details,
see :doc:`rfc4122/version5`.
+Version 6: Reordered Time
+ This version of UUID combines the features of a
+ :ref:`version 1 UUID ` with a *monotonically increasing*
+ UUID. For more details, see :ref:`rfc4122.version6`.
+
+Version 7: Unix Epoch Time
+ This version of UUID combines a timestamp--based on milliseconds elapsed
+ since the Unix Epoch--and random bytes to create a monotonically increasing,
+ sortable UUID without the privacy and entropy concerns associated with
+ version 1 and version 6 UUIDs. For more details, see :ref:`rfc4122.version7`.
+
+Version 8: Custom
+ This version of UUID allows applications to generate custom identifiers in
+ an RFC-compatible format. For more details, see :doc:`rfc4122/version8`.
+
.. _RFC 4122: https://tools.ietf.org/html/rfc4122
+.. _new Internet-Draft under review: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00
diff --git a/docs/rfc4122/version1.rst b/docs/rfc4122/version1.rst
index 226b3ca..1500fb8 100644
--- a/docs/rfc4122/version1.rst
+++ b/docs/rfc4122/version1.rst
@@ -1,8 +1,14 @@
.. _rfc4122.version1:
-=====================
-Version 1: Time-based
-=====================
+=========================
+Version 1: Gregorian Time
+=========================
+
+.. attention::
+
+ If you need a time-based UUID, and you don't need the other features
+ included in version 1 UUIDs, we recommend using
+ :ref:`version 7 UUIDs `.
A version 1 UUID uses a timestamp based on the `Gregorian calendar epoch`_,
along with the MAC address (or *node*) for a network interface on the local
@@ -28,7 +34,7 @@ is running on, using this value as the node. If it cannot find a MAC address, it
will generate a random node.
.. code-block:: php
- :caption: Generate a version 1, time-based UUID
+ :caption: Generate a version 1, Gregorian time UUID
:name: rfc4122.version1.example
use Ramsey\Uuid\Uuid;
@@ -60,7 +66,7 @@ sequence.
.. code-block:: php
:caption: Provide custom node and clock sequence to create a version 1,
- time-based UUID
+ Gregorian time UUID
:name: rfc4122.version1.custom-example
use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
@@ -124,7 +130,7 @@ generate a random node value, and like the StaticNodeProvider, it also sets the
unicast/multicast bit for you.
.. code-block:: php
- :caption: Provide a random node value to create a version 1, time-based UUID
+ :caption: Provide a random node value to create a version 1, Gregorian time UUID
:name: rfc4122.version1.random-example
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
diff --git a/docs/rfc4122/version5.rst b/docs/rfc4122/version5.rst
index 86f8ba4..7af3158 100644
--- a/docs/rfc4122/version5.rst
+++ b/docs/rfc4122/version5.rst
@@ -83,8 +83,8 @@ The best way to do this is to generate a :ref:`version 1 ` or
printf("My namespace UUID is %s\n", $uuid->toString());
-This will generate a version 1, time-based UUID, which we'll store to a constant
-so we can reuse it as our own custom namespace.
+This will generate a version 1, Gregorian time UUID, which we'll store to a
+constant so we can reuse it as our own custom namespace.
.. code-block:: php
:caption: Use a custom namespace to create version 5, name-based UUIDs
diff --git a/docs/rfc4122/version6.rst b/docs/rfc4122/version6.rst
new file mode 100644
index 0000000..93c1816
--- /dev/null
+++ b/docs/rfc4122/version6.rst
@@ -0,0 +1,213 @@
+.. _rfc4122.version6:
+
+=========================
+Version 6: Reordered Time
+=========================
+
+.. note::
+
+ Version 6, reordered time UUIDs are a new format of UUID, proposed in an
+ `Internet-Draft under review`_ at the IETF. While the draft is still going
+ through the IETF process, the version 6 format is not expected to change
+ in any way that breaks compatibility.
+
+.. attention::
+
+ If you need a time-based UUID, and you don't need the other features
+ included in version 6 UUIDs, we recommend using
+ :ref:`version 7 UUIDs `.
+
+Version 6 UUIDs solve `two problems that have long existed`_ with the use of
+:ref:`version 1 ` UUIDs:
+
+1. Scattered database records
+2. Inability to sort by an identifier in a meaningful way (i.e., insert order)
+
+To overcome these issues, we need the ability to generate UUIDs that are
+*monotonically increasing* while still providing all the benefits of version
+1 UUIDs.
+
+Version 6 UUIDs do this by storing the time in standard byte order, instead of
+breaking it up and rearranging the time bytes, according to the `RFC 4122`_
+definition. All other fields remain the same, and the version maintains its
+position, according to RFC 4122.
+
+In all other ways, version 6 UUIDs function like version 1 UUIDs.
+
+.. tip::
+
+ Prior to version 4.0.0, ramsey/uuid provided a solution for this with the
+ :ref:`ordered-time codec `. Use of the
+ ordered-time codec is still valid and acceptable. However, you may replace
+ UUIDs generated using the ordered-time codec with version 6 UUIDs. Keep
+ reading to find out how.
+
+.. code-block:: php
+ :caption: Generate a version 6, reordered time UUID
+ :name: rfc4122.version6.example
+
+ use Ramsey\Uuid\Uuid;
+
+ $uuid = Uuid::uuid6();
+
+ printf(
+ "UUID: %s\nVersion: %d\nDate: %s\nNode: %s\n",
+ $uuid->toString(),
+ $uuid->getFields()->getVersion()?->value,
+ $uuid->getDateTime()->format('r'),
+ $uuid->getFields()->getNode()->toString()
+ );
+
+This will generate a version 6 UUID and print out its string representation, the
+time the UUID was created, and the node used to create the UUID.
+
+It will look something like this:
+
+.. code-block:: text
+
+ UUID: 1ea60f56-b67b-61fc-829a-0242ac130003
+ Version: 6
+ Date: Sun, 08 Mar 2020 04:29:37 +0000
+ Node: 0242ac130003
+
+You may provide custom values for version 6 UUIDs, including node and clock
+sequence.
+
+.. code-block:: php
+ :caption: Provide custom node and clock sequence to create a version 6,
+ reordered time UUID
+ :name: rfc4122.version6.custom-example
+
+ use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
+ use Ramsey\Uuid\Type\Hexadecimal;
+ use Ramsey\Uuid\Uuid;
+
+ $nodeProvider = new StaticNodeProvider(new Hexadecimal('121212121212'));
+ $clockSequence = 16383;
+
+ $uuid = Uuid::uuid6($nodeProvider->getNode(), $clockSequence);
+
+.. tip::
+
+ Version 6 UUIDs generated in ramsey/uuid are instances of UuidV6. Check out
+ the :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV6` API documentation to
+ learn more about what you can do with a UuidV6 instance.
+
+
+.. _rfc4122.version6.nodes:
+
+Custom and Random Nodes
+#######################
+
+In the :ref:`example above `, we provided a
+custom node when generating a version 6 UUID. You may also generate random
+node values.
+
+To learn more, see the :ref:`rfc4122.version1.custom` and
+:ref:`rfc4122.version1.random` sections under :ref:`rfc4122.version1`.
+
+
+.. _rfc4122.version6.clock:
+
+Clock Sequence
+##############
+
+In a version 6 UUID, the clock sequence serves the same purpose as in a version
+1 UUID. See :ref:`rfc4122.version1.clock` to learn more.
+
+
+.. _rfc4122.version6.version1-conversion:
+
+Version 1-to-6 Conversion
+#########################
+
+It is possible to convert back-and-forth between version 6 and version 1 UUIDs.
+
+.. code-block:: php
+ :caption: Convert a version 1 UUID to a version 6 UUID
+ :name: rfc4122.version6.convert-version1-example
+
+ use Ramsey\Uuid\Rfc4122\UuidV1;
+ use Ramsey\Uuid\Rfc4122\UuidV6;
+ use Ramsey\Uuid\Uuid;
+
+ $uuid1 = Uuid::fromString('3960c5d8-60f8-11ea-bc55-0242ac130003');
+
+ if ($uuid1 instanceof UuidV1) {
+ $uuid6 = UuidV6::fromUuidV1($uuid1);
+ }
+
+.. code-block:: php
+ :caption: Convert a version 6 UUID to a version 1 UUID
+ :name: rfc4122.version6.convert-version6-example
+
+ use Ramsey\Uuid\Rfc4122\UuidV6;
+ use Ramsey\Uuid\Uuid;
+
+ $uuid6 = Uuid::fromString('1ea60f83-960c-65d8-bc55-0242ac130003');
+
+ if ($uuid6 instanceof UuidV6) {
+ $uuid1 = $uuid6->toUuidV1();
+ }
+
+
+.. _rfc4122.version6.ordered-time-conversion:
+
+Ordered-time to Version 6 Conversion
+####################################
+
+You may convert UUIDs previously generated and stored using the
+:ref:`ordered-time codec ` into version 6 UUIDs.
+
+.. caution::
+
+ If you perform this conversion, the bytes and string representation of your
+ UUIDs will change. This will break any software that expects your
+ identifiers to be fixed.
+
+.. code-block:: php
+ :caption: Convert an ordered-time codec encoded UUID to a version 6 UUID
+ :name: rfc4122.version6.convert-ordered-time-example
+
+ use Ramsey\Uuid\Codec\OrderedTimeCodec;
+ use Ramsey\Uuid\Rfc4122\UuidV1;
+ use Ramsey\Uuid\Rfc4122\UuidV6;
+ use Ramsey\Uuid\UuidFactory;
+
+ // The bytes of a version 1 UUID previously stored in some datastore
+ // after encoding to bytes with the OrderedTimeCodec.
+ $bytes = hex2bin('11ea60faf17c8af6ad23acde48001122');
+
+ $factory = new UuidFactory();
+ $codec = new OrderedTimeCodec($factory->getUuidBuilder());
+
+ $factory->setCodec($codec);
+
+ $orderedTimeUuid = $factory->fromBytes($bytes);
+
+ if ($orderedTimeUuid instanceof UuidV1) {
+ $uuid6 = UuidV6::fromUuidV1($orderedTimeUuid);
+ }
+
+
+.. _rfc4122.version6.privacy:
+
+Privacy Concerns
+################
+
+Like :ref:`version 1 UUIDs `, version 6 UUIDs use a MAC
+address from a local hardware network interface. This means it is possible to
+uniquely identify the machine on which a version 6 UUID was created.
+
+If the value provided by the timestamp of a version 6 UUID is important to you,
+but you do not wish to expose the interface address of any of your local
+machines, see :ref:`rfc4122.version6.nodes`.
+
+If you do not need an identifier with a node value embedded in it, but you still
+need the benefit of a monotonically increasing unique identifier, see
+:ref:`rfc4122.version7`.
+
+
+.. _Internet-Draft under review: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.6
+.. _two problems that have long existed: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
+.. _RFC 4122: https://tools.ietf.org/html/rfc4122
diff --git a/docs/rfc4122/version7.rst b/docs/rfc4122/version7.rst
new file mode 100644
index 0000000..d708467
--- /dev/null
+++ b/docs/rfc4122/version7.rst
@@ -0,0 +1,173 @@
+.. _rfc4122.version7:
+
+==========================
+Version 7: Unix Epoch Time
+==========================
+
+.. note::
+
+ Version 7, Unix Epoch time UUIDs are a new format of UUID, proposed in an
+ `Internet-Draft under review`_ at the IETF. While the draft is still going
+ through the IETF process, the version 7 format is not expected to change
+ in any way that breaks compatibility.
+
+.. admonition:: ULIDs and Version 7 UUIDs
+ :class: hint
+
+ Version 7 UUIDs are binary-compatible with `ULIDs`_ (universally unique
+ lexicographically-sortable identifiers).
+
+ Both use a 48-bit timestamp in milliseconds since the Unix Epoch, filling
+ the rest with random data. Version 7 UUIDs then add the version and variant
+ bits required by the UUID specification, which reduces the randomness from
+ 80 bits to 74. Otherwise, they are identical.
+
+ You may even convert a version 7 UUID to a ULID.
+ :ref:`See below for an example. `
+
+Version 7 UUIDs solve `two problems that have long existed`_ with the use of
+:ref:`version 1 ` UUIDs:
+
+1. Scattered database records
+2. Inability to sort by an identifier in a meaningful way (i.e., insert order)
+
+To overcome these issues, we need the ability to generate UUIDs that are
+*monotonically increasing*.
+
+:ref:`Version 6 UUIDs ` provide an excellent solution for
+those who need monotonically increasing, sortable UUIDs with the features of
+version 1 UUIDs (MAC address and clock sequence), but if those features aren't
+necessary for your application, using a version 6 UUID might be overkill.
+
+Version 7 UUIDs combine random data (like version 4 UUIDs) with a timestamp (in
+milliseconds since the Unix Epoch, i.e., 1970-01-01 00:00:00 UTC) to create a
+monotonically increasing, sortable UUID that doesn't have any privacy concerns,
+since it doesn't include a MAC address.
+
+For this reason, implementations should use version 7 UUIDs over versions 1 and
+6, if possible.
+
+.. code-block:: php
+ :caption: Generate a version 7, Unix Epoch time UUID
+ :name: rfc4122.version7.example
+
+ use Ramsey\Uuid\Uuid;
+
+ $uuid = Uuid::uuid7();
+
+ printf(
+ "UUID: %s\nVersion: %d\nDate: %s\n",
+ $uuid->toString(),
+ $uuid->getFields()->getVersion(),
+ $uuid->getDateTime()->format('r'),
+ );
+
+This will generate a version 7 UUID and print out its string representation and
+the time it was created.
+
+It will look something like this:
+
+.. code-block:: text
+
+ UUID: 01833ce0-3486-7bfd-84a1-ad157cf64005
+ Version: 7
+ Date: Wed, 14 Sep 2022 16:41:10 +0000
+
+To use an existing date and time to generate a version 7 UUID, you may pass a
+``\DateTimeInterface`` instance to the ``uuid7()`` method.
+
+.. code-block:: php
+ :caption: Generate a version 7 UUID from an existing date and time
+ :name: rfc4122.version7.example-datetime
+
+ use DateTimeImmutable;
+ use Ramsey\Uuid\Uuid;
+
+ $dateTime = new DateTimeImmutable('@281474976710.655');
+ $uuid = Uuid::uuid7($dateTime);
+
+ printf(
+ "UUID: %s\nVersion: %d\nDate: %s\n",
+ $uuid->toString(),
+ $uuid->getFields()->getVersion(),
+ $uuid->getDateTime()->format('r'),
+ );
+
+Which will print something like this:
+
+.. code-block:: text
+
+ UUID: ffffffff-ffff-7964-a8f6-001336ac20cb
+ Version: 7
+ Date: Tue, 02 Aug 10889 05:31:50 +0000
+
+.. tip::
+
+ Version 7 UUIDs generated in ramsey/uuid are instances of UuidV7. Check out
+ the :php:class:`Ramsey\\Uuid\\Rfc4122\\UuidV7` API documentation to learn
+ more about what you can do with a UuidV7 instance.
+
+
+.. _rfc4122.version7.ulid:
+
+Convert a Version 7 UUID to a ULID
+##################################
+
+As mentioned in the callout above, version 7 UUIDs are binary-compatible with
+`ULIDs`_. This means you can encode a version 7 UUID using `Crockford's Base 32
+algorithm`_ and it will be a valid ULID, timestamp and all.
+
+Using the third-party library `tuupola/base32`_, here's how we can encode a
+version 7 UUID as a ULID. Note that there's a little bit of work to perform the
+conversion, since you're working with different bases.
+
+.. code-block:: php
+ :caption: Encode a version 7, Unix Epoch time UUID as a ULID
+ :name: rfc4122.version7.example-ulid
+
+ use Ramsey\Uuid\Uuid;
+ use Tuupola\Base32;
+
+ $crockford = new Base32([
+ 'characters' => Base32::CROCKFORD,
+ 'padding' => false,
+ 'crockford' => true,
+ ]);
+
+ $uuid = Uuid::uuid7();
+
+ // First, we must pad the 16-byte string to 20 bytes
+ // for proper conversion without data loss.
+ $bytes = str_pad($uuid->getBytes(), 20, "\x00", STR_PAD_LEFT);
+
+ // Use Crockford's Base 32 encoding algorithm.
+ $encoded = $crockford->encode($bytes);
+
+ // That 20-byte string was encoded to 32 characters to avoid loss
+ // of data. We must strip off the first 6 characters--which are
+ // all zeros--to get a valid 26-character ULID string.
+ $ulid = substr($encoded, 6);
+
+ printf("ULID: %s\n", $ulid);
+
+This will print something like this:
+
+.. code-block:: text
+
+ ULID: 01GCZ05N3JFRKBRWKNGCQZGP44
+
+.. caution::
+
+ Be aware that all version 7 UUIDs may be converted to ULIDs but not all
+ ULIDs may be converted to UUIDs.
+
+ For that matter, all UUIDs of any version may be encoded as ULIDs, but they
+ will not be monotonically increasing and sortable unless they are version 7
+ UUIDs. You will also not be able to extract a meaningful timestamp from the
+ ULID, unless it was converted from a version 7 UUID.
+
+.. _ULIDs: https://github.com/ulid/spec
+.. _Internet-Draft under review: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.7
+.. _two problems that have long existed: https://www.percona.com/blog/2014/12/19/store-uuid-optimized-way/
+.. _Crockford's Base 32 algorithm: https://www.crockford.com/base32.html
+.. _tuupola/base32: https://packagist.org/packages/tuupola/base32
diff --git a/docs/rfc4122/version8.rst b/docs/rfc4122/version8.rst
new file mode 100644
index 0000000..3f87c23
--- /dev/null
+++ b/docs/rfc4122/version8.rst
@@ -0,0 +1,51 @@
+.. _rfc4122.version8:
+
+=================
+Version 8: Custom
+=================
+
+.. note::
+
+ Version 8, custom UUIDs are a new format of UUID, proposed in an
+ `Internet-Draft under review`_ at the IETF. While the draft is still going
+ through the IETF process, the version 8 format is not expected to change
+ in any way that breaks compatibility.
+
+Version 8 UUIDs allow applications to create custom UUIDs in an RFC-compatible
+way. The only requirement is the version and variant bits must be set according
+to the UUID specification. The bytes provided may contain any value according to
+your application's needs. Be aware, however, that other applications may not
+understand the semantics of the value.
+
+.. warning::
+
+ The bytes should be a 16-byte octet string, an open blob of data that you
+ may fill with 128 bits of information. However, bits 48 through 51 will be
+ replaced with the UUID version field, and bits 64 and 65 will be replaced
+ with the UUID variant. You must not rely on these bits for your application
+ needs.
+
+.. code-block:: php
+ :caption: Generate a version 8, custom UUID
+ :name: rfc4122.version8.example
+
+ use Ramsey\Uuid\Uuid;
+
+ $uuid = Uuid::uuid8("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff");
+
+ printf(
+ "UUID: %s\nVersion: %d\n",
+ $uuid->toString(),
+ $uuid->getFields()->getVersion()
+ );
+
+This will generate a version 8 UUID and print out its string representation.
+It will look something like this:
+
+.. code-block:: text
+
+ UUID: 00112233-4455-8677-8899-aabbccddeeff
+ Version: 8
+
+
+.. _Internet-Draft under review: https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.8
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index 1a2007a..519e3a0 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -1,5 +1,5 @@
-
+
@@ -13,13 +13,12 @@
-
+ $calculator$dceSecurityGenerator$numberConverter$timeConverter$timeGenerator
- $timeProvider
@@ -29,11 +28,6 @@
uuid_parse
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
- $this
@@ -41,16 +35,6 @@
$this
-
-
- new UuidFactory()
-
-
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
- $this
@@ -58,11 +42,6 @@
$this
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
- shell_exec('id -g')
@@ -81,7 +60,13 @@
-
+
+ $this
+ $this
+ $this
+ $this
+ $this
+ $this$this$this$this
@@ -99,69 +84,17 @@
$this
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
-
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
-
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
-
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
-
-
-
- parent::__construct($fields, $numberConverter, $codec, $timeConverter)
-
+
+
+ NonstandardUuidV6
+ $this->isNegative
-
-
- $this->isNegative
-
-
-
- new UuidFactory()
- new UuidFactory()
-
-
- fromDateTime
- getValidator
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- self::getFactory()
- uuid1
- uuid2
- uuid3
- uuid4
- uuid5
- uuid6
- getFactorygetFactory
@@ -172,23 +105,16 @@
-
- FeatureSet
- new FeatureSet()
-
-
- UuidFactory
-
-
+ $this->codec$this->codec$this->codec$this->isDefaultFeatureSet$this->nameGenerator$this->numberConverter
- $this->uuidBuilder
-
+
+ $this$this$this$this
diff --git a/src/Builder/FallbackBuilder.php b/src/Builder/FallbackBuilder.php
index ed9184c..2728d3c 100644
--- a/src/Builder/FallbackBuilder.php
+++ b/src/Builder/FallbackBuilder.php
@@ -27,17 +27,11 @@ use Ramsey\Uuid\UuidInterface;
*/
class FallbackBuilder implements UuidBuilderInterface
{
- /**
- * @var iterable
- */
- private iterable $builders;
-
/**
* @param iterable $builders An array of UUID builders
*/
- public function __construct(iterable $builders)
+ public function __construct(private iterable $builders)
{
- $this->builders = $builders;
}
/**
diff --git a/src/Codec/GuidStringCodec.php b/src/Codec/GuidStringCodec.php
index 7d1e77a..46389cc 100644
--- a/src/Codec/GuidStringCodec.php
+++ b/src/Codec/GuidStringCodec.php
@@ -18,6 +18,7 @@ use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\UuidInterface;
use function bin2hex;
+use function sprintf;
use function substr;
/**
@@ -29,6 +30,26 @@ use function substr;
*/
class GuidStringCodec extends StringCodec
{
+ public function encode(UuidInterface $uuid): string
+ {
+ $hex = bin2hex($uuid->getFields()->getBytes());
+
+ /** @var non-empty-string */
+ return sprintf(
+ '%02s%02s%02s%02s-%02s%02s-%02s%02s-%04s-%012s',
+ substr($hex, 6, 2),
+ substr($hex, 4, 2),
+ substr($hex, 2, 2),
+ substr($hex, 0, 2),
+ substr($hex, 10, 2),
+ substr($hex, 8, 2),
+ substr($hex, 14, 2),
+ substr($hex, 12, 2),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
+ }
+
public function decode(string $encodedUuid): UuidInterface
{
$bytes = $this->getBytes($encodedUuid);
diff --git a/src/Codec/OrderedTimeCodec.php b/src/Codec/OrderedTimeCodec.php
index 80eda69..4276891 100644
--- a/src/Codec/OrderedTimeCodec.php
+++ b/src/Codec/OrderedTimeCodec.php
@@ -86,7 +86,12 @@ class OrderedTimeCodec extends StringCodec
);
}
- // Rearrange the bytes to their original order.
+ /**
+ * Rearrange the bytes to their original order.
+ *
+ * @psalm-suppress UnnecessaryVarAnnotation
+ * @phpstan-var non-empty-string $rearrangedBytes
+ */
$rearrangedBytes = $bytes[4] . $bytes[5] . $bytes[6] . $bytes[7]
. $bytes[2] . $bytes[3]
. $bytes[0] . $bytes[1]
diff --git a/src/Codec/StringCodec.php b/src/Codec/StringCodec.php
index a702d35..e124ba9 100644
--- a/src/Codec/StringCodec.php
+++ b/src/Codec/StringCodec.php
@@ -17,12 +17,13 @@ namespace Ramsey\Uuid\Codec;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
-use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidInterface;
+use function bin2hex;
use function hex2bin;
use function implode;
+use function sprintf;
use function str_replace;
use function strlen;
use function substr;
@@ -36,33 +37,28 @@ use function substr;
*/
class StringCodec implements CodecInterface
{
- private UuidBuilderInterface $builder;
-
/**
* Constructs a StringCodec
*
* @param UuidBuilderInterface $builder The builder to use when encoding UUIDs
*/
- public function __construct(UuidBuilderInterface $builder)
+ public function __construct(private UuidBuilderInterface $builder)
{
- $this->builder = $builder;
}
public function encode(UuidInterface $uuid): string
{
- /** @var FieldsInterface $fields */
- $fields = $uuid->getFields();
+ $hex = bin2hex($uuid->getFields()->getBytes());
- return $fields->getTimeLow()->toString()
- . '-'
- . $fields->getTimeMid()->toString()
- . '-'
- . $fields->getTimeHiAndVersion()->toString()
- . '-'
- . $fields->getClockSeqHiAndReserved()->toString()
- . $fields->getClockSeqLow()->toString()
- . '-'
- . $fields->getNode()->toString();
+ /** @var non-empty-string */
+ return sprintf(
+ '%08s-%04s-%04s-%04s-%012s',
+ substr($hex, 0, 8),
+ substr($hex, 8, 4),
+ substr($hex, 12, 4),
+ substr($hex, 16, 4),
+ substr($hex, 20),
+ );
}
public function encodeBinary(UuidInterface $uuid): string
diff --git a/src/Converter/Number/GenericNumberConverter.php b/src/Converter/Number/GenericNumberConverter.php
index 2c8e471..f19898e 100644
--- a/src/Converter/Number/GenericNumberConverter.php
+++ b/src/Converter/Number/GenericNumberConverter.php
@@ -26,11 +26,8 @@ use Ramsey\Uuid\Type\Integer as IntegerObject;
*/
class GenericNumberConverter implements NumberConverterInterface
{
- private CalculatorInterface $calculator;
-
- public function __construct(CalculatorInterface $calculator)
+ public function __construct(private CalculatorInterface $calculator)
{
- $this->calculator = $calculator;
}
/**
diff --git a/src/Converter/Time/UnixTimeConverter.php b/src/Converter/Time/UnixTimeConverter.php
new file mode 100644
index 0000000..4d6d0a8
--- /dev/null
+++ b/src/Converter/Time/UnixTimeConverter.php
@@ -0,0 +1,90 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Converter\Time;
+
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Math\CalculatorInterface;
+use Ramsey\Uuid\Math\RoundingMode;
+use Ramsey\Uuid\Type\Hexadecimal;
+use Ramsey\Uuid\Type\Integer as IntegerObject;
+use Ramsey\Uuid\Type\Time;
+
+use function explode;
+use function str_pad;
+
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeConverter converts Unix Epoch timestamps to/from hexadecimal values
+ * consisting of milliseconds elapsed since the Unix Epoch
+ *
+ * @psalm-immutable
+ */
+class UnixTimeConverter implements TimeConverterInterface
+{
+ private const MILLISECONDS = 1000;
+
+ public function __construct(private CalculatorInterface $calculator)
+ {
+ }
+
+ public function calculateTime(string $seconds, string $microseconds): Hexadecimal
+ {
+ $timestamp = new Time($seconds, $microseconds);
+
+ // Convert the seconds into milliseconds.
+ $sec = $this->calculator->multiply(
+ $timestamp->getSeconds(),
+ new IntegerObject(self::MILLISECONDS),
+ );
+
+ // Convert the microseconds into milliseconds; the scale is zero because
+ // we need to discard the fractional part.
+ $usec = $this->calculator->divide(
+ RoundingMode::DOWN, // Always round down to stay in the previous millisecond.
+ 0,
+ $timestamp->getMicroseconds(),
+ new IntegerObject(self::MILLISECONDS),
+ );
+
+ /** @var IntegerObject $unixTime */
+ $unixTime = $this->calculator->add($sec, $usec);
+
+ $unixTimeHex = str_pad(
+ $this->calculator->toHexadecimal($unixTime)->toString(),
+ 12,
+ '0',
+ STR_PAD_LEFT
+ );
+
+ return new Hexadecimal($unixTimeHex);
+ }
+
+ public function convertTime(Hexadecimal $uuidTimestamp): Time
+ {
+ $milliseconds = $this->calculator->toInteger($uuidTimestamp);
+
+ $unixTimestamp = $this->calculator->divide(
+ RoundingMode::HALF_UP,
+ 6,
+ $milliseconds,
+ new IntegerObject(self::MILLISECONDS)
+ );
+
+ $split = explode('.', (string) $unixTimestamp, 2);
+
+ return new Time($split[0], $split[1] ?? '0');
+ }
+}
diff --git a/src/DeprecatedUuidFactoryInterface.php b/src/DeprecatedUuidFactoryInterface.php
deleted file mode 100644
index 8c921ab..0000000
--- a/src/DeprecatedUuidFactoryInterface.php
+++ /dev/null
@@ -1,180 +0,0 @@
-
- * @license http://opensource.org/licenses/MIT MIT
- */
-
-declare(strict_types=1);
-
-namespace Ramsey\Uuid;
-
-use DateTimeInterface;
-use Ramsey\Uuid\Type\Hexadecimal;
-use Ramsey\Uuid\Type\Integer as IntegerObject;
-use Ramsey\Uuid\Validator\ValidatorInterface;
-
-/**
- * This interface encapsulates deprecated methods for ramsey/uuid; this
- * interface and its methods will be removed in ramsey/uuid 5.0.0.
- *
- * @deprecated This interface and its methods will be removed in ramsey/uuid 5.0.0.
- */
-interface DeprecatedUuidFactoryInterface
-{
- /**
- * Creates a UUID from a DateTimeInterface instance
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * dedicated methods for creating datetime-based UUIDs. Use a dedicated
- * factory to generate UUIDs from a DateTime instance.
- *
- * @param DateTimeInterface $dateTime The date and time
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
- * duplicates that could arise when the clock is set backwards in time
- * or if the node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID created from a DateTimeInterface instance
- */
- public function fromDateTime(
- DateTimeInterface $dateTime,
- ?Hexadecimal $node = null,
- ?int $clockSeq = null
- ): UuidInterface;
-
- /**
- * Returns the validator to use for the factory
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * dedicated methods for getting validators. Use a dedicated validator
- * class to validate UUIDs.
- *
- * @psalm-mutation-free
- */
- public function getValidator(): ValidatorInterface;
-
- /**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
- * and the current time
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @param Hexadecimal|positive-int|non-empty-string|null $node A 48-bit
- * number representing the hardware address; this number may be
- * represented as an integer or a hexadecimal string
- * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
- * duplicates that could arise when the clock is set backwards in time
- * or if the node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 1 UUID
- */
- public function uuid1(Hexadecimal | int | string | null $node = null, ?int $clockSeq = null): UuidInterface;
-
- /**
- * Returns a version 2 (DCE Security) UUID from a local domain, local
- * identifier, host ID, clock sequence, and the current time
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @param int $localDomain The local domain to use when generating bytes,
- * according to DCE Security
- * @param IntegerObject|null $localIdentifier The local identifier for the
- * given domain; this may be a UID or GID on POSIX systems, if the local
- * domain is person or group, or it may be a site-defined identifier
- * if the local domain is org
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int<0, 63>|null $clockSeq A 6-bit number used to help avoid
- * duplicates that could arise when the clock is set backwards in time
- * or if the node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 2 UUID
- */
- public function uuid2(
- int $localDomain,
- ?IntegerObject $localIdentifier = null,
- ?Hexadecimal $node = null,
- ?int $clockSeq = null
- ): UuidInterface;
-
- /**
- * Returns a version 3 (name-based) UUID based on the MD5 hash of a
- * namespace ID and a name
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @param non-empty-string|UuidInterface $ns The namespace (must be a valid UUID)
- * @param string $name The name to use for creating a UUID
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 3 UUID
- *
- * @psalm-pure
- */
- public function uuid3(UuidInterface | string $ns, string $name): UuidInterface;
-
- /**
- * Returns a version 4 (random) UUID
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 4 UUID
- */
- public function uuid4(): UuidInterface;
-
- /**
- * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
- * namespace ID and a name
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @param non-empty-string|UuidInterface $ns The namespace (must be a valid UUID)
- * @param string $name The name to use for creating a UUID
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 5 UUID
- *
- * @psalm-pure
- */
- public function uuid5(UuidInterface | string $ns, string $name): UuidInterface;
-
- /**
- * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
- * and the current time
- *
- * @deprecated In ramsey/uuid version 5, UUID factories will no longer have
- * methods specific to creating subtypes. Instead, version 5 will use
- * dedicated factories for each subtype.
- *
- * @param Hexadecimal|null $node A 48-bit number representing the hardware
- * address
- * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
- * duplicates that could arise when the clock is set backwards in time
- * or if the node ID changes
- *
- * @return UuidInterface A UuidInterface instance that represents a
- * version 6 UUID
- */
- public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
-}
diff --git a/src/FeatureSet.php b/src/FeatureSet.php
index cd08887..67eb382 100644
--- a/src/FeatureSet.php
+++ b/src/FeatureSet.php
@@ -35,6 +35,7 @@ use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorFactory;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Math\CalculatorInterface;
@@ -58,26 +59,22 @@ use const PHP_INT_SIZE;
*
* A feature set is used by UuidFactory to determine the available features and
* capabilities of the environment.
- *
- * @deprecated This class will go away in ramsey/uuid version 5.
*/
class FeatureSet
{
- private bool $disable64Bit;
- private bool $ignoreSystemNode;
- private bool $enablePecl;
- private UuidBuilderInterface $builder;
+ private ?TimeProviderInterface $timeProvider = null;
+ private CalculatorInterface $calculator;
private CodecInterface $codec;
private DceSecurityGeneratorInterface $dceSecurityGenerator;
private NameGeneratorInterface $nameGenerator;
private NodeProviderInterface $nodeProvider;
private NumberConverterInterface $numberConverter;
- private TimeConverterInterface $timeConverter;
private RandomGeneratorInterface $randomGenerator;
+ private TimeConverterInterface $timeConverter;
private TimeGeneratorInterface $timeGenerator;
- private ?TimeProviderInterface $timeProvider;
+ private TimeGeneratorInterface $unixTimeGenerator;
+ private UuidBuilderInterface $builder;
private ValidatorInterface $validator;
- private CalculatorInterface $calculator;
/**
* @param bool $useGuids True build UUIDs using the GuidStringCodec
@@ -90,23 +87,22 @@ class FeatureSet
*/
public function __construct(
bool $useGuids = false,
- bool $force32Bit = false,
- bool $ignoreSystemNode = false,
- bool $enablePecl = false
+ private bool $force32Bit = false,
+ private bool $ignoreSystemNode = false,
+ private bool $enablePecl = false
) {
- $this->disable64Bit = $force32Bit;
- $this->ignoreSystemNode = $ignoreSystemNode;
- $this->enablePecl = $enablePecl;
-
+ $this->randomGenerator = $this->buildRandomGenerator();
$this->setCalculator(new BrickMathCalculator());
$this->builder = $this->buildUuidBuilder($useGuids);
$this->codec = $this->buildCodec($useGuids);
$this->nodeProvider = $this->buildNodeProvider();
$this->nameGenerator = $this->buildNameGenerator();
- $this->randomGenerator = $this->buildRandomGenerator();
$this->setTimeProvider(new SystemTimeProvider());
$this->setDceSecurityProvider(new SystemDceSecurityProvider());
$this->validator = new GenericValidator();
+
+ assert($this->timeProvider !== null);
+ $this->unixTimeGenerator = $this->buildUnixTimeGenerator();
}
/**
@@ -189,6 +185,14 @@ class FeatureSet
return $this->timeGenerator;
}
+ /**
+ * Returns the Unix Epoch time generator configured for this environment
+ */
+ public function getUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return $this->unixTimeGenerator;
+ }
+
/**
* Returns the validator configured for this environment
*/
@@ -330,6 +334,14 @@ class FeatureSet
))->getGenerator();
}
+ /**
+ * Returns a Unix Epoch time generator configured for this environment
+ */
+ private function buildUnixTimeGenerator(): TimeGeneratorInterface
+ {
+ return new UnixTimeGenerator($this->randomGenerator);
+ }
+
/**
* Returns a name generator configured for this environment
*/
@@ -378,6 +390,6 @@ class FeatureSet
*/
private function is64BitSystem(): bool
{
- return PHP_INT_SIZE === 8 && !$this->disable64Bit;
+ return PHP_INT_SIZE === 8 && !$this->force32Bit;
}
}
diff --git a/src/Fields/SerializableFieldsTrait.php b/src/Fields/SerializableFieldsTrait.php
index a326c2f..b81a5dd 100644
--- a/src/Fields/SerializableFieldsTrait.php
+++ b/src/Fields/SerializableFieldsTrait.php
@@ -49,6 +49,7 @@ trait SerializableFieldsTrait
/**
* @inheritDoc
+ * @psalm-suppress UnusedMethodCall
*/
public function __unserialize(array $data): void
{
diff --git a/src/Generator/UnixTimeGenerator.php b/src/Generator/UnixTimeGenerator.php
new file mode 100644
index 0000000..b64965d
--- /dev/null
+++ b/src/Generator/UnixTimeGenerator.php
@@ -0,0 +1,170 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Generator;
+
+use Brick\Math\BigInteger;
+use DateTimeImmutable;
+use DateTimeInterface;
+use Ramsey\Uuid\Type\Hexadecimal;
+
+use function hash;
+use function pack;
+use function str_pad;
+use function strlen;
+use function substr;
+use function substr_replace;
+use function unpack;
+
+use const PHP_INT_SIZE;
+use const STR_PAD_LEFT;
+
+/**
+ * UnixTimeGenerator generates bytes that combine a 48-bit timestamp in
+ * milliseconds since the Unix Epoch with 80 random bits
+ *
+ * Code and concepts within this class are borrowed from the symfony/uid package
+ * and are used under the terms of the MIT license distributed with symfony/uid.
+ *
+ * symfony/uid is copyright (c) Fabien Potencier.
+ *
+ * @link https://symfony.com/components/Uid Symfony Uid component
+ * @link https://github.com/symfony/uid/blob/4f9f537e57261519808a7ce1d941490736522bbc/UuidV7.php Symfony UuidV7 class
+ * @link https://github.com/symfony/uid/blob/6.2/LICENSE MIT License
+ */
+class UnixTimeGenerator implements TimeGeneratorInterface
+{
+ private static string $time = '';
+ private static ?string $seed = null;
+ private static int $seedIndex = 0;
+
+ /** @var int[] */
+ private static array $rand = [];
+
+ /** @var int[] */
+ private static array $seedParts;
+
+ public function __construct(
+ private readonly RandomGeneratorInterface $randomGenerator,
+ private readonly int $intSize = PHP_INT_SIZE,
+ ) {
+ }
+
+ /**
+ * @param DateTimeInterface|null $dateTime A date-time instance to use when
+ * generating bytes
+ *
+ * @return non-empty-string
+ */
+ public function generate(
+ Hexadecimal | int | string | null $node = null,
+ ?int $clockSeq = null,
+ ?DateTimeInterface $dateTime = null,
+ ): string {
+ $time = ($dateTime ?? new DateTimeImmutable('now'))->format('Uv');
+
+ if ($time > self::$time || ($dateTime !== null && $time !== self::$time)) {
+ $this->randomize($time);
+ } else {
+ $time = $this->increment();
+ }
+
+ if ($this->intSize >= 8) {
+ $time = substr(pack('J', (int) $time), -6);
+ } else {
+ $time = str_pad(BigInteger::of($time)->toBytes(false), 6, "\x00", STR_PAD_LEFT);
+ }
+
+ /** @var non-empty-string */
+ return $time . pack('n*', self::$rand[1], self::$rand[2], self::$rand[3], self::$rand[4], self::$rand[5]);
+ }
+
+ private function randomize(string $time): void
+ {
+ if (self::$seed === null) {
+ $seed = $this->randomGenerator->generate(16);
+ self::$seed = $seed;
+ } else {
+ $seed = $this->randomGenerator->generate(10);
+ }
+
+ /** @var int[] $rand */
+ $rand = unpack('n*', $seed);
+ $rand[1] &= 0x03ff;
+
+ self::$rand = $rand;
+ self::$time = $time;
+ }
+
+ /**
+ * Special thanks to Nicolas Grekas for sharing the following information:
+ *
+ * Within the same ms, we increment the rand part by a random 24-bit number.
+ *
+ * Instead of getting this number from random_bytes(), which is slow, we get
+ * it by sha512-hashing self::$seed. This produces 64 bytes of entropy,
+ * which we need to split in a list of 24-bit numbers. unpack() first splits
+ * them into 16 x 32-bit numbers; we take the first byte of each of these
+ * numbers to get 5 extra 24-bit numbers. Then, we consume those numbers
+ * one-by-one and run this logic every 21 iterations.
+ *
+ * self::$rand holds the random part of the UUID, split into 5 x 16-bit
+ * numbers for x86 portability. We increment this random part by the next
+ * 24-bit number in the self::$seedParts list and decrement
+ * self::$seedIndex.
+ *
+ * @link https://twitter.com/nicolasgrekas/status/1583356938825261061 Tweet from Nicolas Grekas
+ */
+ private function increment(): string
+ {
+ if (self::$seedIndex === 0 && self::$seed !== null) {
+ self::$seed = hash('sha512', self::$seed, true);
+
+ /** @var int[] $s */
+ $s = unpack('l*', self::$seed);
+ $s[] = ($s[1] >> 8 & 0xff0000) | ($s[2] >> 16 & 0xff00) | ($s[3] >> 24 & 0xff);
+ $s[] = ($s[4] >> 8 & 0xff0000) | ($s[5] >> 16 & 0xff00) | ($s[6] >> 24 & 0xff);
+ $s[] = ($s[7] >> 8 & 0xff0000) | ($s[8] >> 16 & 0xff00) | ($s[9] >> 24 & 0xff);
+ $s[] = ($s[10] >> 8 & 0xff0000) | ($s[11] >> 16 & 0xff00) | ($s[12] >> 24 & 0xff);
+ $s[] = ($s[13] >> 8 & 0xff0000) | ($s[14] >> 16 & 0xff00) | ($s[15] >> 24 & 0xff);
+
+ self::$seedParts = $s;
+ self::$seedIndex = 21;
+ }
+
+ self::$rand[5] = 0xffff & $carry = self::$rand[5] + (self::$seedParts[self::$seedIndex--] & 0xffffff);
+ self::$rand[4] = 0xffff & $carry = self::$rand[4] + ($carry >> 16);
+ self::$rand[3] = 0xffff & $carry = self::$rand[3] + ($carry >> 16);
+ self::$rand[2] = 0xffff & $carry = self::$rand[2] + ($carry >> 16);
+ self::$rand[1] += $carry >> 16;
+
+ if (0xfc00 & self::$rand[1]) {
+ $time = self::$time;
+ $mtime = (int) substr($time, -9);
+
+ if ($this->intSize >= 8 || strlen($time) < 10) {
+ $time = (string) ((int) $time + 1);
+ } elseif ($mtime === 999999999) {
+ $time = (1 + (int) substr($time, 0, -9)) . '000000000';
+ } else {
+ $mtime++;
+ $time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9);
+ }
+
+ $this->randomize($time);
+ }
+
+ return self::$time;
+ }
+}
diff --git a/src/Guid/Fields.php b/src/Guid/Fields.php
index 18e3762..269cc37 100644
--- a/src/Guid/Fields.php
+++ b/src/Guid/Fields.php
@@ -17,6 +17,7 @@ namespace Ramsey\Uuid\Guid;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Fields\SerializableFieldsTrait;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
+use Ramsey\Uuid\Rfc4122\MaxTrait;
use Ramsey\Uuid\Rfc4122\NilTrait;
use Ramsey\Uuid\Rfc4122\VariantTrait;
use Ramsey\Uuid\Rfc4122\Version;
@@ -45,6 +46,7 @@ use const STR_PAD_LEFT;
*/
final class Fields implements FieldsInterface
{
+ use MaxTrait;
use NilTrait;
use SerializableFieldsTrait;
use VariantTrait;
@@ -146,10 +148,15 @@ final class Fields implements FieldsInterface
public function getClockSeq(): Hexadecimal
{
- $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
- $clockSeqHex = str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT);
+ if ($this->isMax()) {
+ $clockSeq = 0xffff;
+ } elseif ($this->isNil()) {
+ $clockSeq = 0x0000;
+ } else {
+ $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ }
- return new Hexadecimal($clockSeqHex);
+ return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
}
public function getClockSeqHiAndReserved(): Hexadecimal
@@ -178,7 +185,7 @@ final class Fields implements FieldsInterface
public function getVersion(): ?Version
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return null;
}
@@ -190,7 +197,7 @@ final class Fields implements FieldsInterface
private function isCorrectVariant(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
diff --git a/src/Lazy/LazyUuidFromString.php b/src/Lazy/LazyUuidFromString.php
index 41a1701..f1a7138 100644
--- a/src/Lazy/LazyUuidFromString.php
+++ b/src/Lazy/LazyUuidFromString.php
@@ -17,8 +17,8 @@ namespace Ramsey\Uuid\Lazy;
use DateTimeInterface;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Fields\FieldsInterface;
-use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidV1;
+use Ramsey\Uuid\Rfc4122\UuidV6;
use Ramsey\Uuid\TimeBasedUuidInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
@@ -95,6 +95,7 @@ final class LazyUuidFromString implements TimeBasedUuidInterface
/**
* @inheritDoc
+ * @psalm-suppress UnusedMethodCall
*/
public function __unserialize(array $data): void
{
diff --git a/src/Nonstandard/Fields.php b/src/Nonstandard/Fields.php
index 25c61b0..d2473fb 100644
--- a/src/Nonstandard/Fields.php
+++ b/src/Nonstandard/Fields.php
@@ -146,4 +146,9 @@ final class Fields implements FieldsInterface
{
return false;
}
+
+ public function isMax(): bool
+ {
+ return false;
+ }
}
diff --git a/src/Nonstandard/UuidV6.php b/src/Nonstandard/UuidV6.php
index 0f6729b..e014a8c 100644
--- a/src/Nonstandard/UuidV6.php
+++ b/src/Nonstandard/UuidV6.php
@@ -14,41 +14,36 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Nonstandard;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Rfc4122\TimeTrait;
use Ramsey\Uuid\Rfc4122\UuidInterface;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\Rfc4122\Version;
use Ramsey\Uuid\TimeBasedUuidInterface;
use Ramsey\Uuid\Uuid;
-use Throwable;
-
-use function hex2bin;
-use function str_pad;
-use function substr;
-
-use const STR_PAD_LEFT;
/**
- * Ordered-time, or version 6, UUIDs include timestamp, clock sequence, and node
- * values that are combined into a 128-bit unsigned integer
+ * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and
+ * node values that are combined into a 128-bit unsigned integer
+ *
+ * @deprecated Use {@see \Ramsey\Uuid\Rfc4122\UuidV6} instead.
*
* @link https://github.com/uuid6/uuid6-ietf-draft UUID version 6 IETF draft
* @link http://gh.peabody.io/uuidv6/ "Version 6" UUIDs
*
* @psalm-immutable
*/
-final class UuidV6 extends Uuid implements UuidInterface, TimeBasedUuidInterface
+class UuidV6 extends Uuid implements UuidInterface, TimeBasedUuidInterface
{
+ use TimeTrait;
+
/**
- * Creates a version 6 (time-based) UUID
+ * Creates a version 6 (reordered time) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
* @param NumberConverterInterface $numberConverter The number converter to use
@@ -67,29 +62,13 @@ final class UuidV6 extends Uuid implements UuidInterface, TimeBasedUuidInterface
if ($fields->getVersion() !== Version::ReorderedTime) {
throw new InvalidArgumentException(
'Fields used to create a UuidV6 must represent a '
- . 'version 6 (ordered-time) UUID'
+ . 'version 6 (reordered time) UUID'
);
}
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->getTimeConverter()->convertTime($this->getFields()->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
-
/**
* Converts this UUID into an instance of a version 1 UUID
*/
@@ -114,7 +93,7 @@ final class UuidV6 extends Uuid implements UuidInterface, TimeBasedUuidInterface
/**
* Converts a version 1 UUID into an instance of a version 6 UUID
*/
- public static function fromUuidV1(UuidV1 $uuidV1): UuidV6
+ public static function fromUuidV1(UuidV1 $uuidV1): \Ramsey\Uuid\Rfc4122\UuidV6
{
$hex = $uuidV1->getHex()->toString();
$hex = substr($hex, 13, 3)
diff --git a/src/Provider/Node/SystemNodeProvider.php b/src/Provider/Node/SystemNodeProvider.php
index d617936..ca59035 100644
--- a/src/Provider/Node/SystemNodeProvider.php
+++ b/src/Provider/Node/SystemNodeProvider.php
@@ -133,12 +133,15 @@ class SystemNodeProvider implements NodeProviderInterface
$ifconfig = (string) ob_get_clean();
- $node = '';
if (preg_match_all(self::IFCONFIG_PATTERN, $ifconfig, $matches, PREG_PATTERN_ORDER)) {
- $node = $matches[1][0] ?? '';
+ foreach ($matches[1] as $iface) {
+ if ($iface !== '00:00:00:00:00:00' && $iface !== '00-00-00-00-00-00') {
+ return $iface;
+ }
+ }
}
- return $node;
+ return '';
}
/**
diff --git a/src/Rfc4122/Fields.php b/src/Rfc4122/Fields.php
index fe236b3..7ec6ae7 100644
--- a/src/Rfc4122/Fields.php
+++ b/src/Rfc4122/Fields.php
@@ -40,6 +40,7 @@ use const STR_PAD_LEFT;
*/
final class Fields implements FieldsInterface
{
+ use MaxTrait;
use NilTrait;
use SerializableFieldsTrait;
use VariantTrait;
@@ -81,10 +82,15 @@ final class Fields implements FieldsInterface
public function getClockSeq(): Hexadecimal
{
- $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
- $clockSeqHex = str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT);
+ if ($this->isMax()) {
+ $clockSeq = 0xffff;
+ } elseif ($this->isNil()) {
+ $clockSeq = 0x0000;
+ } else {
+ $clockSeq = hexdec(bin2hex(substr($this->bytes, 8, 2))) & 0x3fff;
+ }
- return new Hexadecimal($clockSeqHex);
+ return new Hexadecimal(str_pad(dechex($clockSeq), 4, '0', STR_PAD_LEFT));
}
public function getClockSeqHiAndReserved(): Hexadecimal
@@ -166,6 +172,14 @@ final class Fields implements FieldsInterface
$this->getTimeMid()->toString(),
hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff
),
+ // The Unix timestamp in version 7 UUIDs is a 48-bit number,
+ // but for consistency, we will return a 60-bit number, padded
+ // to the left with zeros.
+ Version::UnixTime => sprintf(
+ '%011s%04s',
+ $this->getTimeLow()->toString(),
+ $this->getTimeMid()->toString(),
+ ),
default => sprintf(
'%03x%04s%08s',
hexdec($this->getTimeHiAndVersion()->toString()) & 0x0fff,
@@ -179,19 +193,19 @@ final class Fields implements FieldsInterface
public function getVersion(): ?Version
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return null;
}
- /** @var array $parts */
+ /** @var int[] $parts */
$parts = unpack('n*', $this->bytes);
- return Version::tryFrom((int) $parts[4] >> 12);
+ return Version::tryFrom($parts[4] >> 12);
}
private function isCorrectVariant(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
diff --git a/src/Rfc4122/FieldsInterface.php b/src/Rfc4122/FieldsInterface.php
index bd962aa..2e39e5b 100644
--- a/src/Rfc4122/FieldsInterface.php
+++ b/src/Rfc4122/FieldsInterface.php
@@ -104,11 +104,13 @@ interface FieldsInterface extends BaseFieldsInterface
* The version number describes how the UUID was generated and has the
* following meaning:
*
- * 1. Time-based UUID
+ * 1. Gregorian time UUID
* 2. DCE security UUID
* 3. Name-based UUID hashed with MD5
* 4. Randomly generated UUID
* 5. Name-based UUID hashed with SHA-1
+ * 6. Reordered time UUID
+ * 7. Unix Epoch time UUID
*
* This returns `null` if the UUID is not an RFC 4122 variant, since version
* is only meaningful for this variant.
diff --git a/src/Rfc4122/MaxTrait.php b/src/Rfc4122/MaxTrait.php
new file mode 100644
index 0000000..dedb727
--- /dev/null
+++ b/src/Rfc4122/MaxTrait.php
@@ -0,0 +1,41 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+/**
+ * Provides common functionality for max UUIDs
+ *
+ * The max UUID is special form of UUID that is specified to have all 128 bits
+ * set to one. It is the inverse of the nil UUID.
+ *
+ * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.10 Max UUID
+ *
+ * @psalm-immutable
+ */
+trait MaxTrait
+{
+ /**
+ * Returns the bytes that comprise the fields
+ */
+ abstract public function getBytes(): string;
+
+ /**
+ * Returns true if the byte string represents a max UUID
+ */
+ public function isMax(): bool
+ {
+ return $this->getBytes() === "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
+ }
+}
diff --git a/src/Rfc4122/MaxUuid.php b/src/Rfc4122/MaxUuid.php
new file mode 100644
index 0000000..e5ffa72
--- /dev/null
+++ b/src/Rfc4122/MaxUuid.php
@@ -0,0 +1,27 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Uuid;
+
+/**
+ * The max UUID is special form of UUID that is specified to have all 128 bits
+ * set to one
+ *
+ * @psalm-immutable
+ */
+final class MaxUuid extends Uuid implements UuidInterface
+{
+}
diff --git a/src/Rfc4122/TimeTrait.php b/src/Rfc4122/TimeTrait.php
new file mode 100644
index 0000000..0c9d4e2
--- /dev/null
+++ b/src/Rfc4122/TimeTrait.php
@@ -0,0 +1,55 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use DateTimeImmutable;
+use DateTimeInterface;
+use Ramsey\Uuid\Exception\DateTimeException;
+use Throwable;
+
+use function str_pad;
+
+use const STR_PAD_LEFT;
+
+/**
+ * Provides common functionality for getting the time from a time-based UUID
+ *
+ * @psalm-immutable
+ */
+trait TimeTrait
+{
+ /**
+ * Returns a DateTimeInterface object representing the timestamp associated
+ * with the UUID
+ *
+ * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
+ * the timestamp of a time-based UUID
+ */
+ public function getDateTime(): DateTimeInterface
+ {
+ $time = $this->getTimeConverter()->convertTime($this->getFields()->getTimestamp());
+
+ try {
+ return new DateTimeImmutable(
+ '@'
+ . $time->getSeconds()->toString()
+ . '.'
+ . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
+ );
+ } catch (Throwable $e) {
+ throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
+ }
+ }
+}
diff --git a/src/Rfc4122/UuidBuilder.php b/src/Rfc4122/UuidBuilder.php
index c92cde6..02dfde8 100644
--- a/src/Rfc4122/UuidBuilder.php
+++ b/src/Rfc4122/UuidBuilder.php
@@ -17,10 +17,11 @@ namespace Ramsey\Uuid\Rfc4122;
use Ramsey\Uuid\Builder\UuidBuilderInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\Time\UnixTimeConverter;
use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
-use Ramsey\Uuid\Nonstandard\UuidV6;
+use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface;
use Ramsey\Uuid\UuidInterface;
use Throwable;
@@ -38,11 +39,16 @@ class UuidBuilder implements UuidBuilderInterface
* @param NumberConverterInterface $numberConverter The number converter to
* use when constructing the Uuid
* @param TimeConverterInterface $timeConverter The time converter to use
- * for converting timestamps extracted from a UUID to Unix timestamps
+ * for converting Gregorian time extracted from version 1, 2, and 6
+ * UUIDs to Unix timestamps
+ * @param TimeConverterInterface $unixTimeConverter The time converter
+ * to use for converter Unix Epoch time extracted from version 7 UUIDs
+ * to Unix timestamps
*/
public function __construct(
private readonly NumberConverterInterface $numberConverter,
- private readonly TimeConverterInterface $timeConverter
+ private readonly TimeConverterInterface $timeConverter,
+ private readonly TimeConverterInterface $unixTimeConverter = new UnixTimeConverter(new BrickMathCalculator())
) {
}
@@ -59,12 +65,17 @@ class UuidBuilder implements UuidBuilderInterface
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
+ /** @var Fields $fields */
$fields = $this->buildFields($bytes);
if ($fields->isNil()) {
return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
}
+ if ($fields->isMax()) {
+ return new MaxUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
+ }
+
switch ($fields->getVersion()) {
case Version::Time:
return new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter);
@@ -78,6 +89,10 @@ class UuidBuilder implements UuidBuilderInterface
return new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter);
case Version::ReorderedTime:
return new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter);
+ case Version::UnixTime:
+ return new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter);
+ case Version::Custom:
+ return new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter);
}
throw new UnsupportedOperationException(
diff --git a/src/Rfc4122/UuidV1.php b/src/Rfc4122/UuidV1.php
index a64d61c..5802059 100644
--- a/src/Rfc4122/UuidV1.php
+++ b/src/Rfc4122/UuidV1.php
@@ -14,32 +14,26 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Rfc4122;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\TimeBasedUuidInterface;
use Ramsey\Uuid\Uuid;
-use Throwable;
-
-use function str_pad;
-
-use const STR_PAD_LEFT;
/**
- * Time-based, or version 1, UUIDs include timestamp, clock sequence, and node
+ * Gregorian time, or version 1, UUIDs include timestamp, clock sequence, and node
* values that are combined into a 128-bit unsigned integer
*
* @psalm-immutable
*/
final class UuidV1 extends Uuid implements UuidInterface, TimeBasedUuidInterface
{
+ use TimeTrait;
+
/**
- * Creates a version 1 (time-based) UUID
+ * Creates a version 1 (Gregorian time) UUID
*
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
* @param NumberConverterInterface $numberConverter The number converter to use
@@ -64,20 +58,4 @@ final class UuidV1 extends Uuid implements UuidInterface, TimeBasedUuidInterface
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
-
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->getTimeConverter()->convertTime($this->getFields()->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
}
diff --git a/src/Rfc4122/UuidV2.php b/src/Rfc4122/UuidV2.php
index 2ebcd43..4681545 100644
--- a/src/Rfc4122/UuidV2.php
+++ b/src/Rfc4122/UuidV2.php
@@ -14,28 +14,34 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Rfc4122;
-use DateTimeImmutable;
-use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
-use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\TimeBasedUuidInterface;
use Ramsey\Uuid\Type\Integer as IntegerObject;
use Ramsey\Uuid\Uuid;
-use Throwable;
use function hexdec;
-use function str_pad;
-
-use const STR_PAD_LEFT;
/**
* DCE Security version, or version 2, UUIDs include local domain identifier,
* local ID for the specified domain, and node values that are combined into a
* 128-bit unsigned integer
*
+ * It is important to note that a version 2 UUID suffers from some loss of
+ * fidelity of the timestamp, due to replacing the time_low field with the
+ * local identifier. When constructing the timestamp value for date
+ * purposes, we replace the local identifier bits with zeros. As a result,
+ * the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
+ * minutes, 9 seconds, and 496730 microseconds).
+ *
+ * Astute observers might note this value directly corresponds to 2^32 - 1,
+ * or 0xffffffff. The local identifier is 32-bits, and we have set each of
+ * these bits to 0, so the maximum range of timestamp drift is 0x00000000
+ * to 0xffffffff (counted in 100-nanosecond intervals).
+ *
* @link https://publications.opengroup.org/c311 DCE 1.1: Authentication and Security Services
* @link https://publications.opengroup.org/c706 DCE 1.1: Remote Procedure Call
* @link https://pubs.opengroup.org/onlinepubs/9696989899/chap5.htm#tagcjh_08_02_01_01 DCE 1.1: Auth & Sec, §5.2.1.1
@@ -45,8 +51,10 @@ use const STR_PAD_LEFT;
*
* @psalm-immutable
*/
-final class UuidV2 extends Uuid implements UuidInterface
+final class UuidV2 extends Uuid implements UuidInterface, TimeBasedUuidInterface
{
+ use TimeTrait;
+
/**
* Creates a version 2 (DCE Security) UUID
*
@@ -74,41 +82,6 @@ final class UuidV2 extends Uuid implements UuidInterface
parent::__construct($fields, $numberConverter, $codec, $timeConverter);
}
- /**
- * Returns a DateTimeInterface object representing the timestamp associated
- * with the UUID
- *
- * It is important to note that a version 2 UUID suffers from some loss of
- * fidelity of the timestamp, due to replacing the time_low field with the
- * local identifier. When constructing the timestamp value for date
- * purposes, we replace the local identifier bits with zeros. As a result,
- * the timestamp can be off by a range of 0 to 429.4967295 seconds (or 7
- * minutes, 9 seconds, and 496730 microseconds).
- *
- * Astute observers might note this value directly corresponds to 2^32 - 1,
- * or 0xffffffff. The local identifier is 32-bits, and we have set each of
- * these bits to 0, so the maximum range of timestamp drift is 0x00000000
- * to 0xffffffff (counted in 100-nanosecond intervals).
- *
- * @return DateTimeImmutable A PHP DateTimeImmutable instance representing
- * the timestamp of a version 2 UUID
- */
- public function getDateTime(): DateTimeInterface
- {
- $time = $this->getTimeConverter()->convertTime($this->getFields()->getTimestamp());
-
- try {
- return new DateTimeImmutable(
- '@'
- . $time->getSeconds()->toString()
- . '.'
- . str_pad($time->getMicroseconds()->toString(), 6, '0', STR_PAD_LEFT)
- );
- } catch (Throwable $e) {
- throw new DateTimeException($e->getMessage(), (int) $e->getCode(), $e);
- }
- }
-
/**
* Returns the local domain used to create this version 2 UUID
*
diff --git a/src/Rfc4122/UuidV6.php b/src/Rfc4122/UuidV6.php
new file mode 100644
index 0000000..bc18775
--- /dev/null
+++ b/src/Rfc4122/UuidV6.php
@@ -0,0 +1,30 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Nonstandard\UuidV6 as NonstandardUuidV6;
+use Ramsey\Uuid\TimeBasedUuidInterface;
+
+/**
+ * Reordered time, or version 6, UUIDs include timestamp, clock sequence, and
+ * node values that are combined into a 128-bit unsigned integer
+ *
+ * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.6 UUID Version 6
+ *
+ * @psalm-immutable
+ */
+final class UuidV6 extends NonstandardUuidV6 implements UuidInterface, TimeBasedUuidInterface
+{
+}
diff --git a/src/Rfc4122/UuidV7.php b/src/Rfc4122/UuidV7.php
new file mode 100644
index 0000000..4b8930e
--- /dev/null
+++ b/src/Rfc4122/UuidV7.php
@@ -0,0 +1,63 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Codec\CodecInterface;
+use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\TimeBasedUuidInterface;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Unix Epoch time, or version 7, UUIDs include a timestamp in milliseconds
+ * since the Unix Epoch, along with random bytes
+ *
+ * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.7 UUID Version 7
+ *
+ * @psalm-immutable
+ */
+final class UuidV7 extends Uuid implements UuidInterface, TimeBasedUuidInterface
+{
+ use TimeTrait;
+
+ /**
+ * Creates a version 7 (Unix Epoch time) UUID
+ *
+ * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
+ * @param NumberConverterInterface $numberConverter The number converter to use
+ * for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding
+ * UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use
+ * for converting timestamps extracted from a UUID to unix timestamps
+ */
+ public function __construct(
+ Rfc4122FieldsInterface $fields,
+ NumberConverterInterface $numberConverter,
+ CodecInterface $codec,
+ TimeConverterInterface $timeConverter
+ ) {
+ if ($fields->getVersion() !== Version::UnixTime) {
+ throw new InvalidArgumentException(
+ 'Fields used to create a UuidV7 must represent a '
+ . 'version 7 (Unix Epoch time) UUID'
+ );
+ }
+
+ parent::__construct($fields, $numberConverter, $codec, $timeConverter);
+ }
+}
diff --git a/src/Rfc4122/UuidV8.php b/src/Rfc4122/UuidV8.php
new file mode 100644
index 0000000..efa8ab6
--- /dev/null
+++ b/src/Rfc4122/UuidV8.php
@@ -0,0 +1,65 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Rfc4122;
+
+use Ramsey\Uuid\Codec\CodecInterface;
+use Ramsey\Uuid\Converter\NumberConverterInterface;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\InvalidArgumentException;
+use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
+use Ramsey\Uuid\Uuid;
+
+/**
+ * Version 8, Custom UUIDs provide an RFC 4122 compatible format for
+ * experimental or vendor-specific uses
+ *
+ * The only requirement for version 8 UUIDs is that the version and variant bits
+ * must be set. Otherwise, implementations are free to set the other bits
+ * according to their needs. As a result, the uniqueness of version 8 UUIDs is
+ * implementation-specific and should not be assumed.
+ *
+ * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.8 UUID Version 8
+ *
+ * @psalm-immutable
+ */
+final class UuidV8 extends Uuid implements UuidInterface
+{
+ /**
+ * Creates a version 8 (custom) UUID
+ *
+ * @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
+ * @param NumberConverterInterface $numberConverter The number converter to use
+ * for converting hex values to/from integers
+ * @param CodecInterface $codec The codec to use when encoding or decoding
+ * UUID strings
+ * @param TimeConverterInterface $timeConverter The time converter to use
+ * for converting timestamps extracted from a UUID to unix timestamps
+ */
+ public function __construct(
+ Rfc4122FieldsInterface $fields,
+ NumberConverterInterface $numberConverter,
+ CodecInterface $codec,
+ TimeConverterInterface $timeConverter
+ ) {
+ if ($fields->getVersion() !== Version::Custom) {
+ throw new InvalidArgumentException(
+ 'Fields used to create a UuidV8 must represent a '
+ . 'version 8 (custom) UUID'
+ );
+ }
+
+ parent::__construct($fields, $numberConverter, $codec, $timeConverter);
+ }
+}
diff --git a/src/Rfc4122/Validator.php b/src/Rfc4122/Validator.php
index 10b65ca..6447444 100644
--- a/src/Rfc4122/Validator.php
+++ b/src/Rfc4122/Validator.php
@@ -28,7 +28,7 @@ use function str_replace;
final class Validator implements ValidatorInterface
{
private const VALID_PATTERN = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-'
- . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
+ . '[1-8][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
public function getPattern(): string
{
@@ -38,7 +38,8 @@ final class Validator implements ValidatorInterface
public function validate(string $uuid): bool
{
$uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);
+ $uuid = strtolower($uuid);
- return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
+ return $uuid === Uuid::NIL || $uuid === Uuid::MAX || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
}
}
diff --git a/src/Rfc4122/VariantTrait.php b/src/Rfc4122/VariantTrait.php
index 873faf1..1b28453 100644
--- a/src/Rfc4122/VariantTrait.php
+++ b/src/Rfc4122/VariantTrait.php
@@ -51,7 +51,13 @@ trait VariantTrait
throw new InvalidBytesException('Invalid number of bytes');
}
- /** @var array $parts */
+ if ($this->isMax() || $this->isNil()) {
+ // RFC 4122 defines these special types of UUID, so we will consider
+ // them as belonging to the RFC 4122 variant.
+ return Variant::Rfc4122;
+ }
+
+ /** @var int[] $parts */
$parts = unpack('n*', $this->getBytes());
// $parts[5] is a 16-bit, unsigned integer containing the variant bits
@@ -60,7 +66,7 @@ trait VariantTrait
// three characters (three most-significant bits) to determine the
// variant.
$binary = str_pad(
- decbin((int) $parts[5]),
+ decbin($parts[5]),
16,
'0',
STR_PAD_LEFT
@@ -69,15 +75,13 @@ trait VariantTrait
$msb = substr($binary, 0, 3);
if ($msb === '111') {
- $variant = Variant::ReservedFuture;
+ return Variant::ReservedFuture;
} elseif ($msb === '110') {
- $variant = Variant::ReservedMicrosoft;
+ return Variant::ReservedMicrosoft;
} elseif (str_starts_with($msb, '10')) {
- $variant = Variant::Rfc4122;
- } else {
- $variant = Variant::ReservedNcs;
+ return Variant::Rfc4122;
}
- return $variant;
+ return Variant::ReservedNcs;
}
}
diff --git a/src/Rfc4122/VersionTrait.php b/src/Rfc4122/VersionTrait.php
index 9b20163..de5e1bf 100644
--- a/src/Rfc4122/VersionTrait.php
+++ b/src/Rfc4122/VersionTrait.php
@@ -26,6 +26,11 @@ trait VersionTrait
*/
abstract public function getVersion(): ?Version;
+ /**
+ * Returns true if these fields represent a max UUID
+ */
+ abstract public function isMax(): bool;
+
/**
* Returns true if these fields represent a nil UUID
*/
@@ -38,13 +43,14 @@ trait VersionTrait
*/
private function isCorrectVersion(): bool
{
- if ($this->isNil()) {
+ if ($this->isNil() || $this->isMax()) {
return true;
}
return match ($this->getVersion()) {
Version::Time, Version::DceSecurity, Version::HashMd5,
- Version::Random, Version::HashSha1, Version::ReorderedTime => true,
+ Version::Random, Version::HashSha1, Version::ReorderedTime,
+ Version::UnixTime, Version::Custom => true,
default => false,
};
}
diff --git a/src/Type/Integer.php b/src/Type/Integer.php
index b3c9f19..38969b6 100644
--- a/src/Type/Integer.php
+++ b/src/Type/Integer.php
@@ -22,7 +22,6 @@ use function is_numeric;
use function ltrim;
use function preg_match;
use function sprintf;
-use function str_starts_with;
use function substr;
/**
@@ -134,6 +133,8 @@ final class Integer implements NumberInterface
// Add the negative sign back to the value.
if ($sign === '-' && $value !== '0') {
$value = $sign . $value;
+
+ /** @psalm-suppress InaccessibleProperty */
$this->isNegative = true;
}
diff --git a/src/Type/Time.php b/src/Type/Time.php
index 8e03643..a543b50 100644
--- a/src/Type/Time.php
+++ b/src/Type/Time.php
@@ -56,10 +56,8 @@ final class Time implements TypeInterface
*/
public function toString(): string
{
- /** @var numeric-string $combined */
- $combined = $this->seconds->toString() . '.' . $this->microseconds->toString();
-
- return $combined;
+ /** @var numeric-string */
+ return $this->seconds->toString() . '.' . sprintf('%06s', $this->microseconds->toString());
}
/**
diff --git a/src/Uuid.php b/src/Uuid.php
index c0be7ae..9676906 100644
--- a/src/Uuid.php
+++ b/src/Uuid.php
@@ -14,10 +14,12 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
+use BadMethodCallException;
use DateTimeInterface;
use Ramsey\Uuid\Codec\CodecInterface;
use Ramsey\Uuid\Converter\NumberConverterInterface;
use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\UnsupportedOperationException;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Rfc4122\FieldsInterface as Rfc4122FieldsInterface;
use Ramsey\Uuid\Rfc4122\UuidInterface as Rfc4122UuidInterface;
@@ -27,6 +29,7 @@ use ValueError;
use function assert;
use function bin2hex;
+use function method_exists;
use function preg_match;
use function sprintf;
use function str_replace;
@@ -80,6 +83,14 @@ class Uuid implements Rfc4122UuidInterface
*/
public const NIL = '00000000-0000-0000-0000-000000000000';
+ /**
+ * The max UUID is a special form of UUID that is specified to have all 128
+ * bits set to one
+ *
+ * @link https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-00#section-5.10 Max UUID
+ */
+ public const MAX = 'ffffffff-ffff-ffff-ffff-ffffffffffff';
+
/**
* DCE Security principal domain
*
@@ -115,8 +126,9 @@ class Uuid implements Rfc4122UuidInterface
private static ?UuidFactoryInterface $factory = null;
/**
- * @var bool flag to detect if the UUID factory was replaced internally, which disables all optimizations
- * for the default/happy path internal scenarios
+ * @var bool flag to detect if the UUID factory was replaced internally,
+ * which disables all optimizations for the default/happy path internal
+ * scenarios
*/
private static bool $factoryReplaced = false;
@@ -136,10 +148,6 @@ class Uuid implements Rfc4122UuidInterface
* $namespaceSha1Uuid = Uuid::uuid5(Uuid::NAMESPACE_URL, 'http://php.net/');
* ```
*
- * @deprecated ramsey/uuid version 5 will no longer allow direct
- * instantiation of the base Ramsey\Uuid\Uuid class. Instead, you must
- * use factories to create UUID objects.
- *
* @param Rfc4122FieldsInterface $fields The fields from which to construct a UUID
* @param NumberConverterInterface $numberConverter The number converter to use
* for converting hex values to/from integers
@@ -280,9 +288,6 @@ class Uuid implements Rfc4122UuidInterface
/**
* Returns the factory used to create UUIDs
- *
- * @deprecated ramsey/uuid version 5 will no longer support getting a
- * factory instance from the base Ramsey\Uuid\Uuid class.
*/
public static function getFactory(): UuidFactoryInterface
{
@@ -296,11 +301,6 @@ class Uuid implements Rfc4122UuidInterface
/**
* Sets the factory used to create UUIDs
*
- * @deprecated ramsey/uuid version 5 will no longer support setting a
- * factory instance on the base Ramsey\Uuid\Uuid class. If you need to
- * customize the properties used to build a UUID, use one of the
- * dedicated factories that version 5 will introduce.
- *
* @param UuidFactoryInterface $factory A factory that will be used by this
* class to create UUIDs
*/
@@ -402,6 +402,33 @@ class Uuid implements Rfc4122UuidInterface
return self::getFactory()->fromDateTime($dateTime, $node, $clockSeq);
}
+ /**
+ * Creates a UUID from the Hexadecimal object
+ *
+ * @param Hexadecimal $hex Hexadecimal object representing a hexadecimal number
+ *
+ * @return UuidInterface A UuidInterface instance created from the Hexadecimal
+ * object representing a hexadecimal number
+ *
+ * @psalm-pure note: changing the internal factory is an edge case not covered by purity invariants,
+ * but under constant factory setups, this method operates in functionally pure manners
+ * @psalm-suppress MixedInferredReturnType,MixedReturnStatement
+ */
+ public static function fromHexadecimal(Hexadecimal $hex): UuidInterface
+ {
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'fromHexadecimal')) {
+ /**
+ * @phpstan-ignore-next-line
+ * @psalm-suppress UndefinedInterfaceMethod
+ */
+ return self::getFactory()->fromHexadecimal($hex);
+ }
+
+ throw new BadMethodCallException('The method fromHexadecimal() does not exist on the provided factory');
+ }
+
/**
* Creates a UUID from a 128-bit integer string
*
@@ -415,6 +442,7 @@ class Uuid implements Rfc4122UuidInterface
*/
public static function fromInteger(string $integer): UuidInterface
{
+ /** @psalm-suppress ImpureMethodCall */
return self::getFactory()->fromInteger($integer);
}
@@ -432,11 +460,12 @@ class Uuid implements Rfc4122UuidInterface
*/
public static function isValid(string $uuid): bool
{
+ /** @psalm-suppress ImpureMethodCall */
return self::getFactory()->getValidator()->validate($uuid);
}
/**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number,
* and the current time
*
* @param Hexadecimal|positive-int|non-empty-string|null $node A 48-bit
@@ -541,7 +570,7 @@ class Uuid implements Rfc4122UuidInterface
}
/**
- * Returns a version 6 (ordered-time) UUID from a host ID, sequence number,
+ * Returns a version 6 (reordered time) UUID from a host ID, sequence number,
* and the current time
*
* @param Hexadecimal|null $node A 48-bit number representing the hardware
@@ -559,4 +588,58 @@ class Uuid implements Rfc4122UuidInterface
): UuidInterface {
return self::getFactory()->uuid6($node, $clockSeq);
}
+
+ /**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface|null $dateTime An optional date/time from which
+ * to create the version 7 UUID. If not provided, the UUID is generated
+ * using the current date/time.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 7 UUID
+ */
+ public static function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
+ {
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'uuid7')) {
+ /** @var UuidInterface */
+ return $factory->uuid7($dateTime);
+ }
+
+ throw new UnsupportedOperationException(
+ 'The provided factory does not support the uuid7() method',
+ );
+ }
+
+ /**
+ * Returns a version 8 (custom) UUID
+ *
+ * The bytes provided may contain any value according to your application's
+ * needs. Be aware, however, that other applications may not understand the
+ * semantics of the value.
+ *
+ * @param string $bytes A 16-byte octet string. This is an open blob
+ * of data that you may fill with 128 bits of information. Be aware,
+ * however, bits 48 through 51 will be replaced with the UUID version
+ * field, and bits 64 and 65 will be replaced with the UUID variant. You
+ * MUST NOT rely on these bits for your application needs.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 8 UUID
+ */
+ public static function uuid8(string $bytes): UuidInterface
+ {
+ $factory = self::getFactory();
+
+ if (method_exists($factory, 'uuid8')) {
+ /** @var UuidInterface */
+ return $factory->uuid8($bytes);
+ }
+
+ throw new UnsupportedOperationException(
+ 'The provided factory does not support the uuid8() method',
+ );
+ }
}
diff --git a/src/UuidFactory.php b/src/UuidFactory.php
index 221b475..52defae 100644
--- a/src/UuidFactory.php
+++ b/src/UuidFactory.php
@@ -24,6 +24,7 @@ use Ramsey\Uuid\Generator\DefaultTimeGenerator;
use Ramsey\Uuid\Generator\NameGeneratorInterface;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Generator\TimeGeneratorInterface;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Provider\NodeProviderInterface;
use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
@@ -42,68 +43,30 @@ use function substr;
use const STR_PAD_LEFT;
/**
- * @deprecated UuidFactory will go away in ramsey/uuid version 5. Use dedicated
- * factories for subtypes instead.
- *
* @psalm-suppress MissingImmutableAnnotation
*/
class UuidFactory implements UuidFactoryInterface
{
+ private CodecInterface $codec;
+ private DceSecurityGeneratorInterface $dceSecurityGenerator;
+ private NameGeneratorInterface $nameGenerator;
+ private NodeProviderInterface $nodeProvider;
+ private NumberConverterInterface $numberConverter;
+ private RandomGeneratorInterface $randomGenerator;
+ private TimeConverterInterface $timeConverter;
+ private TimeGeneratorInterface $timeGenerator;
+ private TimeGeneratorInterface $unixTimeGenerator;
+ private UuidBuilderInterface $uuidBuilder;
+ private ValidatorInterface $validator;
+
/**
- * @var CodecInterface
+ * @var bool whether the feature set was provided from outside, or we can
+ * operate under "default" assumptions
*/
- private $codec;
+ private bool $isDefaultFeatureSet;
/**
- * @var DceSecurityGeneratorInterface
- */
- private $dceSecurityGenerator;
-
- /**
- * @var NameGeneratorInterface
- */
- private $nameGenerator;
-
- /**
- * @var NodeProviderInterface
- */
- private $nodeProvider;
-
- /**
- * @var NumberConverterInterface
- */
- private $numberConverter;
-
- /**
- * @var RandomGeneratorInterface
- */
- private $randomGenerator;
-
- /**
- * @var TimeConverterInterface
- */
- private $timeConverter;
-
- /**
- * @var TimeGeneratorInterface
- */
- private $timeGenerator;
-
- /**
- * @var UuidBuilderInterface
- */
- private $uuidBuilder;
-
- /**
- * @var ValidatorInterface
- */
- private $validator;
-
- /** @var bool whether the feature set was provided from outside, or we can operate under "default" assumptions */
- private $isDefaultFeatureSet;
-
- /**
- * @param FeatureSet $features A set of available features in the current environment
+ * @param FeatureSet|null $features A set of available features in the current environment
*/
public function __construct(?FeatureSet $features = null)
{
@@ -121,6 +84,7 @@ class UuidFactory implements UuidFactoryInterface
$this->timeGenerator = $features->getTimeGenerator();
$this->uuidBuilder = $features->getBuilder();
$this->validator = $features->getValidator();
+ $this->unixTimeGenerator = $features->getUnixTimeGenerator();
}
/**
@@ -350,9 +314,14 @@ class UuidFactory implements UuidFactoryInterface
}
/**
- * @inheritDoc
+ * @psalm-pure
*/
- public function uuid1($node = null, ?int $clockSeq = null): UuidInterface
+ public function fromHexadecimal(Hexadecimal $hex): UuidInterface
+ {
+ return $this->codec->decode($hex->__toString());
+ }
+
+ public function uuid1(Hexadecimal | int | string | null $node = null, ?int $clockSeq = null): UuidInterface
{
$bytes = $this->timeGenerator->generate($node, $clockSeq);
@@ -420,6 +389,45 @@ class UuidFactory implements UuidFactoryInterface
return $this->uuidFromBytesAndVersion($v6Bytes, Version::ReorderedTime);
}
+ /**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface|null $dateTime An optional date/time from which
+ * to create the version 7 UUID. If not provided, the UUID is generated
+ * using the current date/time.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 7 UUID
+ */
+ public function uuid7(?DateTimeInterface $dateTime = null): UuidInterface
+ {
+ assert($this->unixTimeGenerator instanceof UnixTimeGenerator);
+ $bytes = $this->unixTimeGenerator->generate(null, null, $dateTime);
+
+ return $this->uuidFromBytesAndVersion($bytes, Version::UnixTime);
+ }
+
+ /**
+ * Returns a version 8 (Custom) UUID
+ *
+ * The bytes provided may contain any value according to your application's
+ * needs. Be aware, however, that other applications may not understand the
+ * semantics of the value.
+ *
+ * @param non-empty-string $bytes A 16-byte octet string. This is an open blob
+ * of data that you may fill with 128 bits of information. Be aware,
+ * however, bits 48 through 51 will be replaced with the UUID version
+ * field, and bits 64 and 65 will be replaced with the UUID variant. You
+ * MUST NOT rely on these bits for your application needs.
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 8 UUID
+ */
+ public function uuid8(string $bytes): UuidInterface
+ {
+ return $this->uuidFromBytesAndVersion($bytes, Version::Custom);
+ }
+
/**
* Returns a Uuid created from the provided byte string
*
@@ -435,6 +443,7 @@ class UuidFactory implements UuidFactoryInterface
*/
public function uuid(string $bytes): UuidInterface
{
+ /** @psalm-suppress ImpurePropertyFetch */
return $this->uuidBuilder->build($this->codec, $bytes);
}
diff --git a/src/UuidFactoryInterface.php b/src/UuidFactoryInterface.php
index 0fd9708..adb4cd5 100644
--- a/src/UuidFactoryInterface.php
+++ b/src/UuidFactoryInterface.php
@@ -14,13 +14,18 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
+use DateTimeInterface;
+use Ramsey\Uuid\Type\Hexadecimal;
+use Ramsey\Uuid\Type\Integer as IntegerObject;
+use Ramsey\Uuid\Validator\ValidatorInterface;
+
/**
* UuidFactoryInterface defines common functionality all `UuidFactory` instances
* must implement
*
* @psalm-immutable
*/
-interface UuidFactoryInterface extends DeprecatedUuidFactoryInterface
+interface UuidFactoryInterface
{
/**
* Creates a UUID from a byte string
@@ -34,6 +39,25 @@ interface UuidFactoryInterface extends DeprecatedUuidFactoryInterface
*/
public function fromBytes(string $bytes): UuidInterface;
+ /**
+ * Creates a UUID from a DateTimeInterface instance
+ *
+ * @param DateTimeInterface $dateTime The date and time
+ * @param Hexadecimal|null $node A 48-bit number representing the hardware
+ * address
+ * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
+ * duplicates that could arise when the clock is set backwards in time
+ * or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 1 UUID created from a DateTimeInterface instance
+ */
+ public function fromDateTime(
+ DateTimeInterface $dateTime,
+ ?Hexadecimal $node = null,
+ ?int $clockSeq = null
+ ): UuidInterface;
+
/**
* Creates a UUID from a 128-bit integer string
*
@@ -57,4 +81,104 @@ interface UuidFactoryInterface extends DeprecatedUuidFactoryInterface
* @psalm-pure
*/
public function fromString(string $uuid): UuidInterface;
+
+ /**
+ * Returns the validator to use for the factory
+ *
+ * @psalm-mutation-free
+ */
+ public function getValidator(): ValidatorInterface;
+
+ /**
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number,
+ * and the current time
+ *
+ * @param Hexadecimal|int<1, max>|non-empty-string|null $node A 48-bit number
+ * representing the hardware address; this number may be represented as
+ * an integer or a hexadecimal string
+ * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
+ * duplicates that could arise when the clock is set backwards in time
+ * or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 1 UUID
+ */
+ public function uuid1(Hexadecimal | int | string | null $node = null, ?int $clockSeq = null): UuidInterface;
+
+ /**
+ * Returns a version 2 (DCE Security) UUID from a local domain, local
+ * identifier, host ID, clock sequence, and the current time
+ *
+ * @param int $localDomain The local domain to use when generating bytes,
+ * according to DCE Security
+ * @param IntegerObject|null $localIdentifier The local identifier for the
+ * given domain; this may be a UID or GID on POSIX systems, if the local
+ * domain is person or group, or it may be a site-defined identifier
+ * if the local domain is org
+ * @param Hexadecimal|null $node A 48-bit number representing the hardware
+ * address
+ * @param int<0, 63>|null $clockSeq A 6-bit number used to help avoid
+ * duplicates that could arise when the clock is set backwards in time
+ * or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 2 UUID
+ */
+ public function uuid2(
+ int $localDomain,
+ ?IntegerObject $localIdentifier = null,
+ ?Hexadecimal $node = null,
+ ?int $clockSeq = null
+ ): UuidInterface;
+
+ /**
+ * Returns a version 3 (name-based) UUID based on the MD5 hash of a
+ * namespace ID and a name
+ *
+ * @param non-empty-string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param string $name The name to use for creating a UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 3 UUID
+ *
+ * @psalm-pure
+ */
+ public function uuid3(UuidInterface | string $ns, string $name): UuidInterface;
+
+ /**
+ * Returns a version 4 (random) UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 4 UUID
+ */
+ public function uuid4(): UuidInterface;
+
+ /**
+ * Returns a version 5 (name-based) UUID based on the SHA-1 hash of a
+ * namespace ID and a name
+ *
+ * @param non-empty-string|UuidInterface $ns The namespace (must be a valid UUID)
+ * @param string $name The name to use for creating a UUID
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 5 UUID
+ *
+ * @psalm-pure
+ */
+ public function uuid5(UuidInterface | string $ns, string $name): UuidInterface;
+
+ /**
+ * Returns a version 6 (reordered time) UUID from a host ID, sequence number,
+ * and the current time
+ *
+ * @param Hexadecimal|null $node A 48-bit number representing the hardware
+ * address
+ * @param int<0, 16383>|null $clockSeq A 14-bit number used to help avoid
+ * duplicates that could arise when the clock is set backwards in time
+ * or if the node ID changes
+ *
+ * @return UuidInterface A UuidInterface instance that represents a
+ * version 6 UUID
+ */
+ public function uuid6(?Hexadecimal $node = null, ?int $clockSeq = null): UuidInterface;
}
diff --git a/src/functions.php b/src/functions.php
index 7bc5fb4..4d5a04a 100644
--- a/src/functions.php
+++ b/src/functions.php
@@ -15,11 +15,12 @@ declare(strict_types=1);
namespace Ramsey\Uuid;
+use DateTimeInterface;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
/**
- * Returns a version 1 (time-based) UUID from a host ID, sequence number,
+ * Returns a version 1 (Gregorian time) UUID from a host ID, sequence number,
* and the current time
*
* @param Hexadecimal|positive-int|non-empty-string|null $node A 48-bit number
@@ -108,7 +109,7 @@ function v5(UuidInterface | string $ns, string $name): string
}
/**
- * Returns a version 6 (reordered-time) UUID from a host ID, sequence number,
+ * Returns a version 6 (reordered time) UUID from a host ID, sequence number,
* and the current time
*
* @param Hexadecimal|null $node A 48-bit number representing the hardware
@@ -123,3 +124,37 @@ function v6(?Hexadecimal $node = null, ?int $clockSeq = null): string
{
return Uuid::uuid6($node, $clockSeq)->toString();
}
+
+/**
+ * Returns a version 7 (Unix Epoch time) UUID
+ *
+ * @param DateTimeInterface|null $dateTime An optional date/time from which
+ * to create the version 7 UUID. If not provided, the UUID is generated
+ * using the current date/time.
+ *
+ * @return non-empty-string Version 7 UUID as a string
+ */
+function v7(?DateTimeInterface $dateTime = null): string
+{
+ return Uuid::uuid7($dateTime)->toString();
+}
+
+/**
+ * Returns a version 8 (custom) UUID
+ *
+ * The bytes provided may contain any value according to your application's
+ * needs. Be aware, however, that other applications may not understand the
+ * semantics of the value.
+ *
+ * @param string $bytes A 16-byte octet string. This is an open blob
+ * of data that you may fill with 128 bits of information. Be aware,
+ * however, bits 48 through 51 will be replaced with the UUID version
+ * field, and bits 64 and 65 will be replaced with the UUID variant. You
+ * MUST NOT rely on these bits for your application needs.
+ *
+ * @return non-empty-string Version 7 UUID as a string
+ */
+function v8(string $bytes): string
+{
+ return Uuid::uuid8($bytes)->toString();
+}
diff --git a/tests/Builder/FallbackBuilderTest.php b/tests/Builder/FallbackBuilderTest.php
index 2e605ee..6e87f5e 100644
--- a/tests/Builder/FallbackBuilderTest.php
+++ b/tests/Builder/FallbackBuilderTest.php
@@ -18,10 +18,10 @@ use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Nonstandard\UuidBuilder as NonstandardUuidBuilder;
-use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Rfc4122\UuidBuilder as Rfc4122UuidBuilder;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\Rfc4122\UuidV2;
+use Ramsey\Uuid\Rfc4122\UuidV6;
use Ramsey\Uuid\Test\TestCase;
class FallbackBuilderTest extends TestCase
diff --git a/tests/Converter/Time/UnixTimeConverterTest.php b/tests/Converter/Time/UnixTimeConverterTest.php
new file mode 100644
index 0000000..a8ecd8a
--- /dev/null
+++ b/tests/Converter/Time/UnixTimeConverterTest.php
@@ -0,0 +1,202 @@
+convertTime($uuidTimestamp);
+
+ $this->assertSame($unixTimestamp, $result->getSeconds()->toString());
+ $this->assertSame($microseconds, $result->getMicroseconds()->toString());
+ }
+
+ /**
+ * @return array
+ */
+ public function provideConvertTime(): array
+ {
+ return [
+ [
+ 'uuidTimestamp' => new Hexadecimal('017F22E279B0'),
+ 'unixTimestamp' => '1645557742',
+ 'microseconds' => '0',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('01384fc480fb'),
+ 'unixTimestamp' => '1341368074',
+ 'microseconds' => '491000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('016f8ca10161'),
+ 'unixTimestamp' => '1578612359',
+ 'microseconds' => '521000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('5dbe85111a5f'),
+ 'unixTimestamp' => '103072857659',
+ 'microseconds' => '999000',
+ ],
+
+ // This is the last possible time supported by v7 UUIDs (2 ^ 48 - 1).
+ // 10889-08-02 05:31:50.655 +00:00
+ [
+ 'uuidTimestamp' => new Hexadecimal('ffffffffffff'),
+ 'unixTimestamp' => '281474976710',
+ 'microseconds' => '655000',
+ ],
+
+ // This is the earliest possible date supported by v7 UUIDs.
+ // It is the Unix Epoch (big surprise!).
+ // 1970-01-01 00:00:00.0 +00:00
+ [
+ 'uuidTimestamp' => new Hexadecimal('000000000000'),
+ 'unixTimestamp' => '0',
+ 'microseconds' => '0',
+ ],
+
+ [
+ 'uuidTimestamp' => new Hexadecimal('000000000001'),
+ 'unixTimestamp' => '0',
+ 'microseconds' => '1000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('00000000000f'),
+ 'unixTimestamp' => '0',
+ 'microseconds' => '15000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('000000000064'),
+ 'unixTimestamp' => '0',
+ 'microseconds' => '100000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('0000000003e7'),
+ 'unixTimestamp' => '0',
+ 'microseconds' => '999000',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('0000000003e8'),
+ 'unixTimestamp' => '1',
+ 'microseconds' => '0',
+ ],
+ [
+ 'uuidTimestamp' => new Hexadecimal('0000000003e9'),
+ 'unixTimestamp' => '1',
+ 'microseconds' => '1000',
+ ],
+ ];
+ }
+
+ /**
+ * @param numeric-string $seconds
+ * @param numeric-string $microseconds
+ * @param non-empty-string $expected
+ *
+ * @dataProvider provideCalculateTime
+ */
+ public function testCalculateTime(string $seconds, string $microseconds, string $expected): void
+ {
+ $calculator = new BrickMathCalculator();
+ $converter = new UnixTimeConverter($calculator);
+
+ $result = $converter->calculateTime($seconds, $microseconds);
+
+ $this->assertSame($expected, $result->toString());
+ }
+
+ /**
+ * @return array
+ */
+ public function provideCalculateTime(): array
+ {
+ return [
+ [
+ 'seconds' => '1645557742',
+ 'microseconds' => '0',
+ 'expected' => '017f22e279b0',
+ ],
+ [
+ 'seconds' => '1341368074',
+ 'microseconds' => '491000',
+ 'expected' => '01384fc480fb',
+ ],
+ [
+ 'seconds' => '1578612359',
+ 'microseconds' => '521023',
+ 'expected' => '016f8ca10161',
+ ],
+ [
+ 'seconds' => '103072857659',
+ 'microseconds' => '999499',
+ 'expected' => '5dbe85111a5f',
+ ],
+ [
+ 'seconds' => '103072857659',
+ 'microseconds' => '999999',
+ 'expected' => '5dbe85111a5f',
+ ],
+
+ // This is the earliest possible date supported by v7 UUIDs.
+ // It is the Unix Epoch (big surprise!): 1970-01-01 00:00:00.0 +00:00
+ [
+ 'seconds' => '0',
+ 'microseconds' => '0',
+ 'expected' => '000000000000',
+ ],
+
+ // This is the last possible time supported by v7 UUIDs (2 ^ 48 - 1):
+ // 10889-08-02 05:31:50.655 +00:00
+ [
+ 'seconds' => '281474976710',
+ 'microseconds' => '655000',
+ 'expected' => 'ffffffffffff',
+ ],
+
+ [
+ 'seconds' => '0',
+ 'microseconds' => '1000',
+ 'expected' => '000000000001',
+ ],
+ [
+ 'seconds' => '0',
+ 'microseconds' => '15000',
+ 'expected' => '00000000000f',
+ ],
+ [
+ 'seconds' => '0',
+ 'microseconds' => '100000',
+ 'expected' => '000000000064',
+ ],
+ [
+ 'seconds' => '0',
+ 'microseconds' => '999000',
+ 'expected' => '0000000003e7',
+ ],
+ [
+ 'seconds' => '1',
+ 'microseconds' => '0',
+ 'expected' => '0000000003e8',
+ ],
+ [
+ 'seconds' => '1',
+ 'microseconds' => '1000',
+ 'expected' => '0000000003e9',
+ ],
+ ];
+ }
+}
diff --git a/tests/ExpectedBehaviorTest.php b/tests/ExpectedBehaviorTest.php
index 30efb99..30fbbe2 100644
--- a/tests/ExpectedBehaviorTest.php
+++ b/tests/ExpectedBehaviorTest.php
@@ -82,7 +82,7 @@ class ExpectedBehaviorTest extends TestCase
$this->assertSame(Variant::Rfc4122, $uuid->getFields()->getVariant());
$this->assertSame(Version::tryFrom((int) substr($method, -1)), $uuid->getFields()->getVersion());
- $this->assertTrue(ctype_digit((string) $uuid->getInteger()));
+ $this->assertSame(1, preg_match('/^\d+$/', (string) $uuid->getInteger()));
}
public function provideStaticCreationMethods()
@@ -149,6 +149,7 @@ class ExpectedBehaviorTest extends TestCase
// Non RFC 4122 UUIDs
['ffffffff-ffff-ffff-ffff-ffffffffffff', true],
+ ['00000000-0000-0000-0000-000000000000', true],
['ff6f8cb0-c57d-01e1-0b21-0800200c9a66', true],
['ff6f8cb0-c57d-01e1-1b21-0800200c9a66', true],
['ff6f8cb0-c57d-01e1-2b21-0800200c9a66', true],
@@ -285,7 +286,7 @@ class ExpectedBehaviorTest extends TestCase
public function provideFromStringInteger()
{
return [
- ['00000000-0000-0000-0000-000000000000', null, 0, '0'],
+ ['00000000-0000-0000-0000-000000000000', null, 2, '0'],
['ff6f8cb0-c57d-11e1-8b21-0800200c9a66', 1, 2, '339532337419071774304650190139318639206'],
['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 1, 2, '339532337419071774305803111643925486182'],
['ff6f8cb0-c57d-11e1-ab21-0800200c9a66', 1, 2, '339532337419071774306956033148532333158'],
@@ -318,7 +319,7 @@ class ExpectedBehaviorTest extends TestCase
['ff6f8cb0-c57d-01e1-db21-0800200c9a66', null, 6, '339532337419071698752551071748029454950'],
['ff6f8cb0-c57d-01e1-eb21-0800200c9a66', null, 7, '339532337419071698753703993252636301926'],
['ff6f8cb0-c57d-01e1-fb21-0800200c9a66', null, 7, '339532337419071698754856914757243148902'],
- ['ffffffff-ffff-ffff-ffff-ffffffffffff', null, 7, '340282366920938463463374607431768211455'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', null, 2, '340282366920938463463374607431768211455'],
];
}
@@ -566,6 +567,7 @@ class ExpectedBehaviorTest extends TestCase
['NAMESPACE_OID', '6ba7b812-9dad-11d1-80b4-00c04fd430c8'],
['NAMESPACE_X500', '6ba7b814-9dad-11d1-80b4-00c04fd430c8'],
['NIL', '00000000-0000-0000-0000-000000000000'],
+ ['MAX', 'ffffffff-ffff-ffff-ffff-ffffffffffff'],
];
}
}
diff --git a/tests/FeatureSetTest.php b/tests/FeatureSetTest.php
index 6d5888f..b69ef67 100644
--- a/tests/FeatureSetTest.php
+++ b/tests/FeatureSetTest.php
@@ -10,6 +10,7 @@ use Ramsey\Uuid\Converter\TimeConverterInterface;
use Ramsey\Uuid\FeatureSet;
use Ramsey\Uuid\Generator\DefaultNameGenerator;
use Ramsey\Uuid\Generator\PeclUuidTimeGenerator;
+use Ramsey\Uuid\Generator\UnixTimeGenerator;
use Ramsey\Uuid\Guid\GuidBuilder;
use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Provider\NodeProviderInterface;
@@ -77,4 +78,11 @@ class FeatureSetTest extends TestCase
$this->assertSame($nodeProvider, $featureSet->getNodeProvider());
}
+
+ public function testGetUnixTimeGenerator(): void
+ {
+ $featureSet = new FeatureSet();
+
+ $this->assertInstanceOf(UnixTimeGenerator::class, $featureSet->getUnixTimeGenerator());
+ }
}
diff --git a/tests/FunctionsTest.php b/tests/FunctionsTest.php
index 7b41b89..5cf2228 100644
--- a/tests/FunctionsTest.php
+++ b/tests/FunctionsTest.php
@@ -4,8 +4,12 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Test;
+use DateTimeImmutable;
+use DateTimeInterface;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
use Ramsey\Uuid\Rfc4122\UuidInterface;
+use Ramsey\Uuid\Rfc4122\UuidV7;
+use Ramsey\Uuid\Rfc4122\UuidV8;
use Ramsey\Uuid\Rfc4122\Version;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerObject;
@@ -17,6 +21,8 @@ use function Ramsey\Uuid\v3;
use function Ramsey\Uuid\v4;
use function Ramsey\Uuid\v5;
use function Ramsey\Uuid\v6;
+use function Ramsey\Uuid\v7;
+use function Ramsey\Uuid\v8;
class FunctionsTest extends TestCase
{
@@ -95,4 +101,51 @@ class FunctionsTest extends TestCase
$this->assertIsString($v6);
$this->assertSame(Version::ReorderedTime, $fields->getVersion());
}
+
+ public function testV7ReturnsVersion7UuidString(): void
+ {
+ $v7 = v7();
+
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::fromString($v7);
+
+ /** @var FieldsInterface $fields */
+ $fields = $uuid->getFields();
+
+ $this->assertIsString($v7);
+ $this->assertSame(Version::UnixTime, $fields->getVersion());
+ $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
+ }
+
+ public function testV7WithCustomDateTimeReturnsVersion7UuidString(): void
+ {
+ $dateTime = new DateTimeImmutable('2022-09-14T22:44:33+00:00');
+
+ $v7 = v7($dateTime);
+
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::fromString($v7);
+
+ /** @var FieldsInterface $fields */
+ $fields = $uuid->getFields();
+
+ $this->assertIsString($v7);
+ $this->assertSame(Version::UnixTime, $fields->getVersion());
+ $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
+ $this->assertSame(1663195473, $uuid->getDateTime()->getTimestamp());
+ }
+
+ public function testV8ReturnsVersion8UuidString(): void
+ {
+ $v8 = v8("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff");
+
+ /** @var UuidV8 $uuid */
+ $uuid = Uuid::fromString($v8);
+
+ /** @var FieldsInterface $fields */
+ $fields = $uuid->getFields();
+
+ $this->assertIsString($v8);
+ $this->assertSame(Version::Custom, $fields->getVersion());
+ }
}
diff --git a/tests/Generator/UnixTimeGeneratorTest.php b/tests/Generator/UnixTimeGeneratorTest.php
new file mode 100644
index 0000000..356f99f
--- /dev/null
+++ b/tests/Generator/UnixTimeGeneratorTest.php
@@ -0,0 +1,204 @@
+expects()->generate(16)->andReturns(
+ "\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00\xff\x00",
+ );
+
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator);
+
+ $bytes = $unixTimeGenerator->generate(null, null, $dateTime);
+
+ $this->assertSame($expectedBytes, $bytes);
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResults(): void
+ {
+ $randomGenerator = new RandomBytesGenerator();
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate();
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsWithSameDate(): void
+ {
+ $dateTime = new DateTimeImmutable('now');
+ $randomGenerator = new RandomBytesGenerator();
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate(null, null, $dateTime);
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsFor32BitPath(): void
+ {
+ $randomGenerator = new RandomBytesGenerator();
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate();
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsWithSameDateFor32BitPath(): void
+ {
+ $dateTime = new DateTimeImmutable('now');
+ $randomGenerator = new RandomBytesGenerator();
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate(null, null, $dateTime);
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSet(): void
+ {
+ /** @var RandomGeneratorInterface&MockInterface $randomGenerator */
+ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class);
+ $randomGenerator->expects()->generate(16)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+ $randomGenerator->expects()->generate(10)->times(24)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate();
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetWithSameDate(): void
+ {
+ $dateTime = new DateTimeImmutable('now');
+
+ /** @var RandomGeneratorInterface&MockInterface $randomGenerator */
+ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class);
+ $randomGenerator->expects()->generate(16)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+ $randomGenerator->expects()->generate(10)->times(24)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate(null, null, $dateTime);
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetFor32BitPath(): void
+ {
+ /** @var RandomGeneratorInterface&MockInterface $randomGenerator */
+ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class);
+ $randomGenerator->expects()->generate(16)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+ $randomGenerator->expects()->generate(10)->times(24)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate();
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+
+ /**
+ * @runInSeparateProcess since values are stored statically on the class
+ * @preserveGlobalState disabled
+ */
+ public function testGenerateProducesMonotonicResultsStartingWithAllBitsSetWithSameDateFor32BitPath(): void
+ {
+ $dateTime = new DateTimeImmutable('now');
+
+ /** @var RandomGeneratorInterface&MockInterface $randomGenerator */
+ $randomGenerator = Mockery::mock(RandomGeneratorInterface::class);
+ $randomGenerator->expects()->generate(16)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+ $randomGenerator->expects()->generate(10)->times(24)->andReturns(
+ "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
+ );
+
+ $unixTimeGenerator = new UnixTimeGenerator($randomGenerator, 4);
+
+ $previous = '';
+ for ($i = 0; $i < 25; $i++) {
+ $bytes = $unixTimeGenerator->generate(null, null, $dateTime);
+ $this->assertTrue($bytes > $previous);
+ }
+ }
+}
diff --git a/tests/Guid/FieldsTest.php b/tests/Guid/FieldsTest.php
index b62984a..e4065b3 100644
--- a/tests/Guid/FieldsTest.php
+++ b/tests/Guid/FieldsTest.php
@@ -93,9 +93,13 @@ class FieldsTest extends TestCase
// representations, which are never in GUID byte order.
return [
['b08c6fff7dc5e1018b210800200c9a66'],
- ['b08c6fff7dc5e1719b210800200c9a66'],
- ['b08c6fff7dc5e181ab210800200c9a66'],
['b08c6fff7dc5e191bb210800200c9a66'],
+ ['b08c6fff7dc5e1a19b210800200c9a66'],
+ ['b08c6fff7dc5e1b1ab210800200c9a66'],
+ ['b08c6fff7dc5e1c1ab210800200c9a66'],
+ ['b08c6fff7dc5e1d1ab210800200c9a66'],
+ ['b08c6fff7dc5e1e1ab210800200c9a66'],
+ ['b08c6fff7dc5e1f1ab210800200c9a66'],
];
}
@@ -141,6 +145,7 @@ class FieldsTest extends TestCase
['b08c6fff7dc5e111cb210800200c9a66', 'getVariant', Variant::ReservedMicrosoft],
['b08c6fff7dc5e111cb210800200c9a66', 'getVersion', Version::Time],
['b08c6fff7dc5e111cb210800200c9a66', 'isNil', false],
+ ['b08c6fff7dc5e111cb210800200c9a66', 'isMax', false],
// For ff6f8cb0-c57d-41e1-db21-0800200c9a66
['b08c6fff7dc5e141db210800200c9a66', 'getClockSeq', '1b21'],
@@ -154,6 +159,7 @@ class FieldsTest extends TestCase
['b08c6fff7dc5e141db210800200c9a66', 'getVariant', Variant::ReservedMicrosoft],
['b08c6fff7dc5e141db210800200c9a66', 'getVersion', Version::Random],
['b08c6fff7dc5e141db210800200c9a66', 'isNil', false],
+ ['b08c6fff7dc5e141db210800200c9a66', 'isMax', false],
// For ff6f8cb0-c57d-31e1-8b21-0800200c9a66
['b08c6fff7dc5e1318b210800200c9a66', 'getClockSeq', '0b21'],
@@ -167,6 +173,7 @@ class FieldsTest extends TestCase
['b08c6fff7dc5e1318b210800200c9a66', 'getVariant', Variant::Rfc4122],
['b08c6fff7dc5e1318b210800200c9a66', 'getVersion', Version::HashMd5],
['b08c6fff7dc5e1318b210800200c9a66', 'isNil', false],
+ ['b08c6fff7dc5e1318b210800200c9a66', 'isMax', false],
// For ff6f8cb0-c57d-51e1-9b21-0800200c9a66
['b08c6fff7dc5e1519b210800200c9a66', 'getClockSeq', '1b21'],
@@ -180,6 +187,7 @@ class FieldsTest extends TestCase
['b08c6fff7dc5e1519b210800200c9a66', 'getVariant', Variant::Rfc4122],
['b08c6fff7dc5e1519b210800200c9a66', 'getVersion', Version::HashSha1],
['b08c6fff7dc5e1519b210800200c9a66', 'isNil', false],
+ ['b08c6fff7dc5e1519b210800200c9a66', 'isMax', false],
// For 00000000-0000-0000-0000-000000000000
['00000000000000000000000000000000', 'getClockSeq', '0000'],
@@ -190,9 +198,24 @@ class FieldsTest extends TestCase
['00000000000000000000000000000000', 'getTimeLow', '00000000'],
['00000000000000000000000000000000', 'getTimeMid', '0000'],
['00000000000000000000000000000000', 'getTimestamp', '000000000000000'],
- ['00000000000000000000000000000000', 'getVariant', Variant::ReservedNcs],
+ ['00000000000000000000000000000000', 'getVariant', Variant::Rfc4122],
['00000000000000000000000000000000', 'getVersion', null],
['00000000000000000000000000000000', 'isNil', true],
+ ['00000000000000000000000000000000', 'isMax', false],
+
+ // For ffffffff-ffff-ffff-ffff-ffffffffffff
+ ['ffffffffffffffffffffffffffffffff', 'getClockSeq', 'ffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getClockSeqHiAndReserved', 'ff'],
+ ['ffffffffffffffffffffffffffffffff', 'getClockSeqLow', 'ff'],
+ ['ffffffffffffffffffffffffffffffff', 'getNode', 'ffffffffffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getTimeHiAndVersion', 'ffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getTimeLow', 'ffffffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getTimeMid', 'ffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getTimestamp', 'fffffffffffffff'],
+ ['ffffffffffffffffffffffffffffffff', 'getVariant', Variant::Rfc4122],
+ ['ffffffffffffffffffffffffffffffff', 'getVersion', null],
+ ['ffffffffffffffffffffffffffffffff', 'isNil', false],
+ ['ffffffffffffffffffffffffffffffff', 'isMax', true],
];
}
diff --git a/tests/Nonstandard/FieldsTest.php b/tests/Nonstandard/FieldsTest.php
index cbe377f..e4ac2ee 100644
--- a/tests/Nonstandard/FieldsTest.php
+++ b/tests/Nonstandard/FieldsTest.php
@@ -64,6 +64,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-91e1-0b21-0800200c9a66', 'getVariant', Variant::ReservedNcs],
['ff6f8cb0-c57d-91e1-0b21-0800200c9a66', 'getVersion', null],
['ff6f8cb0-c57d-91e1-0b21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-91e1-0b21-0800200c9a66', 'isMax', false],
];
}
diff --git a/tests/Nonstandard/UuidV6Test.php b/tests/Nonstandard/UuidV6Test.php
index d645abb..78d268c 100644
--- a/tests/Nonstandard/UuidV6Test.php
+++ b/tests/Nonstandard/UuidV6Test.php
@@ -38,7 +38,7 @@ class UuidV6Test extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage(
'Fields used to create a UuidV6 must represent a '
- . 'version 6 (ordered-time) UUID'
+ . 'version 6 (reordered time) UUID'
);
new UuidV6($fields, $numberConverter, $codec, $timeConverter);
diff --git a/tests/Provider/Node/SystemNodeProviderTest.php b/tests/Provider/Node/SystemNodeProviderTest.php
index cff8142..a0b292e 100644
--- a/tests/Provider/Node/SystemNodeProviderTest.php
+++ b/tests/Provider/Node/SystemNodeProviderTest.php
@@ -722,6 +722,7 @@ class SystemNodeProviderTest extends TestCase
'Without leading whitespace' => ['AA-BB-CC-DD-EE-FF '],
'Without trailing linebreak' => ["\nAA-BB-CC-DD-EE-FF"],
'Without trailing whitespace' => [' AA-BB-CC-DD-EE-FF'],
+ 'All zero MAC address' => ['00-00-00-00-00-00'],
];
}
@@ -741,6 +742,7 @@ class SystemNodeProviderTest extends TestCase
['01-23-45:67:89:ab'],
['01-23-45-67:89:ab'],
['01-23-45-67-89:ab'],
+ ['00:00:00:00:00:00'],
];
}
@@ -808,6 +810,10 @@ TXT
EHC29: flags=0<> mtu 0
XHC20: flags=0<> mtu 0
EHC26: flags=0<> mtu 0
+ aa0: flags=8863 mtu 1500
+ options=10b
+ ether 00:00:00:00:00:00
+ status: active
en0: flags=8863 mtu 1500
options=10b
ether 10:dd:b1:b4:e4:8e
@@ -874,6 +880,12 @@ TXT
WINS Proxy Enabled. . . . . . . . : No
DNS Suffix Search List. . . . . . : network.lan
+ Some kind of adapter:
+
+ Connection-specific DNS Suffix . : network.foo
+ Description . . . . . . . . . . . : Some Adapter
+ Physical Address. . . . . . . . . : 00-00-00-00-00-00
+
Ethernet adapter Ethernet:
Connection-specific DNS Suffix . : network.lan
@@ -906,6 +918,7 @@ TXT
],
'Full output - FreeBSD' => [<<<'TXT'
Name Mtu Network Address Ipkts Ierrs Idrop Opkts Oerrs Coll
+ aa0 0 00:00:00:00:00:00 0 0 0 0 0 0
em0 1500 08:00:27:71:a1:00 65514 0 0 42918 0 0
em1 1500 08:00:27:d0:60:a0 1199 0 0 535 0 0
lo0 16384 lo0 4 0 0 4 0 0
@@ -930,7 +943,6 @@ TXT
'FF:FF:FF:FF:FF:FF' => ["\nFF:FF:FF:FF:FF:FF\n", 'ffffffffffff'],
/* Incorrect variations that are also accepted */
- 'Local host' => ["\n00:00:00:00:00:00\n", '000000000000'],
'Too long -- extra character' => ["\nABC-01-23-45-67-89\n", 'bc0123456789'],
'Too long -- extra tuple' => ["\n01-AA-BB-CC-DD-EE-FF\n", '01aabbccddee'],
];
diff --git a/tests/Rfc4122/FieldsTest.php b/tests/Rfc4122/FieldsTest.php
index 9b7bd10..6d5ae9b 100644
--- a/tests/Rfc4122/FieldsTest.php
+++ b/tests/Rfc4122/FieldsTest.php
@@ -88,9 +88,13 @@ class FieldsTest extends TestCase
{
return [
['ff6f8cb0-c57d-01e1-8b21-0800200c9a66'],
- ['ff6f8cb0-c57d-71e1-9b21-0800200c9a66'],
- ['ff6f8cb0-c57d-81e1-ab21-0800200c9a66'],
['ff6f8cb0-c57d-91e1-bb21-0800200c9a66'],
+ ['ff6f8cb0-c57d-a1e1-9b21-0800200c9a66'],
+ ['ff6f8cb0-c57d-b1e1-ab21-0800200c9a66'],
+ ['ff6f8cb0-c57d-c1e1-ab21-0800200c9a66'],
+ ['ff6f8cb0-c57d-d1e1-ab21-0800200c9a66'],
+ ['ff6f8cb0-c57d-e1e1-ab21-0800200c9a66'],
+ ['ff6f8cb0-c57d-f1e1-ab21-0800200c9a66'],
];
}
@@ -132,6 +136,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 'getVariant', Variant::Rfc4122],
['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 'getVersion', Version::Time],
['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-11e1-9b21-0800200c9a66', 'isMax', false],
['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'getClockSeq', '2b21'],
['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'getClockSeqHiAndReserved', 'ab'],
@@ -144,6 +149,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'getVariant', Variant::Rfc4122],
['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'getVersion', Version::Random],
['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-41e1-ab21-0800200c9a66', 'isMax', false],
['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'getClockSeq', '3b21'],
['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'getClockSeqHiAndReserved', 'bb'],
@@ -156,6 +162,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'getVariant', Variant::Rfc4122],
['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'getVersion', Version::HashMd5],
['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-31e1-bb21-0800200c9a66', 'isMax', false],
['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'getClockSeq', '0b21'],
['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'getClockSeqHiAndReserved', '8b'],
@@ -168,6 +175,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'getVariant', Variant::Rfc4122],
['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'getVersion', Version::HashSha1],
['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-51e1-8b21-0800200c9a66', 'isMax', false],
['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'getClockSeq', '0b21'],
['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'getClockSeqHiAndReserved', '8b'],
@@ -180,6 +188,7 @@ class FieldsTest extends TestCase
['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'getVariant', Variant::Rfc4122],
['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'getVersion', Version::ReorderedTime],
['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'isNil', false],
+ ['ff6f8cb0-c57d-61e1-8b21-0800200c9a66', 'isMax', false],
['00000000-0000-0000-0000-000000000000', 'getClockSeq', '0000'],
['00000000-0000-0000-0000-000000000000', 'getClockSeqHiAndReserved', '00'],
@@ -189,9 +198,23 @@ class FieldsTest extends TestCase
['00000000-0000-0000-0000-000000000000', 'getTimeLow', '00000000'],
['00000000-0000-0000-0000-000000000000', 'getTimeMid', '0000'],
['00000000-0000-0000-0000-000000000000', 'getTimestamp', '000000000000000'],
- ['00000000-0000-0000-0000-000000000000', 'getVariant', Variant::ReservedNcs],
+ ['00000000-0000-0000-0000-000000000000', 'getVariant', Variant::Rfc4122],
['00000000-0000-0000-0000-000000000000', 'getVersion', null],
['00000000-0000-0000-0000-000000000000', 'isNil', true],
+ ['00000000-0000-0000-0000-000000000000', 'isMax', false],
+
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getClockSeq', 'ffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getClockSeqHiAndReserved', 'ff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getClockSeqLow', 'ff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getNode', 'ffffffffffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getTimeHiAndVersion', 'ffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getTimeLow', 'ffffffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getTimeMid', 'ffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getTimestamp', 'fffffffffffffff'],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getVariant', Variant::Rfc4122],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'getVersion', null],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'isNil', false],
+ ['ffffffff-ffff-ffff-ffff-ffffffffffff', 'isMax', true],
['000001f5-5cde-21ea-8400-0242ac130003', 'getClockSeq', '0400'],
['000001f5-5cde-21ea-8400-0242ac130003', 'getClockSeqHiAndReserved', '84'],
@@ -204,6 +227,20 @@ class FieldsTest extends TestCase
['000001f5-5cde-21ea-8400-0242ac130003', 'getVariant', Variant::Rfc4122],
['000001f5-5cde-21ea-8400-0242ac130003', 'getVersion', Version::DceSecurity],
['000001f5-5cde-21ea-8400-0242ac130003', 'isNil', false],
+ ['000001f5-5cde-21ea-8400-0242ac130003', 'isMax', false],
+
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getClockSeq', '1b21'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getClockSeqHiAndReserved', '9b'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getClockSeqLow', '21'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getNode', '0800200c9a66'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getTimeHiAndVersion', '71e1'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getTimeLow', '018339f0'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getTimeMid', '1b83'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getTimestamp', '000018339f01b83'],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getVariant', Variant::Rfc4122],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'getVersion', Version::UnixTime],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'isNil', false],
+ ['018339f0-1b83-71e1-9b21-0800200c9a66', 'isMax', false],
];
}
diff --git a/tests/Rfc4122/UuidBuilderTest.php b/tests/Rfc4122/UuidBuilderTest.php
index fa743c0..d2ac79c 100644
--- a/tests/Rfc4122/UuidBuilderTest.php
+++ b/tests/Rfc4122/UuidBuilderTest.php
@@ -9,14 +9,19 @@ use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
use Ramsey\Uuid\Converter\Time\GenericTimeConverter;
use Ramsey\Uuid\Exception\UnableToBuildUuidException;
use Ramsey\Uuid\Math\BrickMathCalculator;
-use Ramsey\Uuid\Nonstandard\UuidV6;
+use Ramsey\Uuid\Nonstandard\UuidV6 as NonstandardUuidV6;
use Ramsey\Uuid\Rfc4122\Fields;
+use Ramsey\Uuid\Rfc4122\MaxUuid;
+use Ramsey\Uuid\Rfc4122\NilUuid;
use Ramsey\Uuid\Rfc4122\UuidBuilder;
use Ramsey\Uuid\Rfc4122\UuidV1;
use Ramsey\Uuid\Rfc4122\UuidV2;
use Ramsey\Uuid\Rfc4122\UuidV3;
use Ramsey\Uuid\Rfc4122\UuidV4;
use Ramsey\Uuid\Rfc4122\UuidV5;
+use Ramsey\Uuid\Rfc4122\UuidV6;
+use Ramsey\Uuid\Rfc4122\UuidV7;
+use Ramsey\Uuid\Rfc4122\UuidV8;
use Ramsey\Uuid\Rfc4122\Version;
use Ramsey\Uuid\Test\TestCase;
@@ -30,7 +35,7 @@ class UuidBuilderTest extends TestCase
*
* @dataProvider provideBuildTestValues
*/
- public function testBuild(string $uuid, string $expectedClass, Version $expectedVersion): void
+ public function testBuild(string $uuid, string $expectedClass, ?Version $expectedVersion): void
{
/** @var non-empty-string $bytes */
$bytes = (string) hex2bin(str_replace('-', '', $uuid));
@@ -56,6 +61,16 @@ class UuidBuilderTest extends TestCase
public function provideBuildTestValues(): array
{
return [
+ [
+ 'uuid' => '00000000-0000-0000-0000-000000000000',
+ 'expectedClass' => NilUuid::class,
+ 'expectedVersion' => null,
+ ],
+ [
+ 'uuid' => 'ffffffff-ffff-ffff-ffff-ffffffffffff',
+ 'expectedClass' => MaxUuid::class,
+ 'expectedVersion' => null,
+ ],
[
'uuid' => 'ff6f8cb0-c57d-11e1-9b21-0800200c9a66',
'expectedClass' => UuidV1::class,
@@ -86,6 +101,26 @@ class UuidBuilderTest extends TestCase
'expectedClass' => UuidV6::class,
'expectedVersion' => Version::ReorderedTime,
],
+
+ // The same UUIDv6 will also be of the expected class type
+ // \Ramsey\Uuid\Nonstandard\UuidV6.
+ [
+ 'uuid' => 'ff6f8cb0-c57d-61e1-9b21-0800200c9a66',
+ 'expectedClass' => NonstandardUuidV6::class,
+ 'expectedVersion' => Version::ReorderedTime,
+ ],
+
+ [
+ 'uuid' => 'ff6f8cb0-c57d-71e1-9b21-0800200c9a66',
+ 'expectedClass' => UuidV7::class,
+ 'expectedVersion' => Version::UnixTime,
+ ],
+
+ [
+ 'uuid' => 'ff6f8cb0-c57d-81e1-9b21-0800200c9a66',
+ 'expectedClass' => UuidV8::class,
+ 'expectedVersion' => Version::Custom,
+ ],
];
}
diff --git a/tests/Rfc4122/UuidV6Test.php b/tests/Rfc4122/UuidV6Test.php
new file mode 100644
index 0000000..f5f3657
--- /dev/null
+++ b/tests/Rfc4122/UuidV6Test.php
@@ -0,0 +1,221 @@
+ $version,
+ ]);
+
+ $numberConverter = Mockery::mock(NumberConverterInterface::class);
+ $codec = Mockery::mock(CodecInterface::class);
+ $timeConverter = Mockery::mock(TimeConverterInterface::class);
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Fields used to create a UuidV6 must represent a '
+ . 'version 6 (reordered time) UUID'
+ );
+
+ new UuidV6($fields, $numberConverter, $codec, $timeConverter);
+ }
+
+ /**
+ * @return array
+ */
+ public function provideTestVersions(): array
+ {
+ return [
+ ['version' => Version::Time],
+ ['version' => Version::DceSecurity],
+ ['version' => Version::HashMd5],
+ ['version' => Version::Random],
+ ['version' => Version::HashSha1],
+ ['version' => Version::UnixTime],
+ ['version' => Version::Custom],
+ ];
+ }
+
+ /**
+ * @param non-empty-string $uuid
+ *
+ * @dataProvider provideUuidV6WithOddMicroseconds
+ */
+ public function testGetDateTimeProperlyHandlesLongMicroseconds(string $uuid, string $expected): void
+ {
+ /** @var UuidV6 $object */
+ $object = Uuid::fromString($uuid);
+
+ $date = $object->getDateTime();
+
+ $this->assertInstanceOf(DateTimeImmutable::class, $date);
+ $this->assertSame($expected, $date->format('U.u'));
+ }
+
+ /**
+ * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
+ */
+ public function provideUuidV6WithOddMicroseconds(): array
+ {
+ return [
+ [
+ 'uuid' => '1b21dd21-4814-6000-9669-00007ffffffe',
+ 'expected' => '1.677722',
+ ],
+ [
+ 'uuid' => '1b21dd21-3714-6000-9669-00007ffffffe',
+ 'expected' => '0.104858',
+ ],
+ [
+ 'uuid' => '1b21dd21-3713-6000-9669-00007ffffffe',
+ 'expected' => '0.105267',
+ ],
+ [
+ 'uuid' => '1b21dd21-2e8a-6980-8d4f-acde48001122',
+ 'expected' => '-1.000000',
+ ],
+ ];
+ }
+
+ /**
+ * @param non-empty-string $uuidv6
+ * @param non-empty-string $uuidv1
+ *
+ * @dataProvider provideUuidV1UuidV6Equivalents
+ */
+ public function testToUuidV1(string $uuidv6, string $uuidv1): void
+ {
+ /** @var UuidV6 $uuid6 */
+ $uuid6 = Uuid::fromString($uuidv6);
+ $uuid1 = $uuid6->toUuidV1();
+
+ $this->assertSame($uuidv6, $uuid6->toString());
+ $this->assertSame($uuidv1, $uuid1->toString());
+
+ $this->assertSame(
+ $uuid6->getDateTime()->format('U.u'),
+ $uuid1->getDateTime()->format('U.u')
+ );
+ }
+
+ /**
+ * @param non-empty-string $uuidv6
+ * @param non-empty-string $uuidv1
+ *
+ * @dataProvider provideUuidV1UuidV6Equivalents
+ */
+ public function testFromUuidV1(string $uuidv6, string $uuidv1): void
+ {
+ /** @var LazyUuidFromString $uuid */
+ $uuid = Uuid::fromString($uuidv1);
+ $uuid1 = $uuid->toUuidV1();
+ $uuid6 = UuidV6::fromUuidV1($uuid1);
+
+ $this->assertSame($uuidv1, $uuid1->toString());
+ $this->assertSame($uuidv6, $uuid6->toString());
+
+ $this->assertSame(
+ $uuid1->getDateTime()->format('U.u'),
+ $uuid6->getDateTime()->format('U.u')
+ );
+ }
+
+ /**
+ * @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint.MissingTraversableTypeHintSpecification
+ */
+ public function provideUuidV1UuidV6Equivalents(): array
+ {
+ return [
+ [
+ 'uuidv6' => '1b21dd21-4814-6000-9669-00007ffffffe',
+ 'uuidv1' => '14814000-1dd2-11b2-9669-00007ffffffe',
+ ],
+ [
+ 'uuidv6' => '1b21dd21-3714-6000-9669-00007ffffffe',
+ 'uuidv1' => '13714000-1dd2-11b2-9669-00007ffffffe',
+ ],
+ [
+ 'uuidv6' => '1b21dd21-3713-6000-9669-00007ffffffe',
+ 'uuidv1' => '13713000-1dd2-11b2-9669-00007ffffffe',
+ ],
+ [
+ 'uuidv6' => '1b21dd21-2e8a-6980-8d4f-acde48001122',
+ 'uuidv1' => '12e8a980-1dd2-11b2-8d4f-acde48001122',
+ ],
+ ];
+ }
+
+ public function testGetDateTimeThrowsException(): void
+ {
+ $fields = Mockery::mock(FieldsInterface::class, [
+ 'getVersion' => Version::ReorderedTime,
+ 'getTimestamp' => new Hexadecimal('0'),
+ ]);
+
+ $numberConverter = Mockery::mock(NumberConverterInterface::class);
+ $codec = Mockery::mock(CodecInterface::class);
+
+ $timeConverter = Mockery::mock(TimeConverterInterface::class, [
+ 'convertTime' => new Time('0', '1234567'),
+ ]);
+
+ $uuid = new UuidV6($fields, $numberConverter, $codec, $timeConverter);
+
+ $this->expectException(DateTimeException::class);
+
+ $uuid->getDateTime();
+ }
+
+ /**
+ * @link https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04#appendix-B.1
+ */
+ public function testUsingDraftPeabodyUuidV6TestVector(): void
+ {
+ $testVector = '1EC9414C-232A-6B00-B3C8-9E6BDECED846';
+
+ /** @var UuidV6 $uuidv6 */
+ $uuidv6 = Uuid::fromString($testVector);
+
+ $uuidv1 = $uuidv6->toUuidV1();
+
+ /** @var FieldsInterface $fields */
+ $fields = $uuidv6->getFields();
+
+ $this->assertSame('1ec9414c', $fields->getTimeLow()->toString());
+ $this->assertSame('232a', $fields->getTimeMid()->toString());
+ $this->assertSame('6b00', $fields->getTimeHiAndVersion()->toString());
+ $this->assertSame('b3', $fields->getClockSeqHiAndReserved()->toString());
+ $this->assertSame('c8', $fields->getClockSeqLow()->toString());
+ $this->assertSame('9e6bdeced846', $fields->getNode()->toString());
+ $this->assertSame(1645557742, $uuidv6->getDateTime()->getTimestamp());
+
+ $this->assertSame(
+ 'c232ab00-9414-11ec-b3c8-9e6bdeced846',
+ $uuidv1->toString(),
+ );
+ }
+}
diff --git a/tests/Rfc4122/UuidV7Test.php b/tests/Rfc4122/UuidV7Test.php
new file mode 100644
index 0000000..09c8e6f
--- /dev/null
+++ b/tests/Rfc4122/UuidV7Test.php
@@ -0,0 +1,131 @@
+ $version,
+ ]);
+
+ $numberConverter = Mockery::mock(NumberConverterInterface::class);
+ $codec = Mockery::mock(CodecInterface::class);
+ $timeConverter = Mockery::mock(TimeConverterInterface::class);
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Fields used to create a UuidV7 must represent a '
+ . 'version 7 (Unix Epoch time) UUID'
+ );
+
+ new UuidV7($fields, $numberConverter, $codec, $timeConverter);
+ }
+
+ /**
+ * @return array
+ */
+ public function provideTestVersions(): array
+ {
+ return [
+ ['version' => Version::Time],
+ ['version' => Version::DceSecurity],
+ ['version' => Version::HashMd5],
+ ['version' => Version::Random],
+ ['version' => Version::HashSha1],
+ ['version' => Version::ReorderedTime],
+ ['version' => Version::Custom],
+ ];
+ }
+
+ /**
+ * @param non-empty-string $uuid
+ *
+ * @dataProvider provideUuidV7WithMicroseconds
+ */
+ public function testGetDateTimeProperlyHandlesMicroseconds(string $uuid, string $expected): void
+ {
+ /** @var UuidV7 $object */
+ $object = Uuid::fromString($uuid);
+
+ $date = $object->getDateTime();
+
+ $this->assertInstanceOf(DateTimeImmutable::class, $date);
+ $this->assertSame($expected, $date->format('U.u'));
+ }
+
+ /**
+ * @return array
+ */
+ public function provideUuidV7WithMicroseconds(): array
+ {
+ return [
+ [
+ 'uuid' => '00000000-0001-71b2-9669-00007ffffffe',
+ 'expected' => '0.001000',
+ ],
+ [
+ 'uuid' => '00000000-000f-71b2-9669-00007ffffffe',
+ 'expected' => '0.015000',
+ ],
+ [
+ 'uuid' => '00000000-0064-71b2-9669-00007ffffffe',
+ 'expected' => '0.100000',
+ ],
+ [
+ 'uuid' => '00000000-03e7-71b2-9669-00007ffffffe',
+ 'expected' => '0.999000',
+ ],
+ [
+ 'uuid' => '00000000-03e8-71b2-9669-00007ffffffe',
+ 'expected' => '1.000000',
+ ],
+ [
+ 'uuid' => '00000000-03e9-71b2-9669-00007ffffffe',
+ 'expected' => '1.001000',
+ ],
+ ];
+ }
+
+ public function testGetDateTimeThrowsException(): void
+ {
+ $fields = Mockery::mock(FieldsInterface::class, [
+ 'getVersion' => Version::UnixTime,
+ 'getTimestamp' => new Hexadecimal('0'),
+ ]);
+
+ $numberConverter = Mockery::mock(NumberConverterInterface::class);
+ $codec = Mockery::mock(CodecInterface::class);
+
+ $timeConverter = Mockery::mock(TimeConverterInterface::class, [
+ 'convertTime' => new Time('0', '1234567'),
+ ]);
+
+ $uuid = new UuidV7($fields, $numberConverter, $codec, $timeConverter);
+
+ $this->expectException(DateTimeException::class);
+
+ $uuid->getDateTime();
+ }
+}
diff --git a/tests/Rfc4122/UuidV8Test.php b/tests/Rfc4122/UuidV8Test.php
new file mode 100644
index 0000000..97cbe97
--- /dev/null
+++ b/tests/Rfc4122/UuidV8Test.php
@@ -0,0 +1,56 @@
+ $version,
+ ]);
+
+ $numberConverter = Mockery::mock(NumberConverterInterface::class);
+ $codec = Mockery::mock(CodecInterface::class);
+ $timeConverter = Mockery::mock(TimeConverterInterface::class);
+
+ $this->expectException(InvalidArgumentException::class);
+ $this->expectExceptionMessage(
+ 'Fields used to create a UuidV8 must represent a '
+ . 'version 8 (custom) UUID'
+ );
+
+ new UuidV8($fields, $numberConverter, $codec, $timeConverter);
+ }
+
+ /**
+ * @return array
+ */
+ public function provideTestVersions(): array
+ {
+ return [
+ ['version' => Version::Time],
+ ['version' => Version::DceSecurity],
+ ['version' => Version::HashMd5],
+ ['version' => Version::Random],
+ ['version' => Version::HashSha1],
+ ['version' => Version::ReorderedTime],
+ ['version' => Version::UnixTime],
+ ];
+ }
+}
diff --git a/tests/Rfc4122/ValidatorTest.php b/tests/Rfc4122/ValidatorTest.php
index e8b9770..b3b2e8a 100644
--- a/tests/Rfc4122/ValidatorTest.php
+++ b/tests/Rfc4122/ValidatorTest.php
@@ -30,7 +30,15 @@ class ValidatorTest extends TestCase
$validator = new Validator();
foreach ($variations as $variation) {
- $this->assertSame($expected, $validator->validate($variation));
+ $this->assertSame(
+ $expected,
+ $validator->validate($variation),
+ sprintf(
+ 'Expected "%s" to be %s',
+ $variation,
+ $expected ? 'valid' : 'not valid',
+ ),
+ );
}
}
@@ -40,7 +48,7 @@ class ValidatorTest extends TestCase
public function provideValuesForValidation(): array
{
$hexMutations = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
- $trueVersions = [1, 2, 3, 4, 5];
+ $trueVersions = [1, 2, 3, 4, 5, 6, 7, 8];
$trueVariants = [8, 9, 'a', 'b'];
$testValues = [];
@@ -87,13 +95,25 @@ class ValidatorTest extends TestCase
'value' => "\nff6f8cb0-c57d-11e1-1b21-0800200c9a66\n",
'expected' => false,
],
+ [
+ 'value' => '00000000-0000-0000-0000-000000000000',
+ 'expected' => true,
+ ],
+ [
+ 'value' => 'ffffffff-ffff-ffff-ffff-ffffffffffff',
+ 'expected' => true,
+ ],
+ [
+ 'value' => 'FFFFFFFF-FFFF-FFFF-FFFF-FFFFFFFFFFFF',
+ 'expected' => true,
+ ],
]);
}
public function testGetPattern(): void
{
$expectedPattern = '\A[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-'
- . '[1-5]{1}[0-9A-Fa-f]{3}-[ABab89]{1}[0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
+ . '[1-8][0-9A-Fa-f]{3}-[ABab89][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}\z';
$validator = new Validator();
diff --git a/tests/Rfc4122/VariantTraitTest.php b/tests/Rfc4122/VariantTraitTest.php
index 0c5acdc..baf3d80 100644
--- a/tests/Rfc4122/VariantTraitTest.php
+++ b/tests/Rfc4122/VariantTraitTest.php
@@ -24,6 +24,8 @@ class VariantTraitTest extends TestCase
/** @var Fields $trait */
$trait = Mockery::mock(VariantTrait::class, [
'getBytes' => $bytes,
+ 'isMax' => false,
+ 'isNil' => false,
]);
$this->expectException(InvalidBytesException::class);
@@ -53,6 +55,8 @@ class VariantTraitTest extends TestCase
/** @var Fields $trait */
$trait = Mockery::mock(VariantTrait::class, [
'getBytes' => $bytes,
+ 'isMax' => false,
+ 'isNil' => false,
]);
$this->assertSame(Variant::from($expectedVariant), $trait->getVariant());
diff --git a/tests/Type/TimeTest.php b/tests/Type/TimeTest.php
index 6adad44..ac21e29 100644
--- a/tests/Type/TimeTest.php
+++ b/tests/Type/TimeTest.php
@@ -26,9 +26,9 @@ class TimeTest extends TestCase
if ($microseconds !== null) {
$params[] = $microseconds;
- $timeString .= ".{$microseconds}";
+ $timeString .= sprintf('.%06s', (string) $microseconds);
} else {
- $timeString .= '.0';
+ $timeString .= '.000000';
}
$time = new Time(...$params);
diff --git a/tests/UuidFactoryTest.php b/tests/UuidFactoryTest.php
index 8a0a06d..671d18e 100644
--- a/tests/UuidFactoryTest.php
+++ b/tests/UuidFactoryTest.php
@@ -68,6 +68,7 @@ class UuidFactoryTest extends TestCase
$randomGenerator = Mockery::mock(RandomGeneratorInterface::class);
$timeConverter = Mockery::mock(TimeConverterInterface::class);
$timeGenerator = Mockery::mock(TimeGeneratorInterface::class);
+ $unixTimeGenerator = Mockery::mock(TimeGeneratorInterface::class);
$nameGenerator = Mockery::mock(NameGeneratorInterface::class);
$dceSecurityGenerator = Mockery::mock(DceSecurityGeneratorInterface::class);
$numberConverter = Mockery::mock(NumberConverterInterface::class);
@@ -85,6 +86,7 @@ class UuidFactoryTest extends TestCase
'getNumberConverter' => $numberConverter,
'getBuilder' => $builder,
'getValidator' => $validator,
+ 'getUnixTimeGenerator' => $unixTimeGenerator,
]);
$uuidFactory = new UuidFactory($featureSet);
diff --git a/tests/UuidTest.php b/tests/UuidTest.php
index 3d93305..9f53248 100644
--- a/tests/UuidTest.php
+++ b/tests/UuidTest.php
@@ -4,12 +4,20 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Test;
+use BadMethodCallException;
use Brick\Math\BigDecimal;
use Brick\Math\RoundingMode;
+use DateTimeImmutable;
use DateTimeInterface;
+use Mockery;
+use Mockery\MockInterface;
use PHPUnit\Framework\MockObject\MockObject;
+use Ramsey\Uuid\Codec\StringCodec;
use Ramsey\Uuid\Codec\TimestampFirstCombCodec;
use Ramsey\Uuid\Codec\TimestampLastCombCodec;
+use Ramsey\Uuid\Converter\Number\GenericNumberConverter;
+use Ramsey\Uuid\Converter\TimeConverterInterface;
+use Ramsey\Uuid\Exception\DateTimeException;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Exception\InvalidUuidStringException;
use Ramsey\Uuid\Exception\UnsupportedOperationException;
@@ -19,16 +27,22 @@ use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
+use Ramsey\Uuid\Math\BrickMathCalculator;
use Ramsey\Uuid\Nonstandard\UuidV6;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
+use Ramsey\Uuid\Rfc4122\Fields;
use Ramsey\Uuid\Rfc4122\FieldsInterface;
+use Ramsey\Uuid\Rfc4122\UuidBuilder;
use Ramsey\Uuid\Rfc4122\UuidV1;
+use Ramsey\Uuid\Rfc4122\UuidV7;
+use Ramsey\Uuid\Rfc4122\UuidV8;
use Ramsey\Uuid\Rfc4122\Version;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Time;
use Ramsey\Uuid\Uuid;
use Ramsey\Uuid\UuidFactory;
+use Ramsey\Uuid\UuidFactoryInterface;
use Ramsey\Uuid\UuidInterface;
use Ramsey\Uuid\Validator\GenericValidator;
use Ramsey\Uuid\Validator\ValidatorInterface;
@@ -66,6 +80,37 @@ class UuidTest extends TestCase
);
}
+ public function testFromHexadecimal(): void
+ {
+ $hex = new Hexadecimal('0x1EA78DEB37CE625E8F1A025041000001');
+ $uuid = Uuid::fromHexadecimal($hex);
+ $this->assertInstanceOf(Uuid::class, $uuid);
+ $this->assertEquals('1ea78deb-37ce-625e-8f1a-025041000001', $uuid->toString());
+ }
+
+ public function testFromHexadecimalShort(): void
+ {
+ $hex = new Hexadecimal('0x1EA78DEB37CE625E8F1A0250410000');
+
+ $this->expectException(InvalidUuidStringException::class);
+ $this->expectExceptionMessage('Invalid UUID string:');
+
+ Uuid::fromHexadecimal($hex);
+ }
+
+ public function testFromHexadecimalThrowsWhenMethodDoesNotExist(): void
+ {
+ $factory = Mockery::mock(UuidFactoryInterface::class);
+ Uuid::setFactory($factory);
+
+ $hex = new Hexadecimal('0x1EA78DEB37CE625E8F1A025041000001');
+
+ $this->expectException(BadMethodCallException::class);
+ $this->expectExceptionMessage('The method fromHexadecimal() does not exist on the provided factory');
+
+ Uuid::fromHexadecimal($hex);
+ }
+
/**
* Tests that UUID and GUID's have the same textual representation but not
* the same binary representation.
@@ -141,6 +186,30 @@ class UuidTest extends TestCase
$this->assertInstanceOf(LazyUuidFromString::class, Uuid::fromString('FF6F8CB0-C57D-11E1-9B21-0800200C9A66'));
}
+ public function testFromStringWithNilUuid(): void
+ {
+ $uuid = Uuid::fromString(Uuid::NIL);
+
+ /** @var Fields $fields */
+ $fields = $uuid->getFields();
+
+ $this->assertSame('00000000-0000-0000-0000-000000000000', $uuid->toString());
+ $this->assertTrue($fields->isNil());
+ $this->assertFalse($fields->isMax());
+ }
+
+ public function testFromStringWithMaxUuid(): void
+ {
+ $uuid = Uuid::fromString(Uuid::MAX);
+
+ /** @var Fields $fields */
+ $fields = $uuid->getFields();
+
+ $this->assertSame('ffffffff-ffff-ffff-ffff-ffffffffffff', $uuid->toString());
+ $this->assertFalse($fields->isNil());
+ $this->assertTrue($fields->isMax());
+ }
+
public function testGetBytes(): void
{
$uuid = Uuid::fromString('ff6f8cb0-c57d-11e1-9b21-0800200c9a66');
@@ -616,6 +685,133 @@ class UuidTest extends TestCase
$this->assertSame(Version::ReorderedTime, $uuid->getFields()->getVersion());
}
+ public function testUuid7(): void
+ {
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7();
+ $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
+ $this->assertSame(Variant::Rfc4122, $uuid->getFields()->getVariant());
+ $this->assertSame(Version::UnixTime, $uuid->getFields()->getVersion());
+ }
+
+ public function testUuid7ThrowsExceptionForUnsupportedFactory(): void
+ {
+ /** @var UuidFactoryInterface&MockInterface $factory */
+ $factory = Mockery::mock(UuidFactoryInterface::class);
+
+ Uuid::setFactory($factory);
+
+ $this->expectException(UnsupportedOperationException::class);
+ $this->expectExceptionMessage('The provided factory does not support the uuid7() method');
+
+ Uuid::uuid7();
+ }
+
+ public function testUuid7WithDateTime(): void
+ {
+ $dateTime = new DateTimeImmutable('@281474976710.655');
+
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7($dateTime);
+ $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
+ $this->assertSame(Variant::Rfc4122, $uuid->getFields()->getVariant());
+ $this->assertSame(Version::UnixTime, $uuid->getFields()->getVersion());
+ $this->assertSame(
+ '10889-08-02T05:31:50.655+00:00',
+ $uuid->getDateTime()->format(DateTimeInterface::RFC3339_EXTENDED),
+ );
+ }
+
+ public function testUuid7SettingTheClockBackwards(): void
+ {
+ $dates = [
+ new DateTimeImmutable('now'),
+ new DateTimeImmutable('last year'),
+ new DateTimeImmutable('1979-01-01 00:00:00.000000'),
+ ];
+
+ foreach ($dates as $dateTime) {
+ /** @var UuidV7 $previous */
+ $previous = Uuid::uuid7($dateTime);
+
+ for ($i = 0; $i < 25; $i++) {
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7($dateTime);
+ $this->assertGreaterThan(0, $uuid->compareTo($previous));
+ $this->assertSame($dateTime->format('Y-m-d H:i'), $uuid->getDateTime()->format('Y-m-d H:i'));
+ $previous = $uuid;
+ }
+ }
+ }
+
+ public function testUuid7WithMinimumDateTime(): void
+ {
+ $dateTime = new DateTimeImmutable('1979-01-01 00:00:00.000000');
+
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7($dateTime);
+ $this->assertInstanceOf(DateTimeInterface::class, $uuid->getDateTime());
+ $this->assertSame(Variant::Rfc4122, $uuid->getFields()->getVariant());
+ $this->assertSame(Version::UnixTime, $uuid->getFields()->getVersion());
+
+ $this->assertSame(
+ '1979-01-01T00:00:00.000+00:00',
+ $uuid->getDateTime()->format(DateTimeInterface::RFC3339_EXTENDED),
+ );
+ }
+
+ public function testUuid7EachUuidIsMonotonicallyIncreasing(): void
+ {
+ /** @var UuidV7 $previous */
+ $previous = Uuid::uuid7();
+
+ for ($i = 0; $i < 25; $i++) {
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7();
+ $now = gmdate('Y-m-d H:i');
+ $this->assertGreaterThan(0, $uuid->compareTo($previous));
+ $this->assertSame($now, $uuid->getDateTime()->format('Y-m-d H:i'));
+ $previous = $uuid;
+ }
+ }
+
+ public function testUuid7EachUuidFromSameDateTimeIsMonotonicallyIncreasing(): void
+ {
+ $dateTime = new DateTimeImmutable();
+
+ /** @var UuidV7 $previous */
+ $previous = Uuid::uuid7($dateTime);
+
+ for ($i = 0; $i < 25; $i++) {
+ /** @var UuidV7 $uuid */
+ $uuid = Uuid::uuid7($dateTime);
+ $this->assertGreaterThan(0, $uuid->compareTo($previous));
+ $this->assertSame($dateTime->format('Y-m-d H:i'), $uuid->getDateTime()->format('Y-m-d H:i'));
+ $previous = $uuid;
+ }
+ }
+
+ public function testUuid8(): void
+ {
+ /** @var UuidV8 $uuid */
+ $uuid = Uuid::uuid8("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff");
+ $this->assertSame(Variant::Rfc4122, $uuid->getFields()->getVariant());
+ $this->assertSame(Version::Custom, $uuid->getFields()->getVersion());
+ }
+
+ public function testUuid8ThrowsExceptionForUnsupportedFactory(): void
+ {
+ /** @var UuidFactoryInterface&MockInterface $factory */
+ $factory = Mockery::mock(UuidFactoryInterface::class);
+
+ Uuid::setFactory($factory);
+
+ $this->expectException(UnsupportedOperationException::class);
+ $this->expectExceptionMessage('The provided factory does not support the uuid8() method');
+
+ Uuid::uuid8("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff");
+ }
+
/**
* Tests known version-3 UUIDs
*
@@ -1199,7 +1395,13 @@ class UuidTest extends TestCase
'urn' => 'urn:uuid:00000000-0000-0000-0000-000000000000',
'time' => '000000000000000',
'clock_seq' => '0000',
- 'variant' => Variant::ReservedNcs,
+ // This is a departure from the Python tests. The Python tests
+ // are technically "correct" because all bits are set to zero,
+ // so it stands to reason that the variant is also zero, but
+ // that leads to this being considered a "Reserved NCS" variant,
+ // and that is not the case. RFC 4122 defines this special UUID,
+ // so it is an RFC 4122 variant.
+ 'variant' => Variant::Rfc4122,
'version' => null,
],
[
@@ -1458,8 +1660,20 @@ class UuidTest extends TestCase
],
'urn' => 'urn:uuid:ffffffff-ffff-ffff-ffff-ffffffffffff',
'time' => 'fffffffffffffff',
- 'clock_seq' => '3fff',
- 'variant' => Variant::ReservedFuture,
+ // This is a departure from the Python tests. The Python tests
+ // are technically "correct" because all bits are set to one,
+ // which ends up calculating the variant as 7, or "Reserved
+ // Future," but that is not the case, and now that max UUIDs
+ // are defined as a special type, within the RFC 4122 variant
+ // rules, we also consider it an RFC 4122 variant.
+ //
+ // Similarly, Python's tests think the clock sequence should be
+ // 0x3fff because of the bit shifting performed on this field.
+ // However, since all the bits in this UUID are defined as being
+ // set to one, we will consider the clock sequence as 0xffff,
+ // which all bits set to one.
+ 'clock_seq' => 'ffff',
+ 'variant' => Variant::Rfc4122,
'version' => null,
],
];
@@ -1589,6 +1803,42 @@ class UuidTest extends TestCase
$this->assertSame($uuid->getFields()->getVersion(), Version::ReorderedTime);
}
+ public function testUuidVersionConstantForVersion7(): void
+ {
+ /** @var \Ramsey\Uuid\Rfc4122\UuidInterface $uuid */
+ $uuid = Uuid::fromString('886313e1-3b8a-7372-9b90-0c9aee199e5d');
+ $this->assertSame($uuid->getFields()->getVersion(), Version::UnixTime);
+ }
+
+ public function testGetDateTimeThrowsExceptionWhenDateTimeCannotParseDate(): void
+ {
+ $numberConverter = new GenericNumberConverter(new BrickMathCalculator());
+ $timeConverter = Mockery::mock(TimeConverterInterface::class);
+
+ $timeConverter
+ ->shouldReceive('convertTime')
+ ->once()
+ ->andReturn(new Time(1234567890, '1234567'));
+
+ $builder = new UuidBuilder($numberConverter, $timeConverter);
+ $codec = new StringCodec($builder);
+
+ $factory = new UuidFactory();
+ $factory->setCodec($codec);
+
+ $uuid = $factory->fromString('b1484596-25dc-11ea-978f-2e728ce88125');
+
+ $this->expectException(DateTimeException::class);
+ $this->expectExceptionMessage(
+ 'Failed to parse time string (@1234567890.1234567) at position 18 (7): Unexpected character'
+ );
+
+ /**
+ * @phpstan-ignore-next-line
+ */
+ $uuid->getDateTime();
+ }
+
/**
* @param mixed[] $args
*
diff --git a/tests/benchmark/GuidConversionBench.php b/tests/benchmark/GuidConversionBench.php
new file mode 100644
index 0000000..a11842a
--- /dev/null
+++ b/tests/benchmark/GuidConversionBench.php
@@ -0,0 +1,43 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Benchmark;
+
+use Ramsey\Uuid\FeatureSet;
+use Ramsey\Uuid\Guid\Guid;
+use Ramsey\Uuid\UuidFactory;
+use Ramsey\Uuid\UuidInterface;
+
+final class GuidConversionBench
+{
+ private const UUID_BYTES = [
+ "\x1e\x94\x42\x33\x98\x10\x41\x38\x96\x22\x56\xe1\xf9\x0c\x56\xed",
+ ];
+
+ private UuidInterface $uuid;
+
+ public function __construct()
+ {
+ $factory = new UuidFactory(new FeatureSet(useGuids: true));
+
+ $this->uuid = $factory->fromBytes(self::UUID_BYTES[0]);
+
+ assert($this->uuid instanceof Guid);
+ }
+
+ public function benchStringConversionOfGuid(): void
+ {
+ $this->uuid->toString();
+ }
+}
diff --git a/tests/benchmark/NonLazyUuidConversionBench.php b/tests/benchmark/NonLazyUuidConversionBench.php
new file mode 100644
index 0000000..32d0e66
--- /dev/null
+++ b/tests/benchmark/NonLazyUuidConversionBench.php
@@ -0,0 +1,39 @@
+
+ * @license http://opensource.org/licenses/MIT MIT
+ */
+
+declare(strict_types=1);
+
+namespace Ramsey\Uuid\Benchmark;
+
+use Ramsey\Uuid\UuidFactory;
+use Ramsey\Uuid\UuidInterface;
+
+final class NonLazyUuidConversionBench
+{
+ private const UUID_BYTES = [
+ "\x1e\x94\x42\x33\x98\x10\x41\x38\x96\x22\x56\xe1\xf9\x0c\x56\xed",
+ ];
+
+ private UuidInterface $uuid;
+
+ public function __construct()
+ {
+ $factory = new UuidFactory();
+
+ $this->uuid = $factory->fromBytes(self::UUID_BYTES[0]);
+ }
+
+ public function benchStringConversionOfUuid(): void
+ {
+ $this->uuid->toString();
+ }
+}
diff --git a/tests/benchmark/UuidGenerationBench.php b/tests/benchmark/UuidGenerationBench.php
index 88b1c19..bcacfa4 100644
--- a/tests/benchmark/UuidGenerationBench.php
+++ b/tests/benchmark/UuidGenerationBench.php
@@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Ramsey\Uuid\Benchmark;
+use DateTimeImmutable;
use Ramsey\Uuid\Provider\Node\StaticNodeProvider;
use Ramsey\Uuid\Type\Hexadecimal;
use Ramsey\Uuid\Type\Integer as IntegerIdentifier;
@@ -99,4 +100,14 @@ final class UuidGenerationBench
{
Uuid::uuid6($this->node, $this->clockSequence);
}
+
+ public function benchUuid7Generation(): void
+ {
+ Uuid::uuid7();
+ }
+
+ public function benchUuid7GenerationWithDateTime(): void
+ {
+ Uuid::uuid7(new DateTimeImmutable('@1663203901.667000'));
+ }
}