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