20250203
This commit is contained in:
		
							
								
								
									
										363
									
								
								sources/classes/ActionState.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								sources/classes/ActionState.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,363 @@ | ||||
| <?php | ||||
| /** | ||||
|  * Отключаем ненужные проверки. | ||||
|  * | ||||
|  * @noinspection PhpUnusedParameterInspection, PhpUnused | ||||
|  */ | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\classes; | ||||
|  | ||||
| use Closure; | ||||
| use goodboyalex\php_components_pack\enums\MessageType; | ||||
| use goodboyalex\php_components_pack\interfaces\ISerializable; | ||||
| use goodboyalex\php_components_pack\models\ActionStateMessageModel; | ||||
|  | ||||
| /** | ||||
|  * Состояние действия. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class ActionState implements ISerializable | ||||
| { | ||||
|     /** | ||||
|      * @var mixed|null $Value Значение | ||||
|      */ | ||||
|     public mixed $Value; | ||||
|  | ||||
|     /** | ||||
|      * @var array $Messages Список информации | ||||
|      */ | ||||
|     private array $Messages = []; | ||||
|  | ||||
|     /** | ||||
|      * Конструктор | ||||
|      * | ||||
|      * @param mixed|null $defValue Значение по умолчанию | ||||
|      */ | ||||
|     public function __construct (mixed $defValue = null) | ||||
|     { | ||||
|         $this->Value = $defValue; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * При выводе GetStringMessages выводит только ошибки. | ||||
|      * | ||||
|      * @return Closure Возвращает функцию, проверяющую сообщение на соответствие типу. | ||||
|      */ | ||||
|     public static function GET_STRING_ERROR_ONLY (): Closure | ||||
|     { | ||||
|         return fn (ActionStateMessageModel $message) | ||||
|             => $message->MessageType === MessageType::Error; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * При выводе GetStringMessages выводит ошибки и предупреждения. | ||||
|      * | ||||
|      * @return Closure Возвращает функцию, проверяющую сообщение на соответствие типу. | ||||
|      */ | ||||
|     public static function GET_STRING_ERROR_AND_WARNING (): Closure | ||||
|     { | ||||
|         return fn (ActionStateMessageModel $message) | ||||
|             => $message->MessageType === MessageType::Error | ||||
|             || $message->MessageType === MessageType::Warning; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * При выводе GetStringMessages выводит все сообщения. | ||||
|      * | ||||
|      * @return Closure Возвращает функцию, проверяющую сообщение на соответствие типу. | ||||
|      */ | ||||
|     public static function GET_STRING_ALL (): Closure | ||||
|     { | ||||
|         return fn (ActionStateMessageModel $message) => true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет данные из другого состояния. | ||||
|      * | ||||
|      * @param ActionState $state Другое состояние | ||||
|      * @param bool $clearAllBefore Очищать сообщения перед добавлением (true) или просто добавить к текущим (false) | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddState (ActionState $state, bool $clearAllBefore = false): void | ||||
|     { | ||||
|         // Если нужно очистить список сообщений | ||||
|         if ($clearAllBefore) | ||||
|             // - то очищаю список сообщений | ||||
|             $this->Clear(fn (ActionStateMessageModel $message) => true); | ||||
|  | ||||
|         // Добавляю сообщения из другого состояния | ||||
|         $this->AddRange($state->GetMessages(function (ActionStateMessageModel $message) | ||||
|         { | ||||
|             return true; | ||||
|         })); | ||||
|  | ||||
|         // Добавляю значение | ||||
|         $this->Value = $state->Value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Очищает список сообщений, согласно условию. | ||||
|      * | ||||
|      * @param callable $predicate Условие выборки | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function Clear (callable $predicate): void | ||||
|     { | ||||
|         // Выбираю все сообщения, удовлетворяющие условию | ||||
|         $list = $this->GetMessages($predicate); | ||||
|  | ||||
|         // Удаляю их из списка | ||||
|         $this->Messages = array_diff($this->Messages, $list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Выбирает сообщения по условию predicate. | ||||
|      * | ||||
|      * @param callable $predicate Условие выборки | ||||
|      * | ||||
|      * @return array Список отобранных сообщений | ||||
|      */ | ||||
|     public function GetMessages (callable $predicate): array | ||||
|     { | ||||
|         // Получаю список элементов | ||||
|         $list = []; | ||||
|  | ||||
|         // Для каждого элемента | ||||
|         foreach ($this->Messages as $actionStateMessage) | ||||
|             // - если он подходит под условие | ||||
|             if ($predicate($actionStateMessage)) | ||||
|                 // - добавляю его в список | ||||
|                 $list[] = $actionStateMessage; | ||||
|  | ||||
|         // Возвращаю список | ||||
|         return $list; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет список | ||||
|      * | ||||
|      * @param array $messages Список сообщений | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddRange (array $messages): void | ||||
|     { | ||||
|         $this->Messages = array_merge($this->Messages, $messages); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Возвращает список сообщений (параметр Message у каждого сообщения). | ||||
|      * | ||||
|      * @param callable $predicate Условие выборки | ||||
|      * @param string $separator Разделитель | ||||
|      * | ||||
|      * @return string Список сообщений | ||||
|      */ | ||||
|     public function GetStringMessages (callable $predicate, string $separator = '\n'): string | ||||
|     { | ||||
|         // Делаю выборку | ||||
|         $list = $this->GetMessages($predicate); | ||||
|  | ||||
|         // Формирую список сообщений | ||||
|         $result = []; | ||||
|  | ||||
|         // Для каждого сообщения из выборки | ||||
|         foreach ($list as $message) { | ||||
|             // - если оно не нужного нам класса | ||||
|             if (!$message instanceof ActionStateMessageModel) | ||||
|                 // -- то пропускаю | ||||
|                 continue; | ||||
|  | ||||
|             // - добавляю сообщение | ||||
|             $result[] = $message->Message; | ||||
|         } | ||||
|  | ||||
|         // Возвращаю список | ||||
|         return implode($separator, $result); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет сообщение о критической ошибке. | ||||
|      * | ||||
|      * @param string $message Сообщение | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddCritical (string $message): void | ||||
|     { | ||||
|         $this->Add(new ActionStateMessageModel(MessageType::Error, true, $message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавление сообщения. | ||||
|      * | ||||
|      * @param ActionStateMessageModel $message Сообщение | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function Add (ActionStateMessageModel $message): void | ||||
|     { | ||||
|         $this->Messages[] = $message; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет сообщение об ошибке. | ||||
|      * | ||||
|      * @param string $message Сообщение | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddError (string $message): void | ||||
|     { | ||||
|         $this->Add(new ActionStateMessageModel(MessageType::Error, false, $message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет предупреждение. | ||||
|      * | ||||
|      * @param string $message Сообщение. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddWarning (string $message): void | ||||
|     { | ||||
|         $this->Add(new ActionStateMessageModel(MessageType::Warning, false, $message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Добавляет информационное сообщение. | ||||
|      * | ||||
|      * @param string $message Сообщение. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function AddInfo (string $message): void | ||||
|     { | ||||
|         $this->Add(new ActionStateMessageModel(MessageType::Info, false, $message)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, есть ли информационные сообщения. | ||||
|      * | ||||
|      * @return bool Наличие сообщений | ||||
|      */ | ||||
|     public function HasInfos (): bool | ||||
|     { | ||||
|         return $this->Count(fn (ActionStateMessageModel $message) => $message->MessageType == MessageType::Info) > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Количество сообщений, удовлетворяющих условию. | ||||
|      * | ||||
|      * @param callable $predicate Условие выборки | ||||
|      * | ||||
|      * @return int Число сообщений | ||||
|      */ | ||||
|     public function Count (callable $predicate): int | ||||
|     { | ||||
|         // Получаю список сообщений | ||||
|         $list = $this->GetMessages($predicate); | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return count($list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, успешно ли завершилась операция. | ||||
|      * | ||||
|      * @param bool $onlyCritical Игнорировать все некритические ошибки и предупреждения (не рекомендуется!) | ||||
|      * | ||||
|      * @return bool Успешно ли завершилась операция. | ||||
|      */ | ||||
|     public function IsSuccess (bool $onlyCritical = false): bool | ||||
|     { | ||||
|         // Если нужно учитывать только критические ошибки | ||||
|         if ($onlyCritical) | ||||
|             // - то проверяю наличие критических ошибок | ||||
|             return !$this->HasErrors($onlyCritical); | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return !$this->HasErrors() && !$this->HasWarnings(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, есть ли ошибки. | ||||
|      * | ||||
|      * @param bool $onlyCritical Учитывать только критические ошибки. | ||||
|      * | ||||
|      * @return bool Наличие ошибок. | ||||
|      */ | ||||
|     public function HasErrors (bool $onlyCritical = false): bool | ||||
|     { | ||||
|         return $this->Count(function (ActionStateMessageModel $message) use ($onlyCritical): bool | ||||
|         { | ||||
|             // - сравниваю тип сообщения | ||||
|             if ($message->MessageType != MessageType::Error) | ||||
|                 // -- если не совпадает, то возвращаю false | ||||
|                 return false; | ||||
|  | ||||
|             // - если нужно выводить только критические ошибки, а сообщение не критическое | ||||
|             if ($onlyCritical && !$message->IsCritical) | ||||
|                 // -- то возвращаю false | ||||
|                 return false; | ||||
|  | ||||
|             // Возвращаю true | ||||
|             return true; | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, есть ли предупреждения. | ||||
|      * | ||||
|      * @return bool Наличие предупреждений | ||||
|      */ | ||||
|     public function HasWarnings (): bool | ||||
|     { | ||||
|         return $this->Count(fn (ActionStateMessageModel $message) => $message->MessageType == MessageType::Warning) > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function Serialize (): string | ||||
|     { | ||||
|         // Создаю список сообщений | ||||
|         $list = []; | ||||
|  | ||||
|         // Для каждого сообщения | ||||
|         foreach ($this->Messages as $message) | ||||
|             // - сериализую его и добавляю в список | ||||
|             $list[] = $message->Serialize(); | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return serialize($list); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function UnSerialize (string $serialized): void | ||||
|     { | ||||
|         // Очищаю список сообщений | ||||
|         $this->Clear(fn (ActionStateMessageModel $message) => true); | ||||
|  | ||||
|         // Десериализую список сообщений | ||||
|         $list = unserialize($serialized); | ||||
|  | ||||
|         // Для каждого сообщения | ||||
|         foreach ($list as $messageSerialized) { | ||||
|             // - создаю новое сообщение | ||||
|             $message = new ActionStateMessageModel(); | ||||
|             // - десериализую его | ||||
|             $message->UnSerialize($messageSerialized); | ||||
|             // - добавляю в список | ||||
|             $this->Add($message); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										335
									
								
								sources/classes/ClassMapper.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										335
									
								
								sources/classes/ClassMapper.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,335 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\classes; | ||||
|  | ||||
| use DateTimeImmutable; | ||||
| use DateTimeInterface; | ||||
| use Exception; | ||||
| use ReflectionClass; | ||||
| use ReflectionException; | ||||
| use stdClass; | ||||
| use UnitEnum; | ||||
|  | ||||
| /** | ||||
|  * Класс сопоставлений классов и объектов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class ClassMapper | ||||
| { | ||||
|     /** | ||||
|      * @var array $DefaultOptions Настройки | ||||
|      */ | ||||
|     public const array DefaultOptions = [ | ||||
|         'ignored' => [], | ||||
|         'allowed' => [] | ||||
|     ]; | ||||
|  | ||||
|     /** | ||||
|      * Передаёт одинаковые параметры из класса $from в класс $to, учитывая игнорируемые ($ignoredProperties) и | ||||
|      * разрешенные ($allowedProperties) свойства. | ||||
|      * | ||||
|      * @param object $from Класс-донор | ||||
|      * @param object $to Класс-приемник | ||||
|      * @param array $options Параметры привязки свойств (см атрибут Bind). | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public static function MapClass (object $from, object $to, array $options = self::DefaultOptions): void | ||||
|     { | ||||
|         // Если есть игнорируемые или разрешенные свойства | ||||
|         if (!(count($options['ignored']) == 0 && count($options['allowed']) == 0)) | ||||
|             // -- то для каждого игнорируемого свойства | ||||
|             foreach ($options['ignored'] as $ignoredProperty) | ||||
|                 // --- и если оно есть в массиве разрешенных | ||||
|                 if (in_array($ignoredProperty, $options['allowed'])) | ||||
|                     // ---- то исключаю его из массива разрешенных | ||||
|                     unset($options['allowed'][array_search($ignoredProperty, $options['allowed'])]); | ||||
|  | ||||
|         // Получаю массив свойств | ||||
|         $properties = get_class_vars(get_class($from)); | ||||
|  | ||||
|         // Для каждого элемента массива | ||||
|         foreach ($properties as $name => $value) { | ||||
|             // - если свойство игнорируется | ||||
|             if (in_array($name, $options['ignored'])) | ||||
|                 // -- пропускаю | ||||
|                 continue; | ||||
|  | ||||
|             // - если свойство не разрешено | ||||
|             if (count($options['allowed']) > 0 && !in_array($name, $options['allowed'])) | ||||
|                 // -- пропускаю | ||||
|                 continue; | ||||
|  | ||||
|             // - если свойство есть в объекте | ||||
|             if (property_exists($to, $name)) | ||||
|                 // -- то присваиваю значение | ||||
|                 $to->$name = $from->$name; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Подготавливает значения свойств класса. | ||||
|      * | ||||
|      * @param array $params Данные запроса. | ||||
|      * @param ReflectionClass $classReflector Анализатор класса. | ||||
|      * @param array $options Массив свойств привязки. | ||||
|      * | ||||
|      * @return array Массив данных класса. | ||||
|      */ | ||||
|     public static function PrepareClassProperties (array $params, ReflectionClass $classReflector, | ||||
|         array $options = self::DefaultOptions): array | ||||
|     { | ||||
|         // Создаю массив данных класса | ||||
|         $classData = []; | ||||
|  | ||||
|         // Для каждого свойства класса | ||||
|         foreach ($classReflector->getProperties() as $property) { | ||||
|             // - получаю имя свойства | ||||
|             $propertyName = $property->getName(); | ||||
|  | ||||
|             // - если это свойство задано в массиве параметров | ||||
|             if (array_key_exists($propertyName, $params)) { | ||||
|                 // -- если задан массив разрешённых свойств | ||||
|                 if (!empty($options["allowed"])) | ||||
|                     // --- если свойство не разрешено | ||||
|                     if (!in_array($propertyName, $options["allowed"])) | ||||
|                         // ---- то пропускаю | ||||
|                         continue; | ||||
|  | ||||
|                 // -- если задан массив запрещённых свойств | ||||
|                 if (!empty($options["ignored"])) | ||||
|                     // --- если свойство должно игнорироваться | ||||
|                     if (in_array($propertyName, $options["ignored"])) | ||||
|                         // ---- то пропускаю | ||||
|                         continue; | ||||
|  | ||||
|                 // -- добавляю значение свойства в результат | ||||
|                 $classData[$propertyName] = $params[$propertyName]; | ||||
|             } | ||||
|             else { | ||||
|                 // - в противном случае, пробегаю массив параметров | ||||
|                 foreach ($params as $key => $value) { | ||||
|                     // -- если в имени параметра есть разделитель "_" | ||||
|                     if (str_starts_with($key, $propertyName . "_")) { | ||||
|                         // -- разбиваю имя параметра на части | ||||
|                         $keyParts = explode("_", $key); | ||||
|  | ||||
|                         // -- добавляю значение свойства в результат | ||||
|                         self::GetClassParametersArrayParser($classData, $keyParts, $value); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Возвращаю массив данных класса | ||||
|         return $classData; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Парсит массив свойств класса. | ||||
|      * | ||||
|      * @param array $source Исходный массив (он же и результат парсинга). | ||||
|      * @param array $parametersKeys Массив имен свойств. Например, Page_Meta_Id должен быть разбит на | ||||
|      * ["Page", "Meta", "Id"]. | ||||
|      * @param mixed $value Значение свойства. | ||||
|      * @param array $options Массив параметров привязки свойств. | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public static function GetClassParametersArrayParser (array &$source, array $parametersKeys, mixed $value, | ||||
|         array $options = self::DefaultOptions): void | ||||
|     { | ||||
|         // Если массив имен свойств пустой | ||||
|         if (empty($parametersKeys)) | ||||
|             // - то прерываю парсинг | ||||
|             return; | ||||
|  | ||||
|         // Получаю имя текущего свойства | ||||
|         $currentName = array_shift($parametersKeys); | ||||
|  | ||||
|         // Если текущего свойства нет в массиве | ||||
|         if (!isset($source[$currentName])) | ||||
|             // - то создаю его | ||||
|             $source[$currentName] = []; | ||||
|  | ||||
|         // Если массив имен свойств содержит только одно свойство | ||||
|         if (count($parametersKeys) === 0) { | ||||
|             // - если задан массив разрешённых свойств | ||||
|             if (!empty($options["allowed"])) | ||||
|                 // --- если свойство не разрешено | ||||
|                 if (!in_array($currentName, $options["allowed"])) | ||||
|                     // ---- то пропускаю | ||||
|                     return; | ||||
|  | ||||
|             // -- если задан массив запрещённых свойств | ||||
|             if (!empty($options["ignored"])) | ||||
|                 // --- если свойство должно игнорироваться | ||||
|                 if (in_array($currentName, $options["ignored"])) | ||||
|                     // ---- то пропускаю | ||||
|                     return; | ||||
|  | ||||
|             // - добавляю значение свойства в результат | ||||
|             $source[$currentName] = $value; | ||||
|         } | ||||
|         else | ||||
|             // - иначе продолжаю парсинг | ||||
|             self::GetClassParametersArrayParser($source[$currentName], $parametersKeys, $value, $options); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Переводит данные из массива в объект класса. | ||||
|      * | ||||
|      * @param string $className Имя класса | ||||
|      * @param array $properties Массив данных | ||||
|      * | ||||
|      * @return mixed Объект класса | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function MapToClassProperty (string $className, array $properties): mixed | ||||
|     { | ||||
|         // Создаю | ||||
|         try { | ||||
|             $classReflector = new ReflectionClass($className); | ||||
|  | ||||
|             // Создаю объект класса | ||||
|             $classObj = new $className(); | ||||
|  | ||||
|             // Для каждого свойства класса | ||||
|             foreach ($properties as $key => $value) { | ||||
|                 // - проверяю наличие свойства | ||||
|                 if (!$classReflector->hasProperty($key)) | ||||
|                     // -- иду к следующему | ||||
|                     continue; | ||||
|  | ||||
|                 // - получаю данные про свойство | ||||
|                 // -- само свойство | ||||
|                 $property = $classReflector->getProperty($key); | ||||
|                 // -- тип свойства | ||||
|                 $propertyType = $property->getType(); | ||||
|  | ||||
|                 // - если значение является классом | ||||
|                 if (!$propertyType->isBuiltin() && is_array($value)) { | ||||
|                     // -- присваиваю объект | ||||
|                     self::SetParameterToClass($classReflector, $key, $classObj, | ||||
|                         self::MapToClassProperty($propertyType->getName(), $value)); | ||||
|  | ||||
|                     // -- следующий элемент | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // - если значение является датой | ||||
|                 if ($classObj->$key instanceof DateTimeInterface) { | ||||
|                     // -- получаю дату | ||||
|                     $dateValue = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $value . " 00:00:00"); | ||||
|  | ||||
|                     // -- если не получилось | ||||
|                     if ($dateValue === false) | ||||
|                         // --- то добавляю дату по умолчанию (1970-01-01 00:00:00) | ||||
|                         $dateValue = DateTimeImmutable::createFromFormat('Y-m-d H:i:s', "1970-01-01 00:00:00"); | ||||
|  | ||||
|                     // -- присваиваю дату | ||||
|                     self::SetParameterToClass($classReflector, $key, $classObj, $dateValue); | ||||
|  | ||||
|                     // -- следующий элемент | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // - если значение является перечислением | ||||
|                 if ($classObj->$key instanceof UnitEnum) { | ||||
|                     // -- если значение уже является перечислением | ||||
|                     if ($value instanceof UnitEnum) | ||||
|                         // --- присваиваю перечисление | ||||
|                         self::SetParameterToClass($classReflector, $key, $classObj, $value); | ||||
|                     else | ||||
|                         // -- иначе | ||||
|                         self::SetParameterToClass($classReflector, $key, $classObj, | ||||
|                             is_numeric($value) ? $classObj->$key::FromInt($value) : $classObj->$key::FromName($value)); | ||||
|  | ||||
|                     // -- следующий элемент | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // - если значение является NULL | ||||
|                 if ($value == "null") { | ||||
|                     // -- присваиваю NULL | ||||
|                     self::SetParameterToClass($classReflector, $key, $classObj, | ||||
|                         is_array($key) ? [] : null); | ||||
|  | ||||
|                     // -- следующий элемент | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // - присваиваю значение | ||||
|                 self::SetParameterToClass($classReflector, $key, $classObj, $value); | ||||
|             } | ||||
|  | ||||
|             // Возвращаю объект класса | ||||
|             return $classObj; | ||||
|         } | ||||
|         catch (Exception $exception) { | ||||
|             throw new Exception($exception->getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Присваивает значение параметра объекту класса. | ||||
|      * | ||||
|      * @param ReflectionClass $classReflector Рефлектор класса. | ||||
|      * @param string $propertyName Имя свойства. | ||||
|      * @param mixed $classObj Объект класса. | ||||
|      * @param mixed $value Значение. | ||||
|      * | ||||
|      * @throws Exception | ||||
|      */ | ||||
|     public static function SetParameterToClass (ReflectionClass $classReflector, string $propertyName, | ||||
|         mixed $classObj, mixed $value): void | ||||
|     { | ||||
|         try { | ||||
|             // Получаю свойство | ||||
|             $property = $classReflector->getProperty($propertyName); | ||||
|  | ||||
|             /** | ||||
|              * Устанавливаю доступ значения свойства. | ||||
|              * | ||||
|              * @noinspection PhpExpressionResultUnusedInspection | ||||
|              */ | ||||
|             $property->setAccessible(true); | ||||
|  | ||||
|             // Если значение null | ||||
|             if ($value == null || $value == "null") | ||||
|                 // - то присваиваю значение по умолчанию | ||||
|                 $value = self::GetDefaults($property->getType()->getName()); | ||||
|  | ||||
|             // Присваиваю значение | ||||
|             $property->setValue($classObj, $value); | ||||
|         } | ||||
|         catch (ReflectionException $exception) { | ||||
|             // Выбрасываю исключение | ||||
|             throw new Exception($exception->getMessage()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Получает значение по умолчанию для разных типов данных. | ||||
|      * | ||||
|      * @param string $typeName Имя типа данных. | ||||
|      * | ||||
|      * @return mixed|null Результат. | ||||
|      */ | ||||
|     public static function GetDefaults (string $typeName): mixed | ||||
|     { | ||||
|         return match ($typeName) { | ||||
|             'int' => 0, | ||||
|             'float' => 0.0, | ||||
|             'bool' => false, | ||||
|             'string' => '', | ||||
|             'array' => [], | ||||
|             'object' => new stdClass(), | ||||
|             default => null, | ||||
|         }; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										60
									
								
								sources/classes/ObjectArray.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								sources/classes/ObjectArray.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\classes; | ||||
|  | ||||
| use ArrayAccess; | ||||
| use Countable; | ||||
| use goodboyalex\php_components_pack\interfaces\ISerializable; | ||||
| use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayBasicTrait; | ||||
| use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayConstantsTrait; | ||||
| use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArrayLINQTrait; | ||||
| use goodboyalex\php_components_pack\traits\ObjectArray\ObjectArraySearchAndSortTrait; | ||||
| use IteratorAggregate; | ||||
|  | ||||
| /** | ||||
|  * Класс, описывающий массив объектов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class ObjectArray implements ArrayAccess, IteratorAggregate, Countable, ISerializable | ||||
| { | ||||
|     /** | ||||
|      * @var array $Container Массив объектов, хранящихся в данном классе. | ||||
|      */ | ||||
|     private array $Container; | ||||
|  | ||||
|     // Реализация наследуемых интерфейсов и классов | ||||
|     use ObjectArrayBasicTrait; | ||||
|  | ||||
|     // Константы | ||||
|     use ObjectArrayConstantsTrait; | ||||
|  | ||||
|     // Поиск элемента | ||||
|     use ObjectArraySearchAndSortTrait; | ||||
|  | ||||
|     // LINQ-подобные методы | ||||
|     use ObjectArrayLINQTrait; | ||||
|  | ||||
|     /** | ||||
|      * Конструктор класса. | ||||
|      * | ||||
|      * @param array $array Массив объектов, который будет храниться в данном классе. | ||||
|      */ | ||||
|     public function __construct (array $array = []) | ||||
|     { | ||||
|         $this->Container = $array; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Возвращает массив объектов, хранящихся в данном классе. | ||||
|      * | ||||
|      * @return array Массив объектов, хранящихся в данном классе. | ||||
|      */ | ||||
|     public function ToArray (): array | ||||
|     { | ||||
|         return $this->Container; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								sources/enums/MessageType.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								sources/enums/MessageType.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\enums; | ||||
|  | ||||
| use goodboyalex\php_components_pack\traits\EnumExtensionsTrait; | ||||
|  | ||||
| /** | ||||
|  * Перечисление типов сообщений. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| enum MessageType: int | ||||
| { | ||||
|     // Подключаю расширение для Enum | ||||
|     use EnumExtensionsTrait; | ||||
|  | ||||
|     /** | ||||
|      * Успех | ||||
|      */ | ||||
|     case Success = 0; | ||||
|  | ||||
|     /** | ||||
|      * Информация | ||||
|      */ | ||||
|     case Info = 1; | ||||
|  | ||||
|     /** | ||||
|      * Предупреждение | ||||
|      */ | ||||
|     case Warning = 2; | ||||
|  | ||||
|     /** | ||||
|      * Ошибка | ||||
|      */ | ||||
|     case Error = 3; | ||||
| } | ||||
							
								
								
									
										60
									
								
								sources/extensions/ArrayExtension.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								sources/extensions/ArrayExtension.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\extensions; | ||||
|  | ||||
| /** | ||||
|  * Расширение массивов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class ArrayExtension | ||||
| { | ||||
|     /** | ||||
|      * Удаляет пустые строки в массиве. | ||||
|      * | ||||
|      * @param array $array Исходный массив | ||||
|      * @param bool $reOrder Переиндексировать массив | ||||
|      * | ||||
|      * @return array Результирующим массив без пустых строк | ||||
|      */ | ||||
|     public static function RemoveEmpties (array $array, bool $reOrder = false): array | ||||
|     { | ||||
|         // Удаляем пустые строки | ||||
|         $result = array_filter($array, fn ($value) => !is_null($value) && $value !== ''); | ||||
|  | ||||
|         // Переиндексируем массив | ||||
|         if ($reOrder) | ||||
|             $result = array_values($result); | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Выделяет в смешанном массиве ассоциативный массив | ||||
|      * | ||||
|      * @param array $array Исходный массив | ||||
|      * | ||||
|      * @return array Ассоциативный массив, содержащийся в исходном массиве | ||||
|      */ | ||||
|     public static function GetAssociativePart (array $array): array | ||||
|     { | ||||
|         // Фильтруем массив, оставляя только элементы со строковыми ключами | ||||
|         return array_filter($array, fn ($key) => self::IsStringKey($key), ARRAY_FILTER_USE_KEY); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Функция для проверки, является ли ключ строковым | ||||
|      * | ||||
|      * @param mixed $key Ключ | ||||
|      * | ||||
|      * @return bool Является ли ключ строковым типом | ||||
|      */ | ||||
|     public static function IsStringKey (mixed $key): bool | ||||
|     { | ||||
|         return !is_int($key); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										147
									
								
								sources/extensions/GUIDExtension.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								sources/extensions/GUIDExtension.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,147 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\extensions; | ||||
|  | ||||
| use Random\RandomException; | ||||
|  | ||||
| /** | ||||
|  * Расширение Guid. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class GUIDExtension | ||||
| { | ||||
|     /** | ||||
|      * Пустой Guid. | ||||
|      */ | ||||
|     public const string GUIDEmpty = "00000000-0000-0000-0000-000000000000"; | ||||
|  | ||||
|     /** | ||||
|      * Генерирует Guid. | ||||
|      * | ||||
|      * @return string Сгенерированный Guid. | ||||
|      */ | ||||
|     public static function Generate (): string | ||||
|     { | ||||
|         // Цикл создания Guid | ||||
|         do | ||||
|             $guid = self::DoGenerate(); | ||||
|             // - пока Guid не будет корректен | ||||
|         while (!self::Validate($guid)); | ||||
|  | ||||
|         // Возвращаем Guid | ||||
|         return $guid; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Генерирует Guid. | ||||
|      * | ||||
|      * @return string Сгенерированный Guid. | ||||
|      */ | ||||
|     private static function DoGenerate (): string | ||||
|     { | ||||
|         try { | ||||
|             return sprintf( | ||||
|                 '%04x%04x-%04x-%04x-%04x-%04x%04x%04x', | ||||
|                 // 32 bits for "time_low" | ||||
|                 random_int(0, 0xffff), | ||||
|                 random_int(0, 0xffff), | ||||
|  | ||||
|                 // 16 bits for "time_mid" | ||||
|                 random_int(0, 0xffff), | ||||
|  | ||||
|                 // 16 bits for "time_hi_and_version", | ||||
|                 // four most significant bits holds version number 4 | ||||
|                 random_int(0, 0x0fff) | 0x4000, | ||||
|  | ||||
|                 // 16 bits, 8 bits for "clk_seq_hi_res", | ||||
|                 // 8 bits for "clk_seq_low", | ||||
|                 // two most significant bits holds zero and one for variant DCE1.1 | ||||
|                 random_int(0, 0x3fff) | 0x8000, | ||||
|  | ||||
|                 // 48 bits for "node" | ||||
|                 random_int(0, 0xffff), | ||||
|                 random_int(0, 0xffff), | ||||
|                 random_int(0, 0xffff) | ||||
|             ); | ||||
|         } | ||||
|         catch (RandomException) { | ||||
|             return self::GUIDEmpty; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет Guid на корректность. | ||||
|      * | ||||
|      * @param string|null $str Guid на проверку | ||||
|      * | ||||
|      * @return bool Корректен ли Guid. | ||||
|      */ | ||||
|     public static function Validate (?string $str): bool | ||||
|     { | ||||
|         // Если Guid пустой | ||||
|         if (StringExtension::IsNullOrWhitespace($str)) | ||||
|             // - возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Проверяем длину | ||||
|         $isLenCorrect = strlen($str) == 36; | ||||
|  | ||||
|         // Если длина не корректна | ||||
|         if (!$isLenCorrect) | ||||
|             // - возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Разбиваем на части | ||||
|         $explodedStr = explode("-", $str); | ||||
|  | ||||
|         // Если количество частей не равно 5 | ||||
|         if (count($explodedStr) !== 5) | ||||
|             // - возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Проверяем длину каждой части | ||||
|         // - первая часть должна быть длиной 8 символов | ||||
|         if (strlen($explodedStr[0]) !== 8) | ||||
|             // -- возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // - вторая часть должна быть длиной 4 символа | ||||
|         if (strlen($explodedStr[1]) !== 4) | ||||
|             // -- возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // - третья часть должна быть длиной 4 символа | ||||
|         if (strlen($explodedStr[2]) !== 4) | ||||
|             // -- возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // - четвертая часть должна быть длиной 4 символа | ||||
|         if (strlen($explodedStr[3]) !== 4) | ||||
|             // -- возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // - пятая часть должна быть длиной 12 символов | ||||
|         if (strlen($explodedStr[4]) !== 12) | ||||
|             // -- возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Проверка пройдена | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет Guid на пустоту. | ||||
|      * | ||||
|      * @param string|null $str Guid на проверку | ||||
|      * | ||||
|      * @return bool Пустой ли GUID | ||||
|      */ | ||||
|     public static function IsNotValidOrEmpty (?string $str): bool | ||||
|     { | ||||
|         return !self::Validate($str) || $str == self::GUIDEmpty; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										210
									
								
								sources/extensions/StringExtension.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								sources/extensions/StringExtension.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\extensions; | ||||
|  | ||||
| /** | ||||
|  * Расширение строк. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class StringExtension | ||||
| { | ||||
|     /** | ||||
|      * @var array|string[] $RussianLetters Набор русских букв | ||||
|      */ | ||||
|     private static array $RussianLetters = | ||||
|         [ | ||||
|             'а', 'б', 'в', 'г', 'д', 'е', 'ё', 'ж', 'з', 'и', 'й', | ||||
|             'к', 'л', 'м', 'н', 'о', 'п', 'р', 'с', 'т', 'у', 'ф', | ||||
|             'х', 'ц', 'ч', 'ш', 'щ', 'ъ', 'ы', 'ь', 'э', 'ю', 'я', | ||||
|             'А', 'Б', 'В', 'Г', 'Д', 'Е', 'Ё', 'Ж', 'З', 'И', 'Й', | ||||
|             'К', 'Л', 'М', 'Н', 'О', 'П', 'Р', 'С', 'Т', 'У', 'Ф', | ||||
|             'Х', 'Ц', 'Ч', 'Ш', 'Щ', 'Ъ', 'Ы', 'Ь', 'Э', 'Ю', 'Я' | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * @var array|string[] $RussianLettersTransliteration Набор русских букв в транслитерации | ||||
|      */ | ||||
|     private static array $RussianLettersTransliteration = | ||||
|         [ | ||||
|             "a", "b", "v", "g", "d", "e", "yo", "zh", "z", "i", "j", | ||||
|             "k", "l", "m", "n", "o", "p", "r", "s", "t", "u", "f", | ||||
|             "h", "c", "ch", "sh", "sch", "j", "i", "j", "e", "yu", "ya", | ||||
|             "A", "B", "V", "G", "D", "E", "Yo", "Zh", "Z", "I", "J", | ||||
|             "K", "L", "M", "N", "O", "P", "R", "S", "T", "U", "F", | ||||
|             "H", "C", "Ch", "Sh", "Sch", "J", "I", "J", "E", "Yu", "Ya" | ||||
|         ]; | ||||
|  | ||||
|     /** | ||||
|      * Сравнивает две строки. | ||||
|      * | ||||
|      * @param string|null $str1 Первая строка. | ||||
|      * @param string|null $str2 Вторая строка. | ||||
|      * @param bool $ignoreCase Игнорировать регистр. | ||||
|      * | ||||
|      * @return int Результат сравнения. Возвращаемые значения: | ||||
|      * | ||||
|      *      -1 | значение $str1 меньше значения $str2. | ||||
|      *       0 | значения $str1 и $str2 равны. | ||||
|      *       1 | значение $str1 больше значения $str2. | ||||
|      */ | ||||
|     public static function Compare (string|null $str1, string|null $str2, bool $ignoreCase = false): int | ||||
|     { | ||||
|         // Если оба пусты | ||||
|         if (self::IsNullOrWhitespace($str1) && self::IsNullOrWhitespace($str2)) | ||||
|             // - то равны | ||||
|             return 0; | ||||
|  | ||||
|         // Если первый из них не пуст, а второй пуст | ||||
|         if (!self::IsNullOrWhitespace($str1) && self::IsNullOrWhitespace($str2)) | ||||
|             // - то первый больше | ||||
|             return 1; | ||||
|  | ||||
|         // Если первый из них пуст, а второй не пуст | ||||
|         if (!self::IsNullOrWhitespace($str1) && self::IsNullOrWhitespace($str2)) | ||||
|             // - то первый меньше | ||||
|             return -1; | ||||
|  | ||||
|         // Если нужно игнорировать регистр | ||||
|         if ($ignoreCase) | ||||
|             // - то сравниваем по "человечески" без учёта регистра | ||||
|             return strnatcasecmp($str1, $str2); | ||||
|  | ||||
|         // Иначе сравниваем по "человечески" с учётом регистра | ||||
|         return strnatcmp($str1, $str2); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, пуста ли строка, содержит ли вместо текста только пробелы. | ||||
|      * | ||||
|      * @param string|null $str Проверяемая строка. | ||||
|      * | ||||
|      * @return bool Результат проверки. | ||||
|      */ | ||||
|     public static function IsNullOrWhitespace (string|null $str): bool | ||||
|     { | ||||
|         return self::IsNullOrEmpty($str) || trim($str) === ''; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, пуста ли строка. | ||||
|      * | ||||
|      * @param string|null $str Проверяемая строка. | ||||
|      * | ||||
|      * @return bool Результат проверки. | ||||
|      */ | ||||
|     public static function IsNullOrEmpty (string|null $str): bool | ||||
|     { | ||||
|         return is_null($str) || $str === ''; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Конвертация в латиницу. | ||||
|      * | ||||
|      * @param string $source Исходное слово или выражение | ||||
|      * | ||||
|      * @return string Транслитерированное слово или выражение | ||||
|      */ | ||||
|     public static function ConvertToLatin (string $source): string | ||||
|     { | ||||
|         // Создаю результат | ||||
|         $result = ""; | ||||
|  | ||||
|         // Длина исходного слова | ||||
|         $length = mb_strlen($source); | ||||
|  | ||||
|         // Для каждой буквы или символа из слова | ||||
|         for ($i = 0; $i < $length; $i++) { | ||||
|             // - получаю букву или символ | ||||
|             $letter = mb_substr($source, $i, 1); | ||||
|  | ||||
|             // - если это буква из русского алфавита | ||||
|             if (self::IsRussianLetter($letter)) { | ||||
|                 // -- транслитерирую эту букву | ||||
|                 $resultTransliteration = self::TransliterationFromRussian($letter); | ||||
|  | ||||
|                 // -- если транслитерация не удалась | ||||
|                 if ($resultTransliteration === false) | ||||
|                     // --- вывожу оригинальную букву | ||||
|                     $result = $result . $letter; | ||||
|                 else | ||||
|                     // --- вывожу транслитерированную букву | ||||
|                     $result = $result . $resultTransliteration; | ||||
|  | ||||
|                 // -- и иду к следующей букве или символу | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // - если до сих пор буква или символ не обработаны, то возвращаю их | ||||
|             $result = $result . $letter; | ||||
|         } | ||||
|  | ||||
|         // Вывожу результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, является ли буква русской. | ||||
|      * | ||||
|      * @param string $letter Буква | ||||
|      * | ||||
|      * @return bool Является ли буква русской | ||||
|      */ | ||||
|     private static function IsRussianLetter (string $letter): bool | ||||
|     { | ||||
|         return in_array($letter, self::$RussianLetters); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Получаю транслитерированную букву русского алфавита. | ||||
|      * | ||||
|      * @param string $letter Буква | ||||
|      * | ||||
|      * @return false|string Транслитерированная буква или false, если массивы не совпадают или буква не содержится | ||||
|      * в массивах. | ||||
|      */ | ||||
|     private static function TransliterationFromRussian (string $letter): false|string | ||||
|     { | ||||
|         // Если размерность массивов разная | ||||
|         if (count(self::$RussianLetters) !== count(self::$RussianLettersTransliteration)) | ||||
|             // - то вывожу ошибку | ||||
|             return false; | ||||
|  | ||||
|         // Получаю индекс буквы | ||||
|         $ind = array_search($letter, self::$RussianLetters, true); | ||||
|  | ||||
|         // Если буква не найдена | ||||
|         if ($ind === false) | ||||
|             // - то вывожу ошибку | ||||
|             return false; | ||||
|  | ||||
|         // Получаю транслитерированную букву | ||||
|         return self::$RussianLettersTransliteration[$ind]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Обрезает строку до указанных в параметре $maxLength символов | ||||
|      * | ||||
|      * @param string $text Исходный текст | ||||
|      * @param int $maxLength Максимальная длина текста | ||||
|      * @param string $endDots Суффикс, которым завершается обрезанная строка | ||||
|      * | ||||
|      * @return string Обрезанный текст | ||||
|      */ | ||||
|     public static function GetShortText (string $text, int $maxLength, string $endDots = ''): string | ||||
|     { | ||||
|         // Если длина текста меньше максимальной | ||||
|         if (mb_strlen($text) <= $maxLength) | ||||
|             // - то возвращаю исходный текст | ||||
|             return $text; | ||||
|  | ||||
|         // Если длина текста больше максимальной, то получаю длину текста без суффикса | ||||
|         $lengthWithoutEndDots = $maxLength - mb_strlen($endDots); | ||||
|  | ||||
|         // Возвращаю обрезанный текст | ||||
|         return mb_substr($text, 0, $lengthWithoutEndDots) . $endDots; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										30
									
								
								sources/interfaces/ISerializable.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								sources/interfaces/ISerializable.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\interfaces; | ||||
|  | ||||
| /** | ||||
|  * Интерфейс поддержки правильной сериализации объектов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| interface ISerializable | ||||
| { | ||||
|     /** | ||||
|      * Сериализация модели | ||||
|      * | ||||
|      * @return string Сериализованная модель | ||||
|      */ | ||||
|     public function Serialize (): string; | ||||
|  | ||||
|     /** | ||||
|      * Десериализует модель | ||||
|      * | ||||
|      * @param string $serialized Сериализованная модель | ||||
|      * | ||||
|      * @return void | ||||
|      */ | ||||
|     public function UnSerialize (string $serialized): void; | ||||
| } | ||||
							
								
								
									
										108
									
								
								sources/models/ActionStateMessageModel.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								sources/models/ActionStateMessageModel.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\models; | ||||
|  | ||||
| use Exception; | ||||
| use goodboyalex\php_components_pack\classes\ClassMapper; | ||||
| use goodboyalex\php_components_pack\enums\MessageType; | ||||
| use goodboyalex\php_components_pack\interfaces\ISerializable; | ||||
| use UnitEnum; | ||||
|  | ||||
| /** | ||||
|  * Класс сообщения состояния. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| final class ActionStateMessageModel implements ISerializable | ||||
| { | ||||
|     /** | ||||
|      * @var MessageType $MessageType Тип сообщения | ||||
|      */ | ||||
|     public MessageType $MessageType; | ||||
|  | ||||
|     /** | ||||
|      * @var bool $IsCritical Критичность сообщения | ||||
|      */ | ||||
|     public bool $IsCritical; | ||||
|  | ||||
|     /** | ||||
|      * @var string $Message Текст сообщения | ||||
|      */ | ||||
|     public string $Message; | ||||
|  | ||||
|     /** | ||||
|      * Конструктор | ||||
|      * | ||||
|      * @param MessageType $type Тип сообщения | ||||
|      * @param bool $isCritical Критичность сообщения | ||||
|      * @param string $message Текст сообщения | ||||
|      */ | ||||
|     public function __construct (MessageType $type = MessageType::Info, bool $isCritical = false, string $message = "") | ||||
|     { | ||||
|         $this->MessageType = $type; | ||||
|         $this->IsCritical = $isCritical; | ||||
|         $this->Message = $message; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function UnSerialize (string $serialized): void | ||||
|     { | ||||
|         // Десериализую массив | ||||
|         $thisNew = unserialize($serialized); | ||||
|  | ||||
|         try { | ||||
|             // Получаю класс | ||||
|             $class = ClassMapper::MapToClassProperty(get_class($this), $thisNew); | ||||
|         } | ||||
|         catch (Exception) { | ||||
|             $class = new ActionStateMessageModel(); | ||||
|         } | ||||
|  | ||||
|         // Заполняю текущий класс | ||||
|         ClassMapper::MapClass($class, $this); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function Serialize (): string | ||||
|     { | ||||
|         // Создаю массив результата | ||||
|         $result = []; | ||||
|  | ||||
|         // Получаю свойства класса | ||||
|         $properties = get_object_vars($this); | ||||
|  | ||||
|         // Для каждого свойства класса | ||||
|         foreach ($properties as $key => $value) { | ||||
|  | ||||
|             // - если значение является перечислением | ||||
|             if ($value instanceof UnitEnum) { | ||||
|                 // -- получаю перечисление | ||||
|                 $result[$key] = $value->name; | ||||
|  | ||||
|                 // -- следующий элемент | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // - если значение является NULL | ||||
|             if ($value == null) { | ||||
|                 // -- присваиваю NULL | ||||
|                 $result[$key] = "null"; | ||||
|                 // -- следующий элемент | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // - присваиваю значение | ||||
|             $result[$key] = $value; | ||||
|         } | ||||
|  | ||||
|         // Сериализую массив и вывожу его | ||||
|         return serialize($result); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										80
									
								
								sources/traits/EnumExtensionsTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								sources/traits/EnumExtensionsTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\traits; | ||||
|  | ||||
| use goodboyalex\php_components_pack\enums\MessageType; | ||||
| use InvalidArgumentException; | ||||
| use ReflectionEnum; | ||||
| use ReflectionException; | ||||
|  | ||||
| /** | ||||
|  * Расширение перечислений. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| trait EnumExtensionsTrait | ||||
| { | ||||
|     /** | ||||
|      * Получает значение перечисления по его имени. | ||||
|      * | ||||
|      * @param string $name Имя значения перечисления | ||||
|      * | ||||
|      * @return MessageType|EnumExtensionsTrait Перечисление | ||||
|      */ | ||||
|     public static function FromName (string $name): self | ||||
|     { | ||||
|         // Создаём экземпляр | ||||
|         $reflection = new ReflectionEnum(static::class); | ||||
|  | ||||
|         // Проверяем, есть ли такая переменная | ||||
|         if (!$reflection->hasCase($name)) | ||||
|             // - если нет - ошибка | ||||
|             throw new InvalidArgumentException(sprintf("Enumeration name '%s' does not exist!", $name)); | ||||
|  | ||||
|         try { | ||||
|             $result = $reflection->getCase($name)->getValue(); | ||||
|         } | ||||
|         catch (ReflectionException) { | ||||
|  | ||||
|             $result = new static(); | ||||
|         } | ||||
|  | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Получает значение перечисления | ||||
|      * | ||||
|      * @return string Значение перечисления | ||||
|      */ | ||||
|     public function GetValue (): string | ||||
|     { | ||||
|         return $this->name; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Конвертирует в перечисление из int. | ||||
|      * | ||||
|      * @param int $value Значение перечисления в формате int | ||||
|      * | ||||
|      * @return MessageType|EnumExtensionsTrait Объект | ||||
|      *     перечисления | ||||
|      */ | ||||
|     public static function FromInt (int $value): self | ||||
|     { | ||||
|         return self::tryFrom($value); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Переводит тип в INT | ||||
|      * | ||||
|      * @return int Значение типа в INT | ||||
|      */ | ||||
|     public function ToInt (): int | ||||
|     { | ||||
|         return $this->value; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										90
									
								
								sources/traits/ObjectArray/ObjectArrayBasicTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								sources/traits/ObjectArray/ObjectArrayBasicTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\traits\ObjectArray; | ||||
|  | ||||
| use ArrayIterator; | ||||
|  | ||||
| /** | ||||
|  * Часть кода класса ObjectArray, отвечающая за функции из наследуемых интерфейсов и классов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| trait ObjectArrayBasicTrait | ||||
| { | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function offsetExists (mixed $offset): bool | ||||
|     { | ||||
|         return isset($this->Container[$offset]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function offsetGet (mixed $offset): mixed | ||||
|     { | ||||
|         return $this->container[$offset] ?? null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function offsetSet (mixed $offset, mixed $value): void | ||||
|     { | ||||
|         // Если смещение не указано | ||||
|         if (is_null($offset)) | ||||
|             // - то добавляем объект в конец массива. | ||||
|             $this->Container[] = $value; | ||||
|         else | ||||
|             // - иначе добавляем объект по указанному смещению. | ||||
|             $this->Container[$offset] = $value; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function offsetUnset (mixed $offset): void | ||||
|     { | ||||
|         unset($this->Container[$offset]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function getIterator (): ArrayIterator | ||||
|     { | ||||
|         return new ArrayIterator($this->Container); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Существует ли элемент по указанному смещению. | ||||
|      * | ||||
|      * @param mixed $offset Смещение. | ||||
|      * | ||||
|      * @return bool Существует ли элемент по указанному смещению. | ||||
|      */ | ||||
|     public function __isset (mixed $offset): bool | ||||
|     { | ||||
|         return isset($this->data[$offset]); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function Serialize (): string | ||||
|     { | ||||
|         return serialize($this->Container); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @inheritDoc | ||||
|      */ | ||||
|     public function UnSerialize (string $serialized): void | ||||
|     { | ||||
|         $this->Container = unserialize($serialized); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										26
									
								
								sources/traits/ObjectArray/ObjectArrayConstantsTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								sources/traits/ObjectArray/ObjectArrayConstantsTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\traits\ObjectArray; | ||||
|  | ||||
| use Closure; | ||||
|  | ||||
| /** | ||||
|  * Часть кода класса ObjectArray, отвечающая за константы. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| trait ObjectArrayConstantsTrait | ||||
| { | ||||
|     /** | ||||
|      * @var Closure Функция сравнения объектов по умолчанию. | ||||
|      */ | ||||
|     public Closure $DefaultComparerFunction { | ||||
|         get { | ||||
|             return fn (mixed $currentPropertyValue, mixed $searchPropertyValue): bool | ||||
|                 => $currentPropertyValue === $searchPropertyValue; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										283
									
								
								sources/traits/ObjectArray/ObjectArrayLINQTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										283
									
								
								sources/traits/ObjectArray/ObjectArrayLINQTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,283 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\traits\ObjectArray; | ||||
|  | ||||
| use goodboyalex\php_components_pack\classes\ObjectArray; | ||||
|  | ||||
| /** | ||||
|  * Часть кода класса ObjectArray, отвечающая за LINQ-подобные операции. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| trait ObjectArrayLINQTrait | ||||
| { | ||||
|     /** | ||||
|      * Возвращает объект, значение свойства которого минимально. | ||||
|      * | ||||
|      * @param callable $itemValuePredicate Функция, возвращающая значение свойства объекта. | ||||
|      * Параметром является объект массива. | ||||
|      * | ||||
|      * @return mixed|null Объект, значение свойства которого минимально | ||||
|      */ | ||||
|     public function MinBy (callable $itemValuePredicate): mixed | ||||
|     { | ||||
|         return array_reduce($this->Container, | ||||
|             fn ($min, $item) => $min === null || $itemValuePredicate($item) < $itemValuePredicate($min) ? $item : $min); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Возвращает объект, значение свойства которого максимально. | ||||
|      * | ||||
|      * @param callable $itemValuePredicate Функция, возвращающая значение свойства объекта. | ||||
|      *  Параметром является объект массива. | ||||
|      * | ||||
|      * @return mixed|null Объект, значение свойства которого максимально. | ||||
|      */ | ||||
|     public function MaxBy (callable $itemValuePredicate): mixed | ||||
|     { | ||||
|         return array_reduce($this->Container, | ||||
|             fn ($max, $item) => $max === null || $itemValuePredicate($item) > $itemValuePredicate($max) ? $item : $max); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Выделяет из массива объектов объект, удовлетворяющий условию. Если объектов несколько, то выбирается первый | ||||
|      * встречающийся объект из них. Если объектов нет, вернёт false. | ||||
|      * | ||||
|      * @param callable|null $selectCondition Функция выборки объектов <code>fn (mixed $item): bool</code>. Вместо неё | ||||
|      *      можно использовать null, тогда функция выберет текущий объект. По умолчанию, null. | ||||
|      * | ||||
|      * @return false|mixed Выбранный объект, удовлетворяющий условию, или false, если таких нет. | ||||
|      */ | ||||
|     public function GetRow (?callable $selectCondition = null): mixed | ||||
|     { | ||||
|         // Если условие не задано | ||||
|         if ($selectCondition === null || !is_callable($selectCondition)) { | ||||
|             // - то если массив не пуст | ||||
|             if (count($this->Container) > 0) | ||||
|                 // -- возвращаем первый элемент | ||||
|                 return $this->Container[0]; | ||||
|             else | ||||
|                 // -- иначе возвращаем false | ||||
|                 return false; | ||||
|         } | ||||
|  | ||||
|         // Получаем результаты выборки из массива по условию $selectCondition | ||||
|         $result = $this->GetRows($selectCondition); | ||||
|  | ||||
|         // Если результат не найден | ||||
|         if (count($result) == 0) | ||||
|             // - возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return $result[0]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Выделяет из массива объектов объекты, удовлетворяющие условию. | ||||
|      * | ||||
|      * @param callable|null $selectCondition Функция выборки объектов <code>fn (mixed $item): bool</code>. Вместо неё | ||||
|      *     можно использовать null, тогда функция будет выбирать все объекты. По умолчанию, null. | ||||
|      * | ||||
|      * @return ObjectArray Массив объектов, удовлетворяющих условию | ||||
|      */ | ||||
|     public function GetRows (?callable $selectCondition = null): ObjectArray | ||||
|     { | ||||
|         // Если условие не задано | ||||
|         if ($selectCondition === null || !is_callable($selectCondition)) | ||||
|             // - то возвращаем все элементы | ||||
|             return new ObjectArray($this->Container); | ||||
|  | ||||
|         // Создаём результирующий массив | ||||
|         $result = []; | ||||
|  | ||||
|         // Проходим по массиву | ||||
|         foreach ($this->Container as $item) { | ||||
|             // - пропускаем не объекты | ||||
|             if (!is_object($item)) | ||||
|                 continue; | ||||
|  | ||||
|             // - если объект удовлетворяет условию | ||||
|             if ($selectCondition($item)) | ||||
|                 // -- добавляем его в результат | ||||
|                 $result[] = $item; | ||||
|         } | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return new ObjectArray($result); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Получение значение единичного поля. Если полей по выборке будет больше одного, то вернёт первое из них. | ||||
|      * | ||||
|      * @param string $column Требуемый столбец | ||||
|      * @param callable|null $wherePredicate Условие выборки <code>fn (mixed $item): bool</code>, которое проверяет, | ||||
|      *      подходит элемент или нет. | ||||
|      * | ||||
|      * @return mixed|null Результат запроса или null в случае ошибки | ||||
|      */ | ||||
|     public function GetValue (string $column, ?callable $wherePredicate = null): mixed | ||||
|     { | ||||
|         // Получаю колонку | ||||
|         $result = $this->GetColumn($column, $wherePredicate); | ||||
|  | ||||
|         // Если результат пуст | ||||
|         if (count($result) == 0) | ||||
|             // -- возвращаю null | ||||
|             return null; | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return $result[0]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Получает колонку в массиве данных. | ||||
|      * | ||||
|      * @param string $column Имя колонки. | ||||
|      * @param callable|null $wherePredicate Условие выборки <code>fn (mixed $item): bool</code>, которое проверяет, | ||||
|      *      подходит элемент или нет. | ||||
|      * | ||||
|      * @return array Ассоциированный массив с результатом выборки. | ||||
|      */ | ||||
|     public function GetColumn (string $column, ?callable $wherePredicate = null): array | ||||
|     { | ||||
|         // Создаю результат | ||||
|         $result = []; | ||||
|  | ||||
|         // Прохожу по массиву | ||||
|         foreach ($this->Container as $item) { | ||||
|             // - пропускаю не объекты | ||||
|             if (!is_object($item)) | ||||
|                 continue; | ||||
|  | ||||
|             // - пропускаю не имеющие требуемого свойства | ||||
|             if (!property_exists($item, $column)) | ||||
|                 continue; | ||||
|  | ||||
|             // - пропускаю не удовлетворяющие условию | ||||
|             if ($wherePredicate !== null && !$wherePredicate($item)) | ||||
|                 continue; | ||||
|  | ||||
|             // - добавляю значение свойства в результат | ||||
|             $result[] = $item->$column; | ||||
|         } | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Заменяет данные в строке\ массива. | ||||
|      * | ||||
|      * @param mixed $setItem Заменяемые элемент. | ||||
|      * @param callable $wherePredicate Условие выборки <code>fn (mixed $item): bool</code>, которое проверяет, | ||||
|      *      подходит элемент или нет. | ||||
|      * | ||||
|      * @return bool Результат выполнения | ||||
|      */ | ||||
|     public function Update (array $setItems, callable $wherePredicate): bool | ||||
|     { | ||||
|         // Удаляю элементы | ||||
|         $result = $this->Delete($wherePredicate); | ||||
|  | ||||
|         // Добавляю новые элементы | ||||
|         foreach ($setItems as $item) | ||||
|             $this->Container[] = $item; | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Удаляет строки по условию. | ||||
|      * | ||||
|      * @param callable|null $wherePredicate Условие выборки <code>fn (mixed $item): bool</code>, которое проверяет, | ||||
|      *     подходит элемент или нет. | ||||
|      * | ||||
|      * @return bool Результат выполнения. Будет true, если все строки, удовлетворяющие условию удалены успешно, | ||||
|      * иначе false. | ||||
|      */ | ||||
|     public function Delete (?callable $wherePredicate = null): bool | ||||
|     { | ||||
|         // Задаю результат | ||||
|         $result = true; | ||||
|  | ||||
|         // Получаю массив строк | ||||
|         $array = $this->GetRows($wherePredicate); | ||||
|  | ||||
|         // Каждый элемент в этих строках | ||||
|         foreach ($array as $item) { | ||||
|             // - получаю его индекс в основном массиве | ||||
|             $key = array_search($item, $this->Container); | ||||
|  | ||||
|             // - и если индекс найден | ||||
|             if ($key !== false) { | ||||
|                 // -- удаляю элемент из основного массива | ||||
|                 $resultArray = array_splice($this->Container, $key, 1); | ||||
|  | ||||
|                 // -- и если удаление прошло успешно, то будет true | ||||
|                 $result = $result && count($resultArray) > 0; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Возвращаю результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, существует ли объект в массиве. | ||||
|      * | ||||
|      * @param callable|null $where Условие выборки <code>fn (mixed $item): bool</code>, которое проверяет, подходит ли | ||||
|      *     объект или нет. Может принимать вместо замыкания null, тогда вернёт false. По умолчанию null. | ||||
|      * | ||||
|      * @return bool Результат проверки | ||||
|      */ | ||||
|     public function IsExist (?callable $where = null): bool | ||||
|     { | ||||
|         // Если условие не задано | ||||
|         if ($where === null || !is_callable($where)) | ||||
|             // - то возвращаем false | ||||
|             return false; | ||||
|  | ||||
|         // Вывожу результат | ||||
|         return $this->Count($where) > 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Считает количество объектов в массиве, удовлетворяющих условию. | ||||
|      * | ||||
|      * @param callable|null $predicate Функция, возвращающая bool: true, если объект удовлетворяет условию, false, если | ||||
|      *     не удовлетворяет. Параметром является объект массива. Вместо функции можно передать null, тогда результатом | ||||
|      *     будет общее количество объектов в массиве. По умолчанию, null. | ||||
|      * | ||||
|      * @return int Количество объектов, удовлетворяющих условию | ||||
|      */ | ||||
|     public function Count (?callable $predicate = null): int | ||||
|     { | ||||
|         // Если условие не задано | ||||
|         if ($predicate === null || !is_callable($predicate)) | ||||
|             // - то возвращаем общее количество объектов | ||||
|             return count($this->Container); | ||||
|  | ||||
|         // Создаём результирующее число | ||||
|         $result = 0; | ||||
|  | ||||
|         // Проходим по массиву | ||||
|         foreach ($this->Container as $item) { | ||||
|             // - пропускаем не объекты | ||||
|             if (!is_object($item)) | ||||
|                 continue; | ||||
|  | ||||
|             // - если элемент удовлетворяет условию | ||||
|             if ($predicate($item)) | ||||
|                 // -- добавляем счётчик | ||||
|                 $result++; | ||||
|         } | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return $result; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										129
									
								
								sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										129
									
								
								sources/traits/ObjectArray/ObjectArraySearchAndSortTrait.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,129 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\traits\ObjectArray; | ||||
|  | ||||
| /** | ||||
|  * Часть кода класса ObjectArray, отвечающая за поиск и исключение объектов. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0 | ||||
|  */ | ||||
| trait ObjectArraySearchAndSortTrait | ||||
| { | ||||
|     /** | ||||
|      * Сортирует массив объектов, по пользовательской функции. | ||||
|      * | ||||
|      * @param callable $objectPropertyValuePredicate Функция <code>fn (mixed $item): mixed => $item-><PROPERTY></code>, | ||||
|      *     возвращающая сравниваемый объект. Возвращаемое значение должно быть значением свойства этого объекта. | ||||
|      * | ||||
|      * <code> | ||||
|      *     class Demo; | ||||
|      *     { | ||||
|      *          public string $Property1; | ||||
|      *          public string $Property2; | ||||
|      *          public function __construct(string $Property1, string $Property2) | ||||
|      *          { | ||||
|      *              $this->Property1 = $Property1; | ||||
|      *              $this->Property2 = $Property2; | ||||
|      *          } | ||||
|      *      } | ||||
|      *      $array = new ObjectArray ( | ||||
|      *        [ | ||||
|      *          new Demo('1', '2'), | ||||
|      *          new Demo('5', '6'), | ||||
|      *          new Demo('3', '4') | ||||
|      *        ]); | ||||
|      * | ||||
|      *      // output: | ||||
|      *      // [Demo('1', '2'), Demo('3', '4'), Demo('5', '6')] | ||||
|      *      $result = $array->SortCallback($array, fn ($item): mixed => $item->Property1); | ||||
|      * </code> | ||||
|      * @param bool $descending Направление сортировки | ||||
|      * | ||||
|      * @return array Отсортированный массив объектов | ||||
|      */ | ||||
|     public function SortCallback (callable $objectPropertyValuePredicate, bool $descending = false): array | ||||
|     { | ||||
|         // Создаём результирующий массив | ||||
|         $result = array_merge($this->Container, []); | ||||
|  | ||||
|         // Сортируем массив | ||||
|         usort($result, | ||||
|             fn ($a, $b) | ||||
|                 => !$descending | ||||
|                 ? $objectPropertyValuePredicate($a) <=> $objectPropertyValuePredicate($b) | ||||
|                 : $objectPropertyValuePredicate($b) <=> $objectPropertyValuePredicate($a)); | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Сортирует массив объектов, по значению свойства объекта. | ||||
|      * | ||||
|      * @param string $objectProperty Имя свойства объекта | ||||
|      * @param bool $descending Направление сортировки | ||||
|      * | ||||
|      * @return array Отсортированный массив объектов | ||||
|      */ | ||||
|     public function Sort (string $objectProperty, bool $descending = false): array | ||||
|     { | ||||
|         // Создаём результирующий массив | ||||
|         $result = array_merge($this->Container, []); | ||||
|  | ||||
|         // Сортируем массив | ||||
|         usort($result, | ||||
|             fn ($a, $b) | ||||
|                 => !$descending | ||||
|                 ? $a->$objectProperty <=> $b->$objectProperty | ||||
|                 : $b->$objectProperty <=> $a->$objectProperty); | ||||
|  | ||||
|         // Возвращаем результат | ||||
|         return $result; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Поиск объекта в массиве объектов по значению свойства объекта. | ||||
|      * | ||||
|      * @param string $forProperty Имя искомого свойства объекта. | ||||
|      * @param mixed $searchValue Искомое значение свойства объекта. | ||||
|      * @param callable|null $compareFunction Функция сравнения, принимающая два параметра: mixed $currentPropertyValue | ||||
|      *     (текущее значение свойства) и mixed $searchPropertyValue (поисковое значение свойства) и возвращает bool - | ||||
|      *     true, если значение свойства совпадает с искомым, false - если не совпадает. Если передаётся null, то будет | ||||
|      *     использоваться DefaultComparerFunction. По умолчанию, null. | ||||
|      * | ||||
|      * @return mixed Объект, найденный по значению свойства или null, если не найден | ||||
|      */ | ||||
|     public function Search (string $forProperty, mixed $searchValue, ?callable $compareFunction = null): mixed | ||||
|     { | ||||
|         // Проходим по массиву | ||||
|         foreach ($this->Container as $item) { | ||||
|             // - пропускаем не объекты | ||||
|             if (!is_object($item)) | ||||
|                 continue; | ||||
|  | ||||
|             // - пропускаем, если значение свойства нет в этом объекте | ||||
|             if (!property_exists($item, $forProperty)) | ||||
|                 continue; | ||||
|  | ||||
|             // - пропускаем, если значение свойства не задано | ||||
|             if (!isset($item->$forProperty)) | ||||
|                 continue; | ||||
|  | ||||
|             // - если не задана функция сравнения | ||||
|             if (is_null($compareFunction) || !is_callable($compareFunction)) | ||||
|                 // -- то устанавливаем функцию сравнения по умолчанию | ||||
|                 $compareFunction = $this->DefaultComparerFunction; | ||||
|  | ||||
|             // - если значение свойства совпадает с искомым | ||||
|             if ($compareFunction($item->$forProperty, $searchValue)) | ||||
|                 // -- возвращаем объект | ||||
|                 return $item; | ||||
|         } | ||||
|  | ||||
|         // Если мы сюда дошли, значить объект не найден - возвращаем null | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user