diff --git a/sources/classes/Dictionary.php b/sources/classes/Dictionary.php index 15f5e54..9d487ec 100644 --- a/sources/classes/Dictionary.php +++ b/sources/classes/Dictionary.php @@ -4,8 +4,13 @@ namespace goodboyalex\php_components_pack\classes; use ArrayAccess; use Countable; +use goodboyalex\php_components_pack\interfaces\IArrayable; +use goodboyalex\php_components_pack\interfaces\IComparable; +use goodboyalex\php_components_pack\interfaces\IHashable; use goodboyalex\php_components_pack\interfaces\ISerializable; +use goodboyalex\php_components_pack\interfaces\ISortable; use goodboyalex\php_components_pack\traits\ArrayBasicTrait; +use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayComparableTrait; use IteratorAggregate; /** @@ -16,7 +21,8 @@ use IteratorAggregate; * @version 1.0.3 * @since 1.0.14 */ -final class Dictionary implements ArrayAccess, IteratorAggregate, Countable, ISerializable +final class Dictionary + implements ArrayAccess, IteratorAggregate, Countable, ISerializable, IArrayable, IHashable, ISortable, IComparable { /** * @var array $Container Контейнер. @@ -26,33 +32,8 @@ final class Dictionary implements ArrayAccess, IteratorAggregate, Countable, ISe // Реализация наследуемых интерфейсов и классов use ArrayBasicTrait; - /** - * Добавление элементов в словарь. - * - * @param array $dictionary Ассоциативный массив вида ключ => значение, который будет добавлен в словарь. - * - * @return void - */ - public function AddRange (array $dictionary): void - { - // Для каждого элемента массива - foreach ($dictionary as $key => $value) - // - добавляем его в словарь. - $this->Add($key, $value); - } - - /** - * Добавление элемента в словарь. - * - * @param string $key Ключ. - * @param mixed $value Хранимое значение. - * - * @return void - */ - public function Add (string $key, mixed $value): void - { - $this->Container[$key] = $value; - } + // Реализация интерфейса IComparable + use ObjectArrayComparableTrait; /** * Получение значения по ключу. @@ -95,16 +76,6 @@ final class Dictionary implements ArrayAccess, IteratorAggregate, Countable, ISe return isset($this->Container[$key]); } - /** - * Очистка всех элементов. - * - * @return void - */ - public function Clear (): void - { - $this->Container = []; - } - /** * @inheritDoc */ @@ -124,13 +95,77 @@ final class Dictionary implements ArrayAccess, IteratorAggregate, Countable, ISe } /** - * Сортирует внутренние данные по ключам. - * - * @param bool $descending Сортировать ли данные в обратном порядке? + * @inheritDoc + */ + public function ToArray (): array + { + return $this->Container; + } + + /** + * @inheritDoc + */ + public function FromArray (array $array): void + { + // Очищаем словарь + $this->Clear(); + + // Добавляем элементы в словарь + $this->AddRange($array); + } + + /** + * Очистка всех элементов. * * @return void */ - public function Sort (bool $descending = false): void + public function Clear (): void + { + $this->Container = []; + } + + /** + * Добавление элементов в словарь. + * + * @param array $dictionary Ассоциативный массив вида ключ => значение, который будет добавлен в словарь. + * + * @return void + */ + public function AddRange (array $dictionary): void + { + // Для каждого элемента массива + foreach ($dictionary as $key => $value) + // - добавляем его в словарь. + $this->Add($key, $value); + } + + /** + * Добавление элемента в словарь. + * + * @param string $key Ключ. + * @param mixed $value Хранимое значение. + * + * @return void + */ + public function Add (string $key, mixed $value): void + { + $this->Container[$key] = $value; + } + + /** + * @inheritDoc + */ + public function Hash (): string + { + return md5(json_encode($this->Container, JSON_UNESCAPED_UNICODE)); + } + + /** + * @inheritDoc + * + * @warning Свойство $property не используется. + */ + public function Sort (string $property = '', bool $descending = false): void { // Если задана сортировка по убыванию if ($descending) @@ -142,12 +177,12 @@ final class Dictionary implements ArrayAccess, IteratorAggregate, Countable, ISe } /** - * Возвращает все элементы словаря в виде массива. + * @inheritDoc * - * @return array Массив, содержащий все элементы словаря. + * @warning Свойство $propertyFunction не используется. */ - public function ToArray (): array + public function SortCallback (callable $propertyFunction, bool $descending = false): void { - return $this->Container; + $this->Sort(descending: $descending); } } \ No newline at end of file diff --git a/sources/classes/ObjectArray.php b/sources/classes/ObjectArray.php index a9a9510..ba79b0e 100644 --- a/sources/classes/ObjectArray.php +++ b/sources/classes/ObjectArray.php @@ -5,9 +5,14 @@ namespace goodboyalex\php_components_pack\classes; use ArrayAccess; use Countable; use goodboyalex\php_components_pack\interfaces\IArrayable; +use goodboyalex\php_components_pack\interfaces\IComparable; +use goodboyalex\php_components_pack\interfaces\IHashable; use goodboyalex\php_components_pack\interfaces\ISerializable; +use goodboyalex\php_components_pack\interfaces\ISortable; use goodboyalex\php_components_pack\traits\ArrayBasicTrait; +use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayComparableTrait; use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayConstantsTrait; +use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayHashableTrait; use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayLINQTrait; use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArraySearchAndSortTrait; use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArraySerializeExTrait; @@ -20,10 +25,11 @@ use IteratorAggregate; * * @author Александр Бабаев * @package php_components_pack - * @version 1.0.6 + * @version 1.1 * @since 1.0 */ -final class ObjectArray implements ArrayAccess, IteratorAggregate, Countable, ISerializable, IArrayable +final class ObjectArray + implements ArrayAccess, IteratorAggregate, Countable, ISerializable, IArrayable, IHashable, ISortable, IComparable { /** * @var array $Container Массив объектов, хранящихся в данном классе. @@ -51,6 +57,12 @@ final class ObjectArray implements ArrayAccess, IteratorAggregate, Countable, IS // Реализация методов интерфейса IArrayable use ObjectArrayToArrayTrait; + // Реализация методов интерфейса IHashable + use ObjectArrayHashableTrait; + + // Реализация методов интерфейса IComparable + use ObjectArrayComparableTrait; + /** * Конструктор класса. * diff --git a/sources/extensions/GUIDExtension.php b/sources/extensions/GUIDExtension.php new file mode 100644 index 0000000..7b59350 --- /dev/null +++ b/sources/extensions/GUIDExtension.php @@ -0,0 +1,155 @@ +IsEqualsTo($other)) + // - если равны, то возвращаем 0 + return 0; + + // Возвращаем результат сравнения количества элементов + return $this->Count() > $other->Count() ? 1 : -1; + } + + /** + * @inheritDoc + */ + public function IsEqualsTo (mixed $other): bool + { + // Получаем хэши + // - этого объекта + $thisHash = $this->Hash(); + // - переданного объекта + $otherHash = $other->Hash(); + + // Сравниваем хэши и возвращаем результат + return $thisHash == $otherHash; + } + + /** + * @inheritDoc + */ + public function CompareByProperty (string $propertyName, mixed $other): int + { + // Получаем значения свойств + // - этого объекта + $thisProperty = $this->GetColumn($propertyName); + // - переданного объекта + $otherProperty = $other->GetColumn($propertyName); + + // Сравниваем их по количеству + if (count($thisProperty) !== count($otherProperty)) + // - если количество элементов не совпадает, то возвращаем результат + return count($thisProperty) > count($otherProperty) ? 1 : -1; + + // Переменная для хранения результата + $delta = 0; + + // Проходимся по массивам + for ($i = 0; $i < count($thisProperty); $i++) { + // - получаем значения + // -- текущего массива + $thisValue = $thisProperty[$i]; + // -- переданного массива + $otherValue = $otherProperty[$i]; + + // - если значения равны + if ($thisValue === $otherValue) + // - то пропускаем элемент + continue; + + // - иначе сравниваем + if ($thisValue > $otherValue) + // - если текущее значение больше, то увеличиваем счетчик + $delta++; + else + // - иначе уменьшаем счетчик + $delta--; + } + + // Возвращаем результат + return $delta === 0 ? 0 : ($delta > 0 ? 1 : -1); + } +} \ No newline at end of file diff --git a/sources/traits/ObjectArray/ObjectArrayHashableTrait.php b/sources/traits/ObjectArray/ObjectArrayHashableTrait.php new file mode 100644 index 0000000..bf21077 --- /dev/null +++ b/sources/traits/ObjectArray/ObjectArrayHashableTrait.php @@ -0,0 +1,66 @@ +Container as $object) { + // - если объект реализует интерфейс IHashable + if ($object instanceof IHashable) { + // -- то хэширую его и добавляю в массив + $toHash[] = $object->Hash(); + + // -- переходим к следующему элементу + continue; + } + + // - если объект реализует интерфейс ISerializable + if ($object instanceof ISerializable) { + // -- то сериализую его и добавляю в массив + $toHash[] = $object->Serialize(); + + // -- переходим к следующему элементу + continue; + } + + // - если объект реализует интерфейс IArrayable + if ($object instanceof IArrayable) { + // -- то преобразую его в массив + $array = $object->ToArray(); + + // -- сериализую его и добавляю в массив + $toHash[] = json_encode($array, JSON_UNESCAPED_UNICODE); + + // -- переходим к следующему элементу + continue; + } + + // - иначе просто сериализую объект + $toHash[] = serialize($object); + } + + // Возвращаю хеш массива + return md5(json_encode($toHash, JSON_UNESCAPED_UNICODE)); + } +} \ No newline at end of file diff --git a/sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php b/sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php index 6490189..a35b8fd 100644 --- a/sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php +++ b/sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php @@ -63,12 +63,12 @@ trait ObjectArraySearchAndSortTrait /** * Сортирует массив объектов, по значению свойства объекта. * - * @param string $objectProperty Имя свойства объекта + * @param string $property Имя свойства объекта * @param bool $descending Направление сортировки * * @return void */ - public function Sort (string $objectProperty, bool $descending = false): void + public function Sort (string $property = '', bool $descending = false): void { // Создаём результирующий массив $result = array_merge($this->Container, []); @@ -77,8 +77,8 @@ trait ObjectArraySearchAndSortTrait usort($result, fn ($a, $b) => !$descending - ? $a->$objectProperty <=> $b->$objectProperty - : $b->$objectProperty <=> $a->$objectProperty); + ? $a->$property <=> $b->$property + : $b->$property <=> $a->$property); // Присваиваем результат $this->Container = $result; diff --git a/sources/types/GUID.md b/sources/types/GUID.md index 0c529d1..6f4c853 100644 --- a/sources/types/GUID.md +++ b/sources/types/GUID.md @@ -40,7 +40,7 @@ ### Перевод в строку. -За перевод в строку отвечают 2 метода: «магический метод» `__toString` и `ToString`. +За перевод в строку отвечают 3 метода: «магический метод» `__toString`, `ToString` и `Segment`. #### «Магический метод» `__toString` @@ -82,6 +82,83 @@ 00000000-0000-0000-0000-000000000000 +#### Метод `Segment` + +Этот метод возвращает сегмент GUID по его номеру. Он имеет **1 обязательный параметр** - номер сегмента +`int $segmentNumber`. + +Метод возвращает `string` - строковое представление сегмента GUID. + +**ВАЖНО:** значение `$segmentNumber` должно быть от 1 до 5 включительно. В противном случае выбросится исключение +`OutOfRangeException`. + +Синтаксис: + + public function Segment (int $segmentNumber): string + +**Пример:** + + // Создаю пустой GUID + $guid = new GUID ('00000000-0000-0000-0000-000000000000'); + // Вывожу его 1 сегмент + echo $guid->Segment(1); + // С новой строки + echo '
'; + // Ошибка + try { + echo $guid->Segment(0); + } catch (OutOfRangeException $e) { + echo $e->getMessage(); + } + +В результате, на экране появится: + + 00000000 + Номер сегмента должен быть между 1 и 5 / Segment number must be between 1 and 5. + +### Перевод из строки. + +За перевод из строки отвечают 2 метода: конструктор и `Parse`. + +#### Метод `Parse` + +Этот статический метод переводит строку в GUID. Он принимает только **1 обязательный параметр** - строковое +представление +GUID `string $guidString` и **1 необязательный параметр** - действие при некорректном GUID `bool $emptyIfNotValid`: +`true` - вернётся пустой GUID, `false` - выбросится исключение типа `InvalidArgumentException`, который по умолчанию +выбрасывает исключение. + +Метод возвращает объект класса `GUID`, полученный из строкового представления. + +**ВАЖНО:** может выбрасываться исключение `InvalidArgumentException` при некорректном GUID и отключённом параметре +`$emptyIfNotValid`. + +Синтаксис: + + public static function Parse (string $guidString, bool $emptyIfNotValid = false): GUID + +**Пример:** + + // Создаю пустой GUID + $guid1 = GUID::Parse ('00000000-0000-0000-0000-000000000000', true); + // Вывожу его + echo "guid1 = $guid1"; + + // Разделитель + echo '
'; + + try { + // Создаю из ошибочного GUID + $guid2 = GUID::Parse('ЭТО ОШИБКА!!!') + } catch (InvalidArgumentException $e) { + echo $e->getMessage(); + } + +В результате, на экране появится: + + 00000000-0000-0000-0000-000000000000 + Предан неверный GUID / Wrong GUID. + ### Работа с массивом байтов Для преобразования GUID в массив байтов и обратно используется 2 метода: `ToBytes` и `FromBytes`. @@ -153,392 +230,109 @@ 00000000-0000-0000-0000-000000000000 -#### Метод `ReadInt` +### Генерация GUID -Это метод, который читает значение ключа JSON. Он имеет **1 обязательный параметр** `string $key` (ключ) и **1 -необязательный параметр** `int $default` (значение по умолчанию, задан по умолчанию в `0`). - -Этот метод возвращает `int`: значение ключа JSON или значение по умолчанию. +За генерацию GUID отвечает статический метод `Generate`. Это метод не имеет параметров и возвращает сгенерированный +GUID. Синтаксис: - 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 + public static function Generate (): GUID **Пример,** -Пусть для примера, класс `Demo` из namespace `iam\namespace` реализует интерфейс `ISerializable`. + // Создаю GUID + $guid = GUID::Generate (); + // Выводим + echo $guid; - // Создаю класс - $json = new JsonReWriter(); - // ... Здесь где-то загрузка данных - // Получаю класс - try { - /** - * @var Demo $unSerializableClass - */ - $unSerializableClass = $json->ReadSerializable("test", "iam\\namespace\\Demo"); - } catch (JsonException $e) { - echo $e->getMessage(); - } +В результате, например, на экране появится: -В результате, переменная `$unSerializableClass` будет содержать данные класса `Demo`. + 5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1 -### Запись данных +### Валидация GUID -Для чтения данных используется один общий метод `Write` и 3 его производных метода: `WriteArray`, `WriteObject` и -`WriteSerializable`. +Для валидации GUID используется 2 метода: `Validate` и `isInvalidOrEmpty`. -**Важно!** Лобой из вышеуказанных методов может выбросить исключение `JsonException`, если ключ не содержит вложений, -хотя от него требуется обратное. +#### Метод `Validate` -#### Метод `Write` +Это статичный метод проверяет корректность GUID. Он имеет только **1 параметр** - объект GUID или его строковое представление для проверки `GUID|null|string $guid`. -Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**: - -- `string $key` (ключ); -- `mixed $value` (записываемое значение). - -Этот метод ничего не возвращает. +Этот метод возвращает `bool`: результат проверки. Синтаксис: - public function Write (string $key, mixed $value): void + public static function Validate (string|GUID|null $guid): 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); + // Валидация класса GUID + echo GUID::Validate(new GUID ('00000000-0000-0000-0000-000000000000')) ? 'GUID верен' : 'GUID ошибочен'; -Содержимое файла `test.json` представлено далее: + // Разделитель + echo '
'; - { - "test": { - "subtest": { - "AAA": "123", - "BBB": 1.23 - } - }, - "test1": { - "test": 123 - }, - "test2": { - "test": true - }, - "test3": { - "test": { - "res": "[1,2,3]" - } - } - } + // Валидация строки + echo GUID::Validate('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1') ? 'GUID верен' : 'GUID ошибочен'; + + // Разделитель + echo '
'; -#### Метод `WriteArray` + // Валидация ошибки + echo GUID::Validate('НЕ GUID') ? 'GUID верен' : 'GUID ошибочен'; -Это метод, который записывает значение в ключ JSON. Он имеет **2 обязательных параметра**: +В результате, на экране появится: -- `string $key` (ключ); -- `array $array` (записываемое значение). + GUID верен + GUID верен + GUID ошибочен -Этот метод ничего не возвращает. +#### Метод `isInvalidOrEmpty` + +Это статический метод, который проверяет объекты GUID на корректность и на «пустое» значение. Он имеет только **1 параметр** - объект GUID или `null` для проверки `?GUID $guid`. + +Этот метод возвращает `bool`: результат проверки GUID. Синтаксис: - 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 + public static function isInvalidOrEmpty (?GUID $guid): 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/ССС"); + // Валидация класса GUID + echo GUID::isInvalidOrEmpty(new GUID ('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1')) ? 'GUID верен' : 'GUID ошибочен'; -В результате, `$check1` будет `true`, а `$check2` - `false`. + // Разделитель + echo '
'; -#### Метод `GetKeys` + // Валидация пустого GUID + echo GUID::isInvalidOrEmpty('00000000-0000-0000-0000-000000000000') ? 'GUID верен' : 'GUID ошибочен'; + + // Разделитель + echo '
'; -Это метод получает список ключей. Он имеет **2 необязательных параметра**: + // Валидация null + echo GUID::isInvalidOrEmpty(null) ? 'GUID верен' : 'GUID ошибочен'; -- `string $parentKey` (ключ родителя (или "" (установлено по умолчанию) для всех); -- `bool $includeChildren` (нужно ли включать дочерние ключи (по умолчанию, да)). +В результате, на экране появится: -Этот метод возвращает `array`: список ключей. + GUID верен + GUID ошибочен + GUID ошибочен + +### Пустой GUID + +За получение пустого GUID отвечает статический метод `Empty`. Это метод не имеет параметров и возвращает пустой GUID (`00000000-0000-0000-0000-000000000000`) Синтаксис: - public function GetKeys (string $parentKey = "", bool $includeChildren = true): array + public static function Empty (): GUID **Пример,** - // Создаём класс - $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(); + // Выводим + echo GUID::Empty(); -В результате, `$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 + 00000000-0000-0000-0000-000000000000 \ No newline at end of file diff --git a/sources/types/GUID.php b/sources/types/GUID.php index 62743dd..78077f1 100644 --- a/sources/types/GUID.php +++ b/sources/types/GUID.php @@ -61,34 +61,6 @@ final class GUID implements IArrayable, IDuplicated, ISerializable, IComparable, $this->Value = $value; } - /** - * Возвращает пустой GUID. - * - * @return GUID Пустой GUID. - */ - public static function Empty (): GUID - { - return new GUID(); - } - - // Подключаем трейт реализующий интерфейс ISerializable - use GUIDSerializeTrait; - - // Подключаем трейт реализующий интерфейс IArrayable - use GUIDArrayableTrait; - - // Подключаем трейт реализующий интерфейс IDuplicated - use GUIDDuplicatedTrait; - - // Подключаем трейт реализующий интерфейс JsonSerializable - use GUIDJsonSerializableTrait; - - // Подключаем трейт реализующий интерфейс IHashable - use GUIDHashableTrait; - - // Подключаем трейт реализующий интерфейс IComparable - use GUIDComparableTrait; - /** * Генерация нового случайного GUID. * @@ -129,6 +101,24 @@ final class GUID implements IArrayable, IDuplicated, ISerializable, IComparable, return new self($guid); } + // Подключаем трейт реализующий интерфейс ISerializable + use GUIDSerializeTrait; + + // Подключаем трейт реализующий интерфейс IArrayable + use GUIDArrayableTrait; + + // Подключаем трейт реализующий интерфейс IDuplicated + use GUIDDuplicatedTrait; + + // Подключаем трейт реализующий интерфейс JsonSerializable + use GUIDJsonSerializableTrait; + + // Подключаем трейт реализующий интерфейс IHashable + use GUIDHashableTrait; + + // Подключаем трейт реализующий интерфейс IComparable + use GUIDComparableTrait; + /** * Проверяет, является ли GUID пустым или недействительным. * @@ -138,17 +128,17 @@ final class GUID implements IArrayable, IDuplicated, ISerializable, IComparable, */ public static function isInvalidOrEmpty (?GUID $guid): bool { - return !self::Validate($guid) || $guid === self::EMPTY; + return !self::Validate($guid) || $guid->IsEqualsTo(self::Empty()); } /** * Валидирует строку GUID. * - * @param mixed $guid Объект GUID или строка для проверки. + * @param string|GUID|null $guid Объект GUID или его строковое представление для проверки. * * @return bool Результат проверки. */ - public static function Validate (mixed $guid): bool + public static function Validate (string|GUID|null $guid): bool { // Проверка на пустое значение if (empty($guid)) @@ -164,6 +154,16 @@ final class GUID implements IArrayable, IDuplicated, ISerializable, IComparable, return preg_match('/^[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}$/', $guid) > 0; } + /** + * Возвращает пустой GUID. + * + * @return GUID Пустой GUID. + */ + public static function Empty (): GUID + { + return new GUID(); + } + /** * Создает экземпляр GUID из массива байтов. * @@ -193,19 +193,26 @@ final class GUID implements IArrayable, IDuplicated, ISerializable, IComparable, /** * Создает экземпляр GUID из строки GUID. * - * @param string $guidString Строка GUID. + * @param string $guidString Строковое представление GUID. + * @param bool $emptyIfNotValid Если GUID недействителен, возвращать пустой GUID или выбрасывать исключение. По + * умолчанию: выбрасывать исключение. * - * @return GUID Класс GUID. + * @return GUID Экземпляр GUID. */ - public static function Parse (string $guidString): GUID + public static function Parse (string $guidString, bool $emptyIfNotValid = false): GUID { - return - // Проверка на валидность переданного GUID - !self::Validate($guidString) - // - если GUID недействителен, выбрасываем исключение - ? throw new InvalidArgumentException('Предан неверный GUID / Wrong GUID.') - // - иначе, создаем экземпляр GUID из строки - : new GUID($guidString); + // Проверка на валидность GUID + if (self::Validate($guidString)) + // - если GUID действителен, возвращаем экземпляр GUID + return new GUID($guidString); + + // Если же GUID недействителен и запрещено выбрасывать исключение + if ($emptyIfNotValid) + // -- то возвращаем пустой GUID + return self::Empty(); + else + // -- иначе выбрасываем исключение + throw new InvalidArgumentException('Предан неверный GUID / Wrong GUID.'); } /** diff --git a/tests/types/GUIDTest.php b/tests/types/GUIDTest.php index f154906..7f2e047 100644 --- a/tests/types/GUIDTest.php +++ b/tests/types/GUIDTest.php @@ -3,6 +3,8 @@ namespace goodboyalex\php_components_pack\tests\types; use goodboyalex\php_components_pack\types\GUID; +use InvalidArgumentException; +use OutOfRangeException; use PHPUnit\Framework\TestCase; class GUIDTest extends TestCase @@ -28,26 +30,57 @@ class GUIDTest extends TestCase public function testSegment () { + $this->PrepareForTest(); + $guid = new GUID ('00000000-0000-0000-0000-000000000000'); + + $this->assertEquals('00000000', $guid->Segment(1)); + + $this->expectException(OutOfRangeException::class); + $guid->Segment(0); } public function testToString () { + $this->PrepareForTest(); + $guid = new GUID ('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1'); + + $this->assertEquals('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1', $guid->ToString()); } public function testIsInvalidOrEmpty () { + $this->PrepareForTest(); + $this->assertFalse(GUID::isInvalidOrEmpty(new GUID ('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1'))); + $this->assertTrue(GUID::isInvalidOrEmpty(new GUID ('00000000-0000-0000-0000-000000000000'))); + $this->assertTrue(GUID::isInvalidOrEmpty(null)); } public function testParse () { + $this->PrepareForTest(); + $guid = new GUID ('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1'); + + $parsed = GUID::Parse('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1', true); + + $this->assertTrue($guid->IsEqualsTo($parsed)); + + $this->expectException(InvalidArgumentException::class); + GUID::Parse('НЕ GUID'); } public function test__toString () { + $this->PrepareForTest(); + + $guid = new GUID ('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1'); + + $str = "$guid"; + + $this->assertEquals('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1', $str); } public function testToBytes () @@ -80,11 +113,17 @@ class GUIDTest extends TestCase public function testGenerate () { + $this->PrepareForTest(); + $guid = GUID::Generate(); + + self::assertFalse(GUID::isInvalidOrEmpty($guid)); } public function testFromBytes () { + $this->PrepareForTest(); + // Создаю массив $array = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; @@ -93,11 +132,14 @@ class GUIDTest extends TestCase // И вывожу его self::assertEquals('00000000-0000-0000-0000-000000000000', $guid->ToString()); - } public function testValidate () { + $this->PrepareForTest(); + $this->assertTrue(GUID::Validate(new GUID ('00000000-0000-0000-0000-000000000000'))); + $this->assertTrue(GUID::Validate('5c0e5f0e-d033-44b1-a0b6-d0e2e369bdd1')); + $this->assertFalse(GUID::Validate('НЕ GUID')); } }