Skip to content

Commit 7ab4ae2

Browse files
authored
Merge pull request #16 from infocyph/feature/update
Fix+GUID
2 parents d83afd2 + 75d3207 commit 7ab4ae2

11 files changed

Lines changed: 105 additions & 40 deletions

README.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
![Packagist Version](https://img.shields.io/packagist/v/infocyph/uid)
88
![Packagist PHP Version Support](https://img.shields.io/packagist/php-v/infocyph/uid)
99
![GitHub code size in bytes](https://img.shields.io/github/languages/code-size/infocyph/uid)
10+
![visitors](https://visitor-badge.laobi.icu/badge?page_id=infocyph.com)
1011

1112
An AIO Unique ID generator written in PHP. Supports,
1213
- UUID (RFC 4122 + Unofficial/Draft)
@@ -172,6 +173,14 @@ $timeInterface = new DateTime(); // DateTime implements DateTimeInterface
172173
\Infocyph\UID\UUID::v8($node); // check additional section for, how to generate one
173174
```
174175

176+
#### GUID
177+
178+
GUID generator, works in all platform. Generate:
179+
```php
180+
\Infocyph\UID\UUID::guid()
181+
```
182+
_Note: Sending false in only parameter will return the string enclosed with Braces_
183+
175184
#### Additional
176185

177186
- Generate node for further use (with version: 1, 6, 7, 8)
@@ -212,7 +221,7 @@ $timeInterface = new DateTime(); // DateTime implements DateTimeInterface
212221
// alternatively
213222
\Infocyph\UID\snowflake();
214223
```
215-
- Parse Snowflake ID (get the timestamp, sequence, worker_id, datacenter_id from any Snowflake ID):
224+
- Parse Snowflake ID (get the timestamp, sequence, worker_id, datacenter_id):
216225
```php
217226
// Parse Snowflake ID
218227
// returns [time => DateTimeInterface object, sequence, worker_id, datacenter_id]
@@ -237,7 +246,7 @@ $timeInterface = new DateTime(); // DateTime implements DateTimeInterface
237246
// alternatively
238247
\Infocyph\UID\sonyflake();
239248
```
240-
- Parse Sonyflake ID (get the timestamp, sequence, machine_id from any Snowflake ID):
249+
- Parse Sonyflake ID (get the timestamp, sequence, machine_id):
241250

242251
```php
243252
// Parse Sonyflake ID

rector.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
declare(strict_types=1);
44

55
use Rector\Config\RectorConfig;
6+
use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector;
67
use Rector\TypeDeclaration\Rector\ClassMethod\AddVoidReturnTypeWhereNoReturnRector;
78

89
return static function (RectorConfig $rectorConfig): void {
@@ -12,4 +13,7 @@
1213
$rectorConfig->sets([
1314
constant("Rector\Set\ValueObject\LevelSetList::UP_TO_PHP_82")
1415
]);
16+
$rectorConfig->skip([
17+
StringClassNameToClassConstantRector::class
18+
]);
1519
};

src/GetSequence.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ private static function sequence(int $dateTime, string $machineId, string $type)
2323
touch(self::$fileLocation);
2424
}
2525
$handle = fopen(self::$fileLocation, "r+");
26-
if (!flock($handle, LOCK_EX)) {
27-
throw new FileLockException('Could not acquire lock on ' . self::$fileLocation);
28-
}
26+
flock($handle, LOCK_EX) || throw new FileLockException('Could not acquire lock on ' . self::$fileLocation);
2927
$line = fgetcsv($handle);
3028
$sequence = 0;
3129
if ($line && ($line[0] = (int)$line[0]) <= $dateTime) {

src/ULID.php

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,31 @@ public static function generate(?DateTimeInterface $dateTime = null): string
2828
{
2929
$time = (int)($dateTime ?? new DateTimeImmutable('now'))->format('Uv');
3030

31-
$isDuplicate = $time === static::$lastGenTime;
32-
static::$lastGenTime = $time;
31+
$isDuplicate = $time === self::$lastGenTime;
32+
self::$lastGenTime = $time;
3333

3434
// Generate time characters
3535
$timeChars = '';
36-
for ($i = static::$timeLength - 1; $i >= 0; $i--) {
37-
$mod = $time % static::$encodingLength;
38-
$timeChars = static::$encodingChars[$mod] . $timeChars;
39-
$time = ($time - $mod) / static::$encodingLength;
36+
for ($i = self::$timeLength - 1; $i >= 0; $i--) {
37+
$mod = $time % self::$encodingLength;
38+
$timeChars = self::$encodingChars[$mod] . $timeChars;
39+
$time = ($time - $mod) / self::$encodingLength;
4040
}
4141

4242
// Generate random characters
4343
$randChars = '';
4444
if (!$isDuplicate) {
45-
for ($i = 0; $i < static::$randomLength; $i++) {
46-
static::$lastRandChars[$i] = random_int(0, 31);
45+
for ($i = 0; $i < self::$randomLength; $i++) {
46+
self::$lastRandChars[$i] = random_int(0, 31);
4747
}
4848
} else {
49-
for ($i = static::$randomLength - 1; $i >= 0 && static::$lastRandChars[$i] === 31; $i--) {
50-
static::$lastRandChars[$i] = 0;
49+
for ($i = self::$randomLength - 1; $i >= 0 && self::$lastRandChars[$i] === 31; $i--) {
50+
self::$lastRandChars[$i] = 0;
5151
}
52-
static::$lastRandChars[$i]++;
52+
self::$lastRandChars[$i]++;
5353
}
54-
for ($i = 0; $i < static::$randomLength; $i++) {
55-
$randChars .= static::$encodingChars[static::$lastRandChars[$i]];
54+
for ($i = 0; $i < self::$randomLength; $i++) {
55+
$randChars .= self::$encodingChars[self::$lastRandChars[$i]];
5656
}
5757

5858
return $timeChars . $randChars;
@@ -67,19 +67,19 @@ public static function generate(?DateTimeInterface $dateTime = null): string
6767
*/
6868
public static function getTime(string $ulid): DateTimeImmutable
6969
{
70-
if (!static::isValid($ulid)) {
70+
if (!self::isValid($ulid)) {
7171
throw new ULIDException('Invalid ULID string');
7272
}
7373

74-
$timeChars = str_split(strrev(substr($ulid, 0, static::$timeLength)));
74+
$timeChars = str_split(strrev(substr($ulid, 0, self::$timeLength)));
7575

7676
$time = 0;
7777
foreach ($timeChars as $index => $char) {
78-
$encodingIndex = strripos(static::$encodingChars, $char);
79-
$time += ($encodingIndex * static::$encodingLength ** $index);
78+
$encodingIndex = strripos(self::$encodingChars, $char);
79+
$time += ($encodingIndex * self::$encodingLength ** $index);
8080
}
8181

82-
$time = str_split($time, static::$timeLength);
82+
$time = str_split($time, self::$timeLength);
8383

8484
if ($time[0] > (time() + (86400 * 365 * 10))) {
8585
throw new ULIDException('Invalid ULID string: timestamp too large');

src/UUID.php

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,27 @@ public static function v8(string $node = null): string
172172
return self::output(8, $string);
173173
}
174174

175+
/**
176+
* Generates a GUID (Globally Unique Identifier) string.
177+
*
178+
* @param bool $trim Whether to trim the curly braces from the GUID string. Default is true.
179+
* @return string The generated GUID string.
180+
* @throws Exception
181+
*/
182+
public static function guid(bool $trim = true): string
183+
{
184+
if (function_exists('com_create_guid') === true) {
185+
$data = com_create_guid();
186+
return $trim ? trim($data, '{}') : $data;
187+
}
188+
189+
$data = random_bytes(16);
190+
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
191+
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
192+
$data = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
193+
return $trim ? $data : "\{$data\}";
194+
}
195+
175196
/**
176197
* Generate unique node.
177198
*
@@ -192,9 +213,11 @@ public static function getNode(): string
192213
*/
193214
public static function parse(string $uuid): array
194215
{
216+
$uuid = trim($uuid, '{}');
195217
$data = [
196218
'isValid' => self::isValid($uuid),
197219
'version' => null,
220+
'variant' => null,
198221
'time' => null,
199222
'node' => null
200223
];
@@ -204,10 +227,17 @@ public static function parse(string $uuid): array
204227
}
205228

206229
$uuidData = explode('-', $uuid);
230+
$variantN = hexdec($uuidData[3][0]);
207231
$data['version'] = (int)$uuidData[2][0];
208232
$data['time'] = in_array($data['version'], [1, 6, 7, 8]) ? self::getTime($uuidData, $data['version']) : null;
209233
$data['node'] = $uuidData[4];
210-
234+
$data['variant'] = match (true) {
235+
$variantN <= 7 => 'NCS',
236+
$variantN >= 8 && $variantN <= 11 => 'DCE 1.1, ISO/IEC 11578:1996',
237+
$variantN === 12 || $variantN === 13 => 'Microsoft GUID',
238+
$variantN === 14 => 'Reserved',
239+
default => 'Unknown'
240+
};
211241
return $data;
212242
}
213243

@@ -235,7 +265,7 @@ private static function prepareNode(int $version, string $node = null): string
235265
*/
236266
private static function isValid(string $uuid): bool
237267
{
238-
return (bool)preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-\d[0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i', $uuid);
268+
return (bool)preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-\d[0-9a-f]{3}-[089a-e][0-9a-f]{3}-[0-9a-f]{12}$/i', $uuid);
239269
}
240270

241271
/**

src/functions.php

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,21 @@ function uuid8(string $node = null): string
108108
}
109109
}
110110

111-
if (!function_exists(\Infocyph\UID\ulid::class)) {
111+
if (!function_exists('Infocyph\UID\guid')) {
112+
/**
113+
* Generates a GUID (Globally Unique Identifier) string.
114+
*
115+
* @param bool $trim Whether to trim the curly braces from the GUID string. Default is true.
116+
* @return string The generated GUID string.
117+
* @throws Exception
118+
*/
119+
function guid(bool $trim = true): string
120+
{
121+
return UUID::guid($trim);
122+
}
123+
}
124+
125+
if (!function_exists('Infocyph\UID\ulid')) {
112126
/**
113127
* Generates ULID.
114128
*
@@ -122,7 +136,7 @@ function ulid(?DateTimeInterface $dateTime = null): string
122136
}
123137
}
124138

125-
if (!function_exists(\Infocyph\UID\snowflake::class)) {
139+
if (!function_exists('Infocyph\UID\snowflake')) {
126140
/**
127141
* Generates Snowflake ID.
128142
*
@@ -137,7 +151,7 @@ function snowflake(int $datacenter = 0, int $workerId = 0): string
137151
}
138152
}
139153

140-
if (!function_exists(\Infocyph\UID\TBSL::class)) {
154+
if (!function_exists('Infocyph\UID\sonyflake')) {
141155
/**
142156
* Generates Sonyflake ID.
143157
*
@@ -147,11 +161,11 @@ function snowflake(int $datacenter = 0, int $workerId = 0): string
147161
*/
148162
function sonyflake(int $machineId = 0): string
149163
{
150-
return TBSL::generate($machineId);
164+
return Sonyflake::generate($machineId);
151165
}
152166
}
153167

154-
if (!function_exists(\Infocyph\UID\tbsl::class)) {
168+
if (!function_exists('Infocyph\UID\tbsl')) {
155169
/**
156170
* Generates TBSL ID.
157171
*

tests/SnowflakeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
test('Basic', function () {
66
$sf = Snowflake::generate();
77
$parsed = Snowflake::parse($sf);
8-
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time() + 1)
8+
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time())
99
->and($parsed['worker_id'])->toBe(0)
1010
->and($parsed['datacenter_id'])->toBe(0);
1111
});

tests/SonyflakeTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
test('Basic', function () {
66
$sf = Sonyflake::generate();
77
$parsed = Sonyflake::parse($sf);
8-
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time() + 1)
8+
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time())
99
->and($parsed['machine_id'])->toBe(0);
1010
});
1111

tests/TBSLTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
test('Basic', function () {
66
$sf = TBSL::generate();
77
$parsed = TBSL::parse($sf);
8-
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time() + 1)
8+
expect($parsed['time']->getTimestamp())->toBeBetween(time() - 1, time())
99
->and($parsed['machineId'])->toBe('00');
1010
});
1111

tests/ULIDTest.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
test('Basic', function () {
66
$ulid = ULID::generate();
7-
expect($ulid)->toBeString();
8-
expect(ULID::isValid($ulid))->toBeTrue()
9-
->and(ULID::getTime($ulid)->getTimestamp())->toBeBetween(time() - 1, time() + 1);
7+
expect($ulid)->toBeString()
8+
->and(ULID::isValid($ulid))->toBeTrue()
9+
->and(ULID::getTime($ulid)->getTimestamp())->toBeBetween(time() - 1, time());
1010
});

0 commit comments

Comments
 (0)