-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInstallUuidManager.php
More file actions
109 lines (88 loc) · 3.32 KB
/
Copy pathInstallUuidManager.php
File metadata and controls
109 lines (88 loc) · 3.32 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<?php
declare(strict_types=1);
namespace Oak\Engine\Installer;
final class InstallUuidManager
{
public function ensureEnvLocalInstallUuid(string $envPath, bool $replace = false): string
{
$content = '';
if (is_file($envPath)) {
$existingContent = file_get_contents($envPath);
if (!is_string($existingContent)) {
throw new \RuntimeException(sprintf('Unable to read "%s".', $envPath));
}
$content = $existingContent;
}
$updated = $this->upsertInstallUuid($content, $replace);
if (!$updated['changed']) {
return $updated['uuid'];
}
$directory = dirname($envPath);
if (!createDirectoryTree($directory, 0o755)) {
throw new \RuntimeException(sprintf('Unable to create directory "%s".', $directory));
}
if (false === file_put_contents($envPath, $updated['content'])) {
throw new \RuntimeException(sprintf('Unable to write "%s".', $envPath));
}
return $updated['uuid'];
}
/**
* @return array{content: string, uuid: string, changed: bool}
*/
public function upsertInstallUuid(string $content, bool $replace = false): array
{
$normalizedContent = str_replace(["\r\n", "\r"], "\n", $content);
$existingUuid = $this->extractInstallUuid($normalizedContent);
if (null !== $existingUuid && !$replace) {
return [
'content' => $normalizedContent,
'uuid' => $existingUuid,
'changed' => false,
];
}
$uuid = $this->generateUuidV7Like();
$uuidLine = 'INSTALL_UUID='.$uuid;
$pattern = '/^\s*#?\s*INSTALL_UUID\s*=.*$/m';
if (1 === preg_match($pattern, $normalizedContent)) {
$updatedContent = (string) preg_replace($pattern, $uuidLine, $normalizedContent, 1);
} else {
$updatedContent = rtrim($normalizedContent, "\n");
$updatedContent = '' === $updatedContent ? $uuidLine."\n" : $updatedContent."\n".$uuidLine."\n";
}
return [
'content' => $updatedContent,
'uuid' => $uuid,
'changed' => $updatedContent !== $normalizedContent,
];
}
private function extractInstallUuid(string $content): ?string
{
if (1 !== preg_match('/^\s*INSTALL_UUID\s*=\s*("?)([0-9a-fA-F-]+)\1\s*$/m', $content, $matches)) {
return null;
}
$uuid = strtolower($matches[2]);
return 1 === preg_match('/^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/', $uuid)
? $uuid
: null;
}
private function generateUuidV7Like(): string
{
$timestamp = (int) floor(microtime(true) * 1000);
$bytes = random_bytes(16);
for ($index = 5; $index >= 0; --$index) {
$bytes[$index] = chr($timestamp & 0xFF);
$timestamp >>= 8;
}
$bytes[6] = chr((ord($bytes[6]) & 0x0F) | 0x70);
$bytes[8] = chr((ord($bytes[8]) & 0x3F) | 0x80);
$hex = bin2hex($bytes);
return sprintf(
'%s-%s-%s-%s-%s',
substr($hex, 0, 8),
substr($hex, 8, 4),
substr($hex, 12, 4),
substr($hex, 16, 4),
substr($hex, 20, 12),
);
}
}