1: <?php
2: /*
3: You may not change or alter any portion of this comment or credits
4: of supporting developers from this source code or any supporting source code
5: which is considered copyrighted (c) material of the original comment or credit authors.
6:
7: This program is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY; without even the implied warranty of
9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10: */
11:
12: namespace Xmf;
13:
14: /**
15: * Generate UUID
16: *
17: * @category Xmf\Uuid
18: * @package Xmf
19: * @author Richard Griffith <richard@geekwright.com>
20: * @copyright 2017-2021 XOOPS Project (https://xoops.org)
21: * @license GNU GPL 2.0 or later (https://www.gnu.org/licenses/gpl-2.0.html)
22: */
23: class Uuid
24: {
25: // match spec for version 4 UUID as per rfc4122
26: const UUID_REGEX = '/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/';
27:
28: /**
29: * generate - generate a version 4 (random) UUID
30: *
31: * Based on comment by pavel.volyntsev(at)gmail at https://php.net/manual/en/function.com-create-guid.php
32: *
33: * @return string UUID
34: *
35: * @throws \Exception on insufficient entropy
36: */
37: public static function generate()
38: {
39: $data = random_bytes(16);
40:
41: $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
42: $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
43:
44: return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
45: }
46:
47: /**
48: * Pack a UUID into a binary string
49: *
50: * @param string $uuid a valid UUID
51: *
52: * @return string packed UUID as a binary string
53: *
54: * @throws \InvalidArgumentException
55: * @throws \UnexpectedValueException
56: */
57: public static function packAsBinary($uuid)
58: {
59: if (!preg_match(static::UUID_REGEX, $uuid)) {
60: throw new \InvalidArgumentException('Invalid UUID');
61: }
62: $return = pack("H*", str_replace('-', '', $uuid));
63: if (false === $return) {
64: throw new \UnexpectedValueException('Packing UUID Failed');
65: }
66: return $return;
67: }
68:
69: /**
70: * Unpack a UUID stored as a binary string
71: *
72: * @param string $packedUuid a packed UUID as returned by packAsBinary()
73: *
74: * @return string unpacked UUID
75: *
76: * @throws \InvalidArgumentException
77: * @throws \UnexpectedValueException
78: */
79: public static function unpackBinary($packedUuid)
80: {
81: if (16 !== strlen($packedUuid)) {
82: throw new \InvalidArgumentException('Invalid packed UUID');
83: }
84: $return = vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($packedUuid), 4));
85: if (!preg_match(static::UUID_REGEX, $return)) {
86: throw new \UnexpectedValueException('Unpacking UUID Failed');
87: }
88: return $return;
89: }
90: }
91: