20250612
* Добавлено перечисление стадий в информации о версии VersionInfoStage. * Добавлен новый класс, описывающий информацию о версии, VersionInfo (подробнее см. VersionInfo.md).
This commit is contained in:
		
							
								
								
									
										295
									
								
								sources/classes/VersionInfo.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										295
									
								
								sources/classes/VersionInfo.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,295 @@ | ||||
| <?php | ||||
|  | ||||
| namespace goodboyalex\php_components_pack\classes; | ||||
|  | ||||
| use goodboyalex\php_components_pack\enums\VersionInfoStage; | ||||
| use goodboyalex\php_components_pack\extensions\StringExtension; | ||||
|  | ||||
| /** | ||||
|  * Класс, описывающий информацию о версии. | ||||
|  * | ||||
|  * @author Александр Бабаев | ||||
|  * @package php_components_pack | ||||
|  * @version 1.0 | ||||
|  * @since 1.0.24 | ||||
|  */ | ||||
| final class VersionInfo | ||||
| { | ||||
|     /** | ||||
|      * @var array $StagesNames Имена стадий сборки. | ||||
|      */ | ||||
|     public const array StagesNames = [ | ||||
|         VersionInfoStage::PreAlpha->value => 'PreAlpha', | ||||
|         VersionInfoStage::Alpha->value => 'Alpha', | ||||
|         VersionInfoStage::Beta->value => 'Beta', | ||||
|         VersionInfoStage::ReleaseCandidate->value => 'rc', | ||||
|         VersionInfoStage::Stable->value => 'Stable' | ||||
|     ]; | ||||
|  | ||||
|     /** | ||||
|      * @var string $DefaultTemplate Шаблон вывода по умолчанию. | ||||
|      */ | ||||
|     public const string DefaultTemplate = '#{Major}.#{Minor}.#{Release}.#{Build} #{Stage} #{StageNumber}'; | ||||
|  | ||||
|     /** | ||||
|      * @var int $Major Мажорная версия. | ||||
|      */ | ||||
|     private(set) int $Major = 0; | ||||
|  | ||||
|     /** | ||||
|      * @var int $Minor Минорная версия. | ||||
|      */ | ||||
|     private(set) int $Minor = 0; | ||||
|  | ||||
|     /** | ||||
|      * @var int $Release Номер релиза. | ||||
|      */ | ||||
|     private(set) int $Release = 0; | ||||
|  | ||||
|     /** | ||||
|      * @var int $Build Номер сборки. | ||||
|      */ | ||||
|     private(set) int $Build = 0; | ||||
|  | ||||
|     /** | ||||
|      * @var VersionInfoStage $Stage Стадия сборки. | ||||
|      */ | ||||
|     private(set) VersionInfoStage $Stage = VersionInfoStage::Undefined; | ||||
|  | ||||
|     /** | ||||
|      * @var int $StageNumber Номер стадии сборки. | ||||
|      */ | ||||
|     private(set) int $StageNumber = 0; | ||||
|  | ||||
|     /** | ||||
|      * Конструктор. | ||||
|      * | ||||
|      * @param int $Major Мажорная версия. | ||||
|      * @param int $Minor Минорная версия. | ||||
|      * @param int $Release Номер релиза. | ||||
|      * @param int $Build Номер сборки. | ||||
|      * @param VersionInfoStage $Stage Стадия сборки. | ||||
|      * @param int $StageNumber Номер стадии сборки. | ||||
|      */ | ||||
|     public function __construct (int $Major, int $Minor, int $Release, int $Build, | ||||
|         VersionInfoStage $Stage = VersionInfoStage::Undefined, int $StageNumber = 0) | ||||
|     { | ||||
|         $this->Major = $Major; | ||||
|         $this->Minor = $Minor; | ||||
|         $this->Release = $Release; | ||||
|         $this->Build = $Build; | ||||
|         $this->Stage = $Stage; | ||||
|         $this->StageNumber = $StageNumber; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Сравнивает две версии. | ||||
|      * | ||||
|      * @param VersionInfo $version1 Версия 1. | ||||
|      * @param VersionInfo $version2 Версия 2. | ||||
|      * | ||||
|      * @return int Возвращает 1, если версия 1 больше версии 2, 0, если равны, -1, если версия 1 меньше версии 2. | ||||
|      */ | ||||
|     public static function Compare (VersionInfo $version1, VersionInfo $version2): int | ||||
|     { | ||||
|         return $version1->CompareWith($version2); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Сравнивает текущую версию с переданной. | ||||
|      * | ||||
|      * @param VersionInfo $version Переданная версия. | ||||
|      * | ||||
|      * @return int Возвращает 1, если текущая версия больше переданной, 0, если равны, -1, если текущая версия меньше | ||||
|      *     переданной. | ||||
|      */ | ||||
|     public function CompareWith (VersionInfo $version): int | ||||
|     { | ||||
|         // Задаем шаблон вывода | ||||
|         $toStringTemplate = '#{Major}.#{Minor}.#{Release}.#{Build}'; | ||||
|  | ||||
|         // Сначала сравним числа (мажорную, минорную версии, номер релиза и сборки): | ||||
|         $compareResult = version_compare( | ||||
|             $this->ToString($toStringTemplate), | ||||
|             $version->ToString($toStringTemplate) | ||||
|         ); | ||||
|  | ||||
|         // Если численные части совпадают, проверяем стадии сборки | ||||
|         if ($compareResult === 0) { | ||||
|             // - особый случай: стабильная версия всегда больше любых промежуточных стадий | ||||
|             if ($this->Stage === VersionInfoStage::Stable && self::IsNotUndefinedOrStable($version->Stage)) | ||||
|                 // - считаем нашу старшей | ||||
|                 return 1; | ||||
|  | ||||
|             // - особый случай: если наша версия не stable, а другая stable | ||||
|             if ($version->Stage === VersionInfoStage::Stable && self::IsNotUndefinedOrStable($this->Stage)) | ||||
|                 // - считаем нашу младшей | ||||
|                 return -1; | ||||
|  | ||||
|             // - преобразуем стадии в целые числа для прямого сравнения | ||||
|             $currentStageValue = $this->Stage->ToInt(); | ||||
|             $otherStageValue = $version->Stage->ToInt(); | ||||
|  | ||||
|             // - если стадии отличаются | ||||
|             if ($currentStageValue !== $otherStageValue) | ||||
|                 // - сравниваем их | ||||
|                 return $currentStageValue <=> $otherStageValue; | ||||
|  | ||||
|             // - если стадии одинаковые | ||||
|             if (self::IsNotUndefinedOrStable($this->Stage) && self::IsNotUndefinedOrStable($version->Stage) | ||||
|                 && $this->StageNumber !== $version->StageNumber) | ||||
|                 return $this->StageNumber <=> $version->StageNumber; | ||||
|  | ||||
|             // - если все совпадает, то вернём 0 | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         // Возврат результата сравнения | ||||
|         return $compareResult; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Возвращает строковое представление версии. | ||||
|      * | ||||
|      * @param string $template Шаблон вывода. В шаблоне маркеры #{Major}, #{Minor}, #{Release}, #{Build}, #{Stage} и | ||||
|      *     #{StageNumber} заменяются на значения соответствующих свойств. По умолчанию используется | ||||
|      *     {@link DefaultTemplate}. | ||||
|      * @param array $stagesNames Имена стадий сборки (по умолчанию из константы {@link StagesNames}). | ||||
|      * | ||||
|      * @return string Строковое представление версии. | ||||
|      */ | ||||
|     public function ToString (string $template = self::DefaultTemplate, array $stagesNames = self::StagesNames): string | ||||
|     { | ||||
|         // Получаем строковое представление стадии сборки | ||||
|         $stage = match ($this->Stage) { | ||||
|             // - для неопределенной стадии сборки и релиза возвращаем пустую строку | ||||
|             VersionInfoStage::Undefined, VersionInfoStage::Stable => '', | ||||
|  | ||||
|             // - для остальных стадий сборки возвращаем строковое представление стадии сборки | ||||
|             VersionInfoStage::PreAlpha => $stagesNames[VersionInfoStage::PreAlpha->value], | ||||
|             VersionInfoStage::Alpha => $stagesNames[VersionInfoStage::Alpha->value], | ||||
|             VersionInfoStage::Beta => $stagesNames[VersionInfoStage::Beta->value], | ||||
|             VersionInfoStage::ReleaseCandidate => $stagesNames[VersionInfoStage::ReleaseCandidate->value] | ||||
|         }; | ||||
|  | ||||
|         // Возвращаем строковое представление номера стадии сборки, если конечно стадия определена и она не релиз | ||||
|         // и номер сборки должен быть задан (больше 0) | ||||
|         $stageNum = self::IsNotUndefinedOrStable($this->Stage) && $this->StageNumber > 0 | ||||
|             ? "$this->StageNumber" : ''; | ||||
|  | ||||
|         // Создаём массив для замены | ||||
|         $replaceData = [ | ||||
|             '#{Major}' => "$this->Major", | ||||
|             '#{Minor}' => "$this->Minor", | ||||
|             '#{Release}' => "$this->Release", | ||||
|             '#{Build}' => "$this->Build", | ||||
|             '#{Stage}' => $stage, | ||||
|             '#{StageNumber}' => $stageNum | ||||
|         ]; | ||||
|  | ||||
|         // Заменяем все в шаблоне | ||||
|         $result = StringExtension::ReplaceAll($replaceData, $template); | ||||
|  | ||||
|         // Возвращаем результат, удаляя лишние пробелы в конце | ||||
|         return rtrim($result, ' '); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Проверяет, является ли версия неопределённой или релизом. | ||||
|      * | ||||
|      * @param VersionInfoStage $versionStage Стадия сборки. | ||||
|      * | ||||
|      * @return bool Возвращает true, если стадия сборки определена и не является релизом. | ||||
|      */ | ||||
|     public static function IsNotUndefinedOrStable (VersionInfoStage $versionStage): bool | ||||
|     { | ||||
|         return $versionStage !== VersionInfoStage::Undefined && $versionStage !== VersionInfoStage::Stable; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Преобразует строку с версией в объект {@link VersionInfo}. | ||||
|      * | ||||
|      * @param string $version Строка с версией (она должна быть в формате {@link DefaultTemplate}). | ||||
|      * @param array $stagesNames Имена стадий сборки (по умолчанию из константы {@link StagesNames}). | ||||
|      * | ||||
|      * @return VersionInfo Возвращает объект {@link VersionInfo} с данными о версии. | ||||
|      */ | ||||
|     public static function Parse (string $version, array $stagesNames = self::StagesNames): VersionInfo | ||||
|     { | ||||
|         // Убираем пробелы в начале и конце строки | ||||
|         $version = trim($version); | ||||
|  | ||||
|         // Разбиваем строку на части по пробелам (1 часть - основная - мажор, минор, релиз, сборка, | ||||
|         // 2 часть - стадия и 3 - номер стадии) | ||||
|         $versionParts = explode(' ', $version); | ||||
|  | ||||
|         // Проверяем, что строка содержит хотя бы 1 часть | ||||
|         if (count($versionParts) < 1) | ||||
|             // - если нет, то возвращаем пустую версию | ||||
|             return new  VersionInfo(0, 0, 0, 0); | ||||
|  | ||||
|         // Составим регулярное выражение для парсинга базовой информации о версии | ||||
|         $pattern = '/^(\d+)\.(\d+)\.(\d+)\.(\d+)/'; | ||||
|  | ||||
|         // Парсим базовую информацию о версии | ||||
|         if (!preg_match($pattern, $versionParts[0], $matches)) | ||||
|             // - если не удалось, то возвращаем пустую версию | ||||
|             return new  VersionInfo(0, 0, 0, 0); | ||||
|  | ||||
|         // Проверяем, что найдены все 4 части | ||||
|         if (!$matches || count($matches) < 5) | ||||
|             // - если нет, то возвращаем пустую версию | ||||
|             return new VersionInfo(0, 0, 0, 0); | ||||
|  | ||||
|         // Получаем значения | ||||
|         [, $major, $minor, $release, $build] = $matches; | ||||
|  | ||||
|         // Парсим обязательные цифры | ||||
|         // - мажорная версия | ||||
|         $major = intval($major); | ||||
|         // - минорная версия | ||||
|         $minor = intval($minor); | ||||
|         // - номер релиза | ||||
|         $release = intval($release); | ||||
|         // - номер сборки | ||||
|         $build = intval($build); | ||||
|  | ||||
|         // Если частей версии больше 1 | ||||
|         if (count($versionParts) > 1) { | ||||
|             // - получаем массив для перевода строковых имен стадий в числа | ||||
|             $stageEnumMap = array_flip($stagesNames); | ||||
|  | ||||
|             // - получаем стадию | ||||
|             $stage = VersionInfoStage::FromInt(intval($stageEnumMap[$versionParts[1]] ?? 0)); | ||||
|  | ||||
|             // - если стадия определена и не релиз, и кроме того, есть номер стадии | ||||
|             if (self::IsNotUndefinedOrStable($stage) && count($versionParts) > 2) | ||||
|                 // -- получаем номер стадии | ||||
|                 $stageNumber = intval($versionParts[2]); | ||||
|             else | ||||
|                 // -- иначе, устанавливаем номер стадии 0 | ||||
|                 $stageNumber = 0; | ||||
|         } | ||||
|         else { | ||||
|             // - иначе, устанавливаем стадию неопределённой | ||||
|             $stage = VersionInfoStage::Undefined; | ||||
|             // - и номер стадии 0 | ||||
|             $stageNumber = 0; | ||||
|         } | ||||
|  | ||||
|         // Создание объекта VersionInfo | ||||
|         return new VersionInfo($major, $minor, $release, $build, $stage, $stageNumber); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Выводит строковое представление версии (упрощённая версия ToString() с шаблоном по умолчанию, необходимая для | ||||
|      * вывода при попытке привести объект к типу string). | ||||
|      * | ||||
|      * @return string Строковое представление версии. | ||||
|      */ | ||||
|     public function __toString (): string | ||||
|     { | ||||
|         // Получаем строковое представление версии и возвращаем его | ||||
|         return $this->ToString(); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user