Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
148 lars 1
<?php
2
 
3
/**
4
 * This file is part of the ramsey/uuid library
5
 *
6
 * For the full copyright and license information, please view the LICENSE
7
 * file that was distributed with this source code.
8
 *
9
 * @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
10
 * @license http://opensource.org/licenses/MIT MIT
11
 */
12
 
13
declare(strict_types=1);
14
 
15
namespace Ramsey\Uuid\Generator;
16
 
17
use Ramsey\Uuid\Converter\TimeConverterInterface;
18
use Ramsey\Uuid\Exception\InvalidArgumentException;
19
use Ramsey\Uuid\Exception\RandomSourceException;
20
use Ramsey\Uuid\Exception\TimeSourceException;
21
use Ramsey\Uuid\Provider\NodeProviderInterface;
22
use Ramsey\Uuid\Provider\TimeProviderInterface;
23
use Ramsey\Uuid\Type\Hexadecimal;
24
use Throwable;
25
 
26
use function dechex;
27
use function hex2bin;
28
use function is_int;
29
use function pack;
30
use function preg_match;
31
use function sprintf;
32
use function str_pad;
33
use function strlen;
34
 
35
use const STR_PAD_LEFT;
36
 
37
/**
38
 * DefaultTimeGenerator generates strings of binary data based on a node ID,
39
 * clock sequence, and the current time
40
 */
41
class DefaultTimeGenerator implements TimeGeneratorInterface
42
{
43
    public function __construct(
44
        private NodeProviderInterface $nodeProvider,
45
        private TimeConverterInterface $timeConverter,
46
        private TimeProviderInterface $timeProvider
47
    ) {
48
    }
49
 
50
    /**
51
     * @throws InvalidArgumentException if the parameters contain invalid values
52
     * @throws RandomSourceException if random_int() throws an exception/error
53
     *
54
     * @inheritDoc
55
     */
56
    public function generate($node = null, ?int $clockSeq = null): string
57
    {
58
        if ($node instanceof Hexadecimal) {
59
            $node = $node->toString();
60
        }
61
 
62
        $node = $this->getValidNode($node);
63
 
64
        if ($clockSeq === null) {
65
            try {
66
                // This does not use "stable storage"; see RFC 4122, Section 4.2.1.1.
67
                $clockSeq = random_int(0, 0x3fff);
68
            } catch (Throwable $exception) {
69
                throw new RandomSourceException(
70
                    $exception->getMessage(),
71
                    (int) $exception->getCode(),
72
                    $exception
73
                );
74
            }
75
        }
76
 
77
        $time = $this->timeProvider->getTime();
78
 
79
        $uuidTime = $this->timeConverter->calculateTime(
80
            $time->getSeconds()->toString(),
81
            $time->getMicroseconds()->toString()
82
        );
83
 
84
        $timeHex = str_pad($uuidTime->toString(), 16, '0', STR_PAD_LEFT);
85
 
86
        if (strlen($timeHex) !== 16) {
87
            throw new TimeSourceException(sprintf(
88
                'The generated time of \'%s\' is larger than expected',
89
                $timeHex
90
            ));
91
        }
92
 
93
        $timeBytes = (string) hex2bin($timeHex);
94
 
95
        return $timeBytes[4] . $timeBytes[5] . $timeBytes[6] . $timeBytes[7]
96
            . $timeBytes[2] . $timeBytes[3]
97
            . $timeBytes[0] . $timeBytes[1]
98
            . pack('n*', $clockSeq)
99
            . $node;
100
    }
101
 
102
    /**
103
     * Uses the node provider given when constructing this instance to get
104
     * the node ID (usually a MAC address)
105
     *
106
     * @param int|string|null $node A node value that may be used to override the node provider
107
     *
108
     * @return string 6-byte binary string representation of the node
109
     *
110
     * @throws InvalidArgumentException
111
     */
112
    private function getValidNode(int | string | null $node): string
113
    {
114
        if ($node === null) {
115
            $node = $this->nodeProvider->getNode();
116
        }
117
 
118
        // Convert the node to hex, if it is still an integer.
119
        if (is_int($node)) {
120
            $node = dechex($node);
121
        }
122
 
123
        if (!preg_match('/^[A-Fa-f0-9]+$/', (string) $node) || strlen((string) $node) > 12) {
124
            throw new InvalidArgumentException('Invalid node value');
125
        }
126
 
127
        return (string) hex2bin(str_pad((string) $node, 12, '0', STR_PAD_LEFT));
128
    }
129
}