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\NumberConverterInterface;
18
use Ramsey\Uuid\Exception\DceSecurityException;
19
use Ramsey\Uuid\Provider\DceSecurityProviderInterface;
20
use Ramsey\Uuid\Type\Hexadecimal;
21
use Ramsey\Uuid\Type\Integer as IntegerObject;
22
use Ramsey\Uuid\Uuid;
23
 
24
use function hex2bin;
25
use function in_array;
26
use function pack;
27
use function str_pad;
28
use function strlen;
29
use function substr_replace;
30
 
31
use const STR_PAD_LEFT;
32
 
33
/**
34
 * DceSecurityGenerator generates strings of binary data based on a local
35
 * domain, local identifier, node ID, clock sequence, and the current time
36
 */
37
class DceSecurityGenerator implements DceSecurityGeneratorInterface
38
{
39
    private const DOMAINS = [
40
        Uuid::DCE_DOMAIN_PERSON,
41
        Uuid::DCE_DOMAIN_GROUP,
42
        Uuid::DCE_DOMAIN_ORG,
43
    ];
44
 
45
    /**
46
     * Upper bounds for the clock sequence in DCE Security UUIDs.
47
     */
48
    private const CLOCK_SEQ_HIGH = 63;
49
 
50
    /**
51
     * Lower bounds for the clock sequence in DCE Security UUIDs.
52
     */
53
    private const CLOCK_SEQ_LOW = 0;
54
 
55
    public function __construct(
56
        private NumberConverterInterface $numberConverter,
57
        private TimeGeneratorInterface $timeGenerator,
58
        private DceSecurityProviderInterface $dceSecurityProvider
59
    ) {
60
    }
61
 
62
    public function generate(
63
        int $localDomain,
64
        ?IntegerObject $localIdentifier = null,
65
        ?Hexadecimal $node = null,
66
        ?int $clockSeq = null
67
    ): string {
68
        if (!in_array($localDomain, self::DOMAINS)) {
69
            throw new DceSecurityException(
70
                'Local domain must be a valid DCE Security domain'
71
            );
72
        }
73
 
74
        if ($localIdentifier && $localIdentifier->isNegative()) {
75
            throw new DceSecurityException(
76
                'Local identifier out of bounds; it must be a value between 0 and 4294967295'
77
            );
78
        }
79
 
80
        if ($clockSeq > self::CLOCK_SEQ_HIGH || $clockSeq < self::CLOCK_SEQ_LOW) {
81
            throw new DceSecurityException(
82
                'Clock sequence out of bounds; it must be a value between 0 and 63'
83
            );
84
        }
85
 
86
        switch ($localDomain) {
87
            case Uuid::DCE_DOMAIN_ORG:
88
                if ($localIdentifier === null) {
89
                    throw new DceSecurityException(
90
                        'A local identifier must be provided for the org domain'
91
                    );
92
                }
93
 
94
                break;
95
            case Uuid::DCE_DOMAIN_PERSON:
96
                if ($localIdentifier === null) {
97
                    $localIdentifier = $this->dceSecurityProvider->getUid();
98
                }
99
 
100
                break;
101
            case Uuid::DCE_DOMAIN_GROUP:
102
            default:
103
                if ($localIdentifier === null) {
104
                    $localIdentifier = $this->dceSecurityProvider->getGid();
105
                }
106
 
107
                break;
108
        }
109
 
110
        $identifierHex = $this->numberConverter->toHex($localIdentifier->toString());
111
 
112
        // The maximum value for the local identifier is 0xffffffff, or
113
        // 4294967295. This is 8 hexadecimal digits, so if the length of
114
        // hexadecimal digits is greater than 8, we know the value is greater
115
        // than 0xffffffff.
116
        if (strlen($identifierHex) > 8) {
117
            throw new DceSecurityException(
118
                'Local identifier out of bounds; it must be a value between 0 and 4294967295'
119
            );
120
        }
121
 
122
        $domainByte = pack('n', $localDomain)[1];
123
        $identifierBytes = (string) hex2bin(str_pad($identifierHex, 8, '0', STR_PAD_LEFT));
124
 
125
        if ($node instanceof Hexadecimal) {
126
            $node = $node->toString();
127
        }
128
 
129
        // Shift the clock sequence 8 bits to the left, so it matches 0x3f00.
130
        if ($clockSeq !== null) {
131
            $clockSeq = $clockSeq << 8;
132
        }
133
 
134
        $bytes = $this->timeGenerator->generate($node, $clockSeq);
135
 
136
        // Replace bytes in the time-based UUID with DCE Security values.
137
        $bytes = substr_replace($bytes, $identifierBytes, 0, 4);
138
 
139
        return substr_replace($bytes, $domainByte, 9, 1);
140
    }
141
}