diff --git a/sources/extensions/GUIDExtension.php b/sources/extensions/GUIDExtension.php
deleted file mode 100644
index fb5b289..0000000
--- a/sources/extensions/GUIDExtension.php
+++ /dev/null
@@ -1,147 +0,0 @@
-$other.
+ *
+ * @param mixed $other Второй класс для сравнения.
+ *
+ * @return int Возвращает результат сравнения. 0
, если GUID равны, -1
, если текущий GUID
+ * меньше, чем второй и 1
, если текущий GUID больше другого.
+ */
+ public function CompareTo (mixed $other): int;
+
+ /**
+ * Сравнивает на равенство текущий класс с другим, переданным в $other
.
+ *
+ * @param mixed $other Второй класс для сравнения.
+ *
+ * @return bool Результат сравнения: true
, если оба класса равны и false
, если нет.
+ */
+ public function IsEqualsTo (mixed $other): bool;
+
+ /**
+ * Сравнение объектов по указанному свойству.
+ *
+ * @param string $propertyName Название свойства для сравнения.
+ * @param mixed $other Объект для сравнения.
+ *
+ * @return int Результат сравнения: -1
, 0
или 1
.
+ */
+ public function CompareByProperty (string $propertyName, mixed $other): int;
+}
\ No newline at end of file
diff --git a/sources/interfaces/IHashable.php b/sources/interfaces/IHashable.php
new file mode 100644
index 0000000..dcf34bb
--- /dev/null
+++ b/sources/interfaces/IHashable.php
@@ -0,0 +1,21 @@
+true - по убыванию, false
- по
+ * возрастанию. По умолчанию - по возрастанию.
+ *
+ * @return void
+ */
+ public function Sort (string $property = '', bool $descending = false): void;
+
+ /**
+ * Сортирует элементы класса по заданной функции.
+ *
+ * @param callable $propertyFunction Функция, возвращающая значение свойства для сортировки.
+ * @param bool $descending Направление сортировки: true
- по убыванию, false
- по
+ * возрастанию. По умолчанию - по возрастанию.
+ *
+ * @return void
+ */
+ public function SortCallback (callable $propertyFunction, bool $descending = false): void;
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDArrayableTrait.php b/sources/traits/GUID/GUIDArrayableTrait.php
new file mode 100644
index 0000000..a85ef8c
--- /dev/null
+++ b/sources/traits/GUID/GUIDArrayableTrait.php
@@ -0,0 +1,43 @@
+ GUID::class,
+ "value" => $this->Value
+ ];
+ }
+
+ /**
+ * @inheritDoc
+ * @throws TypeException Если тип не соответствует.
+ */
+ public function FromArray (array $array): void
+ {
+ // Проверка типа
+ if (!isset($array["type_class"]) || $array["type_class"] != GUID::class)
+ // - если тип не соответствует, выбрасываем исключение
+ throw new TypeException($array["type_class"] ?? "", 'Неверный тип данных / Wrong data type.');
+
+ // Получаем значение GUID
+ $this->Value = $array["value"];
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDComparableTrait.php b/sources/traits/GUID/GUIDComparableTrait.php
new file mode 100644
index 0000000..ba996a6
--- /dev/null
+++ b/sources/traits/GUID/GUIDComparableTrait.php
@@ -0,0 +1,56 @@
+Value === $other->ToString();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function CompareTo (mixed $other): int
+ {
+ // Сравниваем строковые значения GUID
+ $compareResult = strcmp($this->Value, $other->ToString());
+
+ // Возвращаем результат сравнения
+ // - если текущий GUID меньше, чем второй
+ if ($compareResult < 0)
+ // - возвращаем -1
+ return -1;
+ // - если текущий GUID больше, чем второй
+ else if ($compareResult > 0)
+ // - возвращаем 1
+ return 1;
+ else
+ // - иначе если GUID равны, то возвращаем 0
+ return 0;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ #[Deprecated('Этот класс не имеет свойств. Данные методы не будут работать корректно. / This class has no properties. These methods will not work correctly.', '1.2')]
+ public function CompareByProperty (string $propertyName, mixed $other): int
+ {
+ // Этот класс не имеет свойств, поэтому возвращаем 0
+ return 0;
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDDuplicatedTrait.php b/sources/traits/GUID/GUIDDuplicatedTrait.php
new file mode 100644
index 0000000..5c08d44
--- /dev/null
+++ b/sources/traits/GUID/GUIDDuplicatedTrait.php
@@ -0,0 +1,24 @@
+Value);
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDHashableTrait.php b/sources/traits/GUID/GUIDHashableTrait.php
new file mode 100644
index 0000000..9335ead
--- /dev/null
+++ b/sources/traits/GUID/GUIDHashableTrait.php
@@ -0,0 +1,22 @@
+Value);
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDJsonSerializableTrait.php b/sources/traits/GUID/GUIDJsonSerializableTrait.php
new file mode 100644
index 0000000..e40a823
--- /dev/null
+++ b/sources/traits/GUID/GUIDJsonSerializableTrait.php
@@ -0,0 +1,22 @@
+Value;
+ }
+}
\ No newline at end of file
diff --git a/sources/traits/GUID/GUIDSerializeTrait.php b/sources/traits/GUID/GUIDSerializeTrait.php
new file mode 100644
index 0000000..c5cd3da
--- /dev/null
+++ b/sources/traits/GUID/GUIDSerializeTrait.php
@@ -0,0 +1,41 @@
+ToArray();
+
+ // Преобразуем в JSON
+ return json_encode($array, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
+ }
+
+ /**
+ * @inheritDoc
+ * @throws TypeException Если тип не соответствует.
+ */
+ public function UnSerialize (string $serialized): void
+ {
+ // Преобразуем в массив
+ $array = json_decode($serialized, true, flags: JSON_UNESCAPED_UNICODE);
+
+ // Получаем значение
+ $this->FromArray($array);
+ }
+}
\ No newline at end of file
diff --git a/sources/types/GUID.md b/sources/types/GUID.md
new file mode 100644
index 0000000..75f64bf
--- /dev/null
+++ b/sources/types/GUID.md
@@ -0,0 +1,583 @@
+# Описание класса GUID
+
+## Информация о версии
+
+Версия класса: 1.0
+
+Впервые введено в пакет с версии: 1.2
+
+Описание класса: Класс GUID предназначен для работы с уникальными идентификаторами формата UUID/GUID.
+
+## Реализуемые интерфейсы
+
+Класс реализует следующие интерфейсы:
+
+* `IArrayable`,
+* `IDuplicated`,
+* `ISerializable`,
+* `IComparable`,
+* `IHashable`,
+* `JsonSerializable`.
+
+## Публичные свойства и константы класса
+
+В классе определены следующие свойства и константы:
+
+- `const GUID EMPTY` - константа для пустого GUID.
+
+## Методы и функции
+
+### Конструктор и деструктор.
+
+Конструктор принимает **1 необязательный параметр**:
+
+* `string $value` - строка GUID (по умолчанию, эквивалент `EMPTY`).
+
+В результате создаётся новый класс `GUID`.
+
+**Пример:**
+
+ // Контсуктор
+ $guid = new GUID ('00000000-0000-0000-0000-000000000000');
+ // Деструктор
+ unset($guid);
+
+Создаст и уничтожит класс `GUID`.
+
+### Сохранение и загрузка из файла.
+
+За сохранение и загрузку отвечают 2 метода: `SaveToFile` и `LoadFromFile`.
+
+#### Сохранение в файл (метод `SaveToFile`)
+
+Этот метод сохраняет содержимое JSON в файл. Он содержит **1 обязательный параметр**:
+
+* `string $fileName` - имя файла на диске.
+
+Метод возвращает `bool` - сохранены ли данные в файл: `true` - да, `false` - нет.
+
+Синтаксис:
+
+ public function SaveToFile (string $fileName): bool
+
+**Пример:**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Сохраняем созданный JSON файл
+ $json->SaveToFile($fileName);
+
+Содержимое файла `test.json` представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+#### Загрузка файла (метод `LoadFromFile`)
+
+Этот метод загружает содержимое файла в класс. Он содержит **1 обязательный параметр**:
+
+* `string $fileName` - имя файла на диске.
+
+Метод возвращает `bool` - загружены ли данные из файла: `true` - да, `false` - нет.
+
+Синтаксис:
+
+ public function LoadFromFile (string $fileName): bool
+
+**Пример:**
+Пусть дан файл `test.json`, содержимое которого представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+Следующий код загрузит это содержимое в класс:
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Загружаю данные
+ $json->LoadFromFile($fileName);
+
+### Чтение данных
+
+Для чтения данных используется один общий метод `Read` и 7 его производных метода: `ReadString`, `ReadInt`, `ReadFloat`,
+`ReadBool`, `ReadArray`, `ReadObject` и `ReadSerializable`.
+
+#### Метод `Read`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `mixed $default` (значение по умолчанию, задан по умолчанию в `null`).
+
+Этот метод возвращает `mixed`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function Read (string $key, mixed $default = null): mixed
+
+**Пример,**
+
+ // Создаю класс
+ $json = new JsonReWriter();
+ // Заполняю данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->Write("test3/test/res", json_encode([1, 2, 3]));
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+ // Получаю значение
+ $float = (float)$json->Read("test/subtest/BBB"));
+
+В результате, переменная `$float` будет иметь значение `1.23`.
+
+#### Метод `ReadString`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `string $default` (значение по умолчанию, задан по умолчанию в `""`).
+
+Этот метод возвращает `string`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadString (string $key, string $default = ""): string
+
+#### Метод `ReadInt`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `int $default` (значение по умолчанию, задан по умолчанию в `0`).
+
+Этот метод возвращает `int`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadInt (string $key, int $default = 0): int
+
+#### Метод `ReadFloat`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `float $default` (значение по умолчанию, задан по умолчанию в `0.0`).
+
+Этот метод возвращает `float`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadFloat (string $key, float $default = 0.0): float
+
+#### Метод `ReadBool`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `bool $default` (значение по умолчанию, задан по умолчанию в `false`).
+
+Этот метод возвращает `bool`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadBool (string $key, bool $default = false): bool
+
+#### Метод `ReadArray`
+
+Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1
+необязательный параметр** `array $default` (значение по умолчанию, задан по умолчанию в `[]`).
+
+Этот метод возвращает `array`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadArray (string $key, array $default = []): array
+
+#### Метод `ReadObject`
+
+Это метод, который читает значение ключа JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `object $default` (значение по умолчанию).
+
+Этот метод возвращает `object`: значение ключа JSON или значение по умолчанию.
+
+Синтаксис:
+
+ public function ReadObject (string $key, object $default): object
+
+#### Метод `ReadSerializable`
+
+Это метод, который читает значение ключа JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `string $serializableClassName` (имя класса, реализующего интерфейс ISerializable, с namespace).
+
+Этот метод возвращает класс, реализующий интерфейс `ISerializable`.
+
+**Важно!** Этот метод может выбросить исключение `JsonException`, если класс, заданный в `$serializableClassName` не
+реализует интерфейс `ISerializable`.
+
+Синтаксис:
+
+ public function ReadSerializable (string $key, string $serializableClassName): ISerializable
+
+**Пример,**
+
+Пусть для примера, класс `Demo` из namespace `iam\namespace` реализует интерфейс `ISerializable`.
+
+ // Создаю класс
+ $json = new JsonReWriter();
+ // ... Здесь где-то загрузка данных
+ // Получаю класс
+ try {
+ /**
+ * @var Demo $unSerializableClass
+ */
+ $unSerializableClass = $json->ReadSerializable("test", "iam\\namespace\\Demo");
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+
+В результате, переменная `$unSerializableClass` будет содержать данные класса `Demo`.
+
+### Запись данных
+
+Для чтения данных используется один общий метод `Write` и 3 его производных метода: `WriteArray`, `WriteObject` и
+`WriteSerializable`.
+
+**Важно!** Лобой из вышеуказанных методов может выбросить исключение `JsonException`, если ключ не содержит вложений,
+хотя от него требуется обратное.
+
+#### Метод `Write`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `mixed $value` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function Write (string $key, mixed $value): void
+
+**Пример,**
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Сохраняем созданный JSON файл
+ $json->SaveToFile($fileName);
+
+Содержимое файла `test.json` представлено далее:
+
+ {
+ "test": {
+ "subtest": {
+ "AAA": "123",
+ "BBB": 1.23
+ }
+ },
+ "test1": {
+ "test": 123
+ },
+ "test2": {
+ "test": true
+ },
+ "test3": {
+ "test": {
+ "res": "[1,2,3]"
+ }
+ }
+ }
+
+#### Метод `WriteArray`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `array $array` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteArray (string $key, array $array): void
+
+#### Метод `WriteObject`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `object $value` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteObject (string $key, object $value): void
+
+#### Метод `WriteSerializable`
+
+Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**:
+
+- `string $key` (ключ);
+- `ISerializable $serializableValue` (записываемое значение).
+
+Этот метод ничего не возвращает.
+
+Синтаксис:
+
+ public function WriteSerializable (string $key, ISerializable $serializableValue): void
+
+**Пример,**
+Пусть для примера, класс `Demo` из namespace `iam\namespace` реализует интерфейс `ISerializable`.
+
+ // Имя файла
+ $fileName = __DIR__ . "/test.json";
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Создаём класс Demo
+ $serializableClass = new Demo(...);
+ // Заполним данными
+ try {
+ $json->WriteSerializable("test", $serializableClass);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ ...
+
+### Работа с ключами JSON
+
+Для работы с ключами JSON есть 2 метода: `IsKeyExists` и `GetKeys`.
+
+#### Метод `IsKeyExists`
+
+Это метод проверяем наличие ключа в JSON. Он имеет **1 обязательный параметр** - `string $key` (ключ).
+
+Этот метод возвращает `bool`: `true` если ключ найден и `false` в противном случае.
+
+Синтаксис:
+
+ public function IsKeyExists (string $key): bool
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Проверяем ключи
+ $check1 = $json->IsKeyExists("test/subtest/AAA");
+ $check2 = $json->IsKeyExists("test/subtest/ССС");
+
+В результате, `$check1` будет `true`, а `$check2` - `false`.
+
+#### Метод `GetKeys`
+
+Это метод получает список ключей. Он имеет **2 необязательных параметра**:
+
+- `string $parentKey` (ключ родителя (или "" (установлено по умолчанию) для всех);
+- `bool $includeChildren` (нужно ли включать дочерние ключи (по умолчанию, да)).
+
+Этот метод возвращает `array`: список ключей.
+
+Синтаксис:
+
+ public function GetKeys (string $parentKey = "", bool $includeChildren = true): array
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Получаем ключи
+ $keys1 = $json->GetKeys("test");
+ $keys2 = $json->GetKeys("test", false);
+ $keys3 = $json->GetKeys();
+
+В результате, `$key1` будет следующим массивом:
+
+ [
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB"
+ ]
+
+`$key2` будет следующим массивом:
+
+ [
+ "subtest"
+ ]
+
+`$key3` будет следующим массивом:
+
+ [
+ "test",
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB",
+ "test1",
+ "test1/test",
+ "test2",
+ "test2/test",
+ "test3",
+ "test3/test",
+ "test3/test/res"
+ ]
+
+### Удаление ключей JSON
+
+Для удаления ключей JSON есть 2 метода: `DeleteKey`, который удаляет только определённый ключ и `Clear`, который удаляет
+**все ключи** из json-файла.
+
+#### Метод `DeleteKey`
+
+Это метод удаляет только определённый ключ в JSON. Он имеет **1 обязательный параметр** - `string $key` (ключ).
+
+Этот метод возвращает `bool` - результат удаления ключа: `true` - удаление прошло успешно, `false` - произошла ошибка
+при удалении.
+
+Синтаксис:
+
+ public function DeleteKey (string $key): bool
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Получаемем ключи до удаления
+ $check1 = $json->GetKeys("test/subtest");
+ // Удаляем ключ
+ $this->DeleteKey("test/subtest/BBB");
+ // Получаемем ключи после удаления
+ $check2 = $json->GetKeys("test/subtest");
+
+В результате, `$check1` будет
+
+ [
+ "test/subtest",
+ "test/subtest/AAA",
+ "test/subtest/BBB"
+ ]
+
+а `$check2`:
+
+ [
+ "test/subtest",
+ "test/subtest/AAA"
+ ]
+
+#### Метод `Clear`
+
+Это метод удаляет **все ключи** из json-файла. Он не имеет никаких параметров и ничего не возвращает.
+
+Синтаксис:
+
+ public function Clear (): void
+
+**Пример,**
+
+ // Создаём класс
+ $json = new JsonReWriter();
+ // Заполним данными
+ try {
+ $json->Write("test/subtest/AAA", "123");
+ $json->Write("test/subtest/BBB", 1.23);
+ $json->Write("test1/test", 123);
+ $json->Write("test2/test", true);
+ $json->WriteArray("test3/test/res", [1, 2, 3]);
+ } catch (JsonException $e) {
+ echo $e->getMessage();
+ }
+ // Очищаем
+ $json->Clear();
+ // Получаем ключи
+ $keys = $json->GetKeys();
+
+В результате, `$key` будет следующим массивом:
+
+ [
+ ]
\ No newline at end of file
diff --git a/sources/types/GUID.php b/sources/types/GUID.php
new file mode 100644
index 0000000..57f5372
--- /dev/null
+++ b/sources/types/GUID.php
@@ -0,0 +1,270 @@
+ StringExtension::IsNullOrWhitespace($this->Value) ? GUID_EMPTY_STRING : $this->Value;
+ set {
+ if (!self::Validate($value))
+ throw new InvalidArgumentException('Неверный идентификатор (GUID) / Wrong GUID identifier.');
+
+ $this->Value = $value;
+ }
+ }
+
+ /**
+ * Конструктор GUID-класса.
+ *
+ * @param string $value Значение GUID. По умолчанию, пустой GUID.
+ *
+ * @see GUID_EMPTY_STRING
+ */
+ public function __construct (string $value = GUID_EMPTY_STRING)
+ {
+ $this->Value = $value;
+ }
+
+ // Подключаем трейт реализующий интерфейс ISerializable
+ use GUIDSerializeTrait;
+
+ // Подключаем трейт реализующий интерфейс IArrayable
+ use GUIDArrayableTrait;
+
+ // Подключаем трейт реализующий интерфейс IDuplicated
+ use GUIDDuplicatedTrait;
+
+ // Подключаем трейт реализующий интерфейс JsonSerializable
+ use GUIDJsonSerializableTrait;
+
+ // Подключаем трейт реализующий интерфейс IHashable
+ use GUIDHashableTrait;
+
+ // Подключаем трейт реализующий интерфейс IComparable
+ use GUIDComparableTrait;
+
+ /**
+ * Генерация нового случайного GUID.
+ *
+ * @return GUID Новый уникальный GUID.
+ */
+ public static function Generate (): GUID
+ {
+ try {
+ // Генерация случайных значений для GUID
+ $randomParts = [
+ // - 32-разрядная часть поля time_low
+ random_int(0, 0xffff),
+ // - продолжение time_low
+ random_int(0, 0xffff),
+ // - 16-разрядная часть поля time_mid
+ random_int(0, 0xffff),
+ // - версии бит в time_hi_and_version
+ random_int(0, 0x0fff) | 0x4000,
+ // - различные биты в clk_seq_hi_res и clk_seq_low
+ random_int(0, 0x3fff) | 0x8000,
+ // - первые 16 бит node_id
+ random_int(0, 0xffff),
+ // - продолжение node_id (вторые 16 бит)
+ random_int(0, 0xffff),
+ // - последние 16 бит node_id
+ random_int(0, 0xffff)
+ ];
+
+ // Формирование GUID из случайных значений
+ $guid = vsprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', $randomParts);
+ }
+ catch (Throwable) {
+ // Если возникла ошибка при генерации GUID, возвращаем пустой GUID
+ $guid = GUID_EMPTY_STRING;
+ }
+
+ // Создание экземпляра GUID со сгенерированным значением и возврат его
+ return new self($guid);
+ }
+
+ /**
+ * Проверяет, является ли GUID пустым или недействительным.
+ *
+ * @param GUID|null $guid Экземпляр GUID или null.
+ *
+ * @return bool True, если GUID недействителен или равен пустому значению.
+ */
+ public static function isInvalidOrEmpty (?GUID $guid): bool
+ {
+ return !self::Validate($guid) || $guid === self::EMPTY;
+ }
+
+ /**
+ * Валидирует строку GUID.
+ *
+ * @param mixed $guid Объект GUID или строка для проверки.
+ *
+ * @return bool Результат проверки.
+ */
+ public static function Validate (mixed $guid): bool
+ {
+ // Проверка на пустое значение
+ if (empty($guid))
+ // - если пустое, то возвращаем false
+ return false;
+
+ // Проверка на тип GUID
+ if ($guid instanceof GUID)
+ // - если GUID, то переводим его в строку
+ $guid = $guid->Value;
+
+ // Проверка на соответствие формату GUID
+ return preg_match('/^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$/', $guid) > 0;
+ }
+
+ /**
+ * Создает экземпляр GUID из массива байтов.
+ *
+ * @param array $bytes Массив байтов GUID.
+ *
+ * @return GUID Класс GUID
+ */
+ public static function FromBytes (array $bytes): GUID
+ {
+ // Проверка на корректность массива байтов
+ if (count($bytes) != 16)
+ // - если массив байтов не содержит 16 байтов, выбрасываем исключение
+ throw new LengthException('Массив байтов должен содержать 16 байтов / Bytes array must contain 16 bytes.');
+
+ // Преобразование массива байтов в строку
+ $hex = bin2hex(pack('C*', ...$bytes));
+
+ // Создание GUID из преобразованной строки
+ $guid =
+ new GUID(substr($hex, 0, 8) . '-' . substr($hex, 8, 4) . '-' . substr($hex, 12, 4) . '-' . substr($hex, 16,
+ 4) . '-' . substr($hex, 20, 12));
+
+ // Возврат экземпляра GUID
+ return new GUID($guid);
+ }
+
+ /**
+ * Создает экземпляр GUID из строки GUID.
+ *
+ * @param string $guidString Строка GUID.
+ *
+ * @return GUID Класс GUID.
+ */
+ public static function Parse (string $guidString): GUID
+ {
+ return
+ // Проверка на валидность переданного GUID
+ !self::Validate($guidString)
+ // - если GUID недействителен, выбрасываем исключение
+ ? throw new InvalidArgumentException('Предан неверный GUID / Wrong GUID.')
+ // - иначе, создаем экземпляр GUID из строки
+ : new GUID($guidString);
+ }
+
+ /**
+ * Преобразует объект GUID в строку.
+ *
+ * @return string Строковое представление GUID.
+ */
+ public function __toString (): string
+ {
+ return $this->Value;
+ }
+
+ /**
+ * Возвращает сегмент GUID по его номеру.
+ *
+ * @param int $segmentNumber Номер сегмента: 1 - time_low, 2 - time_mid, 3 - time_hi_and_version, 4 -
+ * clk_seq_hi_res и clk_seq_low, 5 - node_id. В случае, если номер сегмента некорректен, выбрасывается
+ * исключение OutOfRangeException
.
+ *
+ * @return string Сегмент GUID.
+ * @throws OutOfRangeException Если номер сегмента некорректен.
+ */
+ public function Segment (int $segmentNumber): string
+ {
+ // Проверка на корректность номера сегмента
+ if ($segmentNumber < 1 || $segmentNumber > 5)
+ // - если номер сегмента некорректен, выбрасываем исключение
+ throw new OutOfRangeException('Номер сегмента должен быть между 1 и 5 / Segment number must be between 1 and 5.');
+
+ // Разделение GUID на сегменты по дефисам
+ $segments = explode('-', $this->Value);
+
+ // Возврат нужного сегмента
+ return $segments[$segmentNumber - 1];
+ }
+
+ /**
+ * Возвращает массив байтов GUID.
+ *
+ * @return array Массив байтов GUID.
+ */
+ public function ToBytes (): array
+ {
+ // Разделение GUID на части
+ [$data1, $data2, $data3, $data4_1, $data4_2, $data5] =
+ sscanf($this->Value, "%08s-%04s-%04s-%04s-%04s%012s");
+
+ // Преобразование в массив байтов
+ return unpack('C*', hex2bin($data1 . $data2 . $data3 . $data4_1 . $data4_2 . $data5));
+ }
+
+ /**
+ * Возвращает строковое представление GUID.
+ *
+ * @return string Строковое представление GUID.
+ */
+ public function ToString (): string
+ {
+ return $this->Value;
+ }
+}
\ No newline at end of file