From b6f9698e59b9758d8ea74e881fa76f89792eb2df Mon Sep 17 00:00:00 2001 From: babaev-an Date: Fri, 14 Feb 2025 16:41:50 +0300 Subject: [PATCH] 20250214 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit + [TwoDimSize]: Класс, описывающий двумерный размер. + [HashGetType]: Перечисление типов получения хэша. + [FileHash]: Класс для работы с хэшем файла или строки. --- sources/classes/FileHash.php | 79 +++++++++++++ sources/classes/TwoDimSize.php | 183 +++++++++++++++++++++++++++++++ sources/enums/HashGetType.php | 29 +++++ tests/classes/FileHashTest.php | 42 +++++++ tests/classes/TwoDimSizeTest.php | 66 +++++++++++ 5 files changed, 399 insertions(+) create mode 100644 sources/classes/FileHash.php create mode 100644 sources/classes/TwoDimSize.php create mode 100644 sources/enums/HashGetType.php create mode 100644 tests/classes/FileHashTest.php create mode 100644 tests/classes/TwoDimSizeTest.php diff --git a/sources/classes/FileHash.php b/sources/classes/FileHash.php new file mode 100644 index 0000000..51aa549 --- /dev/null +++ b/sources/classes/FileHash.php @@ -0,0 +1,79 @@ +HashBy = $HashBy; + $this->Hash = match ($HashBy) { + HashGetType::ByString => $this->pGetHash($str), + HashGetType::ByFile => $this->pGetFileHash($str) + }; + } + + /** + * Получение хэша файла по строке. + * + * @param string $str Строка. + * + * @return string Хэш строки. + */ + private function pGetHash (string $str): string + { + return hash('sha256', $str); + } + + /** + * Получение хэша файла по имени файла. + * + * @param string $fileName Имя файла. + * + * @return string Хэш файла. + */ + private function pGetFileHash (string $fileName): string + { + return hash_file('sha256', $fileName); + } + + /** + * Сравнивает текущий хэш с хэшем otherHash и выдаёт true, если совпадают, и + * false, если не совпадают. + * + * @param FileHash $otherHash Другой хэш. + * + * @return bool true, если совпадают, и false, если не совпадают. + */ + public function IsEqual (FileHash $otherHash): bool + { + return StringExtension::Compare($this->Hash, $otherHash->Hash, true) === 0; + } +} \ No newline at end of file diff --git a/sources/classes/TwoDimSize.php b/sources/classes/TwoDimSize.php new file mode 100644 index 0000000..a52f2de --- /dev/null +++ b/sources/classes/TwoDimSize.php @@ -0,0 +1,183 @@ +pWidth; + } + set { + $this->pWidth = $this->NoNegativeValues ? max($value, 0) : $value; + } + + } + + /** + * @var int $Height Ширина (публичная) + */ + public int $Height { + get { + return $this->pHeight; + } + set { + $this->pHeight = $this->NoNegativeValues ? max($value, 0) : $value; + } + + } + + /** + * @var int $pWidth Длина (приватное) + */ + private int $pWidth = 0; + + /** + * @var int $pHeight Ширина (приватное) + */ + private int $pHeight = 0; + + /** + * Конструктор. + * + * @param int $width Длина. + * @param int $height Ширина. + * @param bool $noNegativeValues Значения не должны быть отрицательными. + */ + public function __construct (int $width = 0, int $height = 0, bool $noNegativeValues = true) + { + $this->Width = $width; + $this->Height = $height; + $this->NoNegativeValues = $noNegativeValues; + } + + /** + * Конвертация в строку (магический метод). + * + * @return string Строка. + */ + public function __toString (): string + { + return $this->AsString(); + } + + /** + * Конвертация в строку (расширенный метод). + * + * @param string $delimiter Делитель размера. + * + * @return string Строка. + */ + public function AsString (string $delimiter = self::DEFAULT_DELIMITER): string + { + return $this->Width . $delimiter . $this->Height; + } + + /** + * @inheritDoc + */ + public function Serialize (): string + { + // Получаю строковое значение + $str = $this->AsString("x"); + + // Добавляю допустимы ли отрицательные значения + $str .= $this->NoNegativeValues ? "x1" : "x0"; + + // Возвращаю строку + return $str; + } + + /** + * @inheritDoc + */ + public function UnSerialize (string $serialized): void + { + // Десериализую строку + $result = explode("x", $serialized); + + // Присваиваю параметры + $this->NoNegativeValues = $result[2] === "1"; + + // Объединяю длину и ширину + $tdSize = $result[0] . self::DEFAULT_DELIMITER . $result[1]; + + // Пытаюсь получить размер + try { + $result = self::Parse($tdSize, noNegativeValues: $this->NoNegativeValues); + } + catch (Exception $e) { + $result = new TwoDimSize(noNegativeValues: $this->NoNegativeValues); + } + + // Присваиваю длину + $this->Width = $result->Width; + + // Присваиваю ширину + $this->Height = $result->Height; + } + + /** + * Получение размера из строки. + * + * @param string $str Строка. + * @param string $delimiter Разделитель размеров. + * @param bool $noNegativeValues Значения не должны быть отрицательными. + * + * @return TwoDimSize Модель размеров. + * @throws Exception Если в строке str не содержится символа delimiter или таких + * разделителей слишком много. + */ + public static function Parse (string $str, string $delimiter = self::DEFAULT_DELIMITER, + bool $noNegativeValues = true): TwoDimSize + { + // Разделяю значения + $splitSizes = explode($delimiter, $str); + + // Проверяю, что массив имеет ровно два элемента + if (count($splitSizes) != 2) + throw new Exception(sprintf("Похоже, что в строке %s не содержится символа «%s» или таких разделителей слишком много!", + $str, $delimiter)); + + // Пытаюсь получить длину + $width = filter_var($splitSizes[0], FILTER_VALIDATE_INT); + + // Если не удалось получить длину + if ($width === false) + $width = 0; + + // Пытаюсь получить ширину + $height = filter_var($splitSizes[1], FILTER_VALIDATE_INT); + + // Если не удалось получить ширину + if ($height === false) + $height = 0; + + // Вывожу значение + return new TwoDimSize($width, $height, $noNegativeValues); + } +} \ No newline at end of file diff --git a/sources/enums/HashGetType.php b/sources/enums/HashGetType.php new file mode 100644 index 0000000..8d1fbaa --- /dev/null +++ b/sources/enums/HashGetType.php @@ -0,0 +1,29 @@ +PrepareForTest(); + + $fileHash = new FileHash("Тестовое слово"); + $this->assertEquals("000e22f7ba01ae35f781bc3069038110c46593306cafef6b489f7c83b34629b7", $fileHash->Hash); + + $fileHash = new FileHash(__DIR__ . '/../data/A.php', HashGetType::ByFile); + $this->assertEquals("fc8dad93af5de5dd7c7d64e04faadfa22557e577a1538737fe462a5f78699fa2", $fileHash->Hash); + + $fileHash = new FileHash(__DIR__ . '/../data/B.php', HashGetType::ByFile); + $this->assertEquals("f419262e46e9461517af46d0c1e4faf25f38990bb50351b691d84f1ad51f2299", $fileHash->Hash); + } + + private function PrepareForTest (): void + { + require_once __DIR__ . '/../../sources/traits/EnumExtensionsTrait.php'; + require_once __DIR__ . '/../../sources/enums/HashGetType.php'; + require_once __DIR__ . '/../../sources/extensions/StringExtension.php'; + require_once __DIR__ . '/../../sources/classes/FileHash.php'; + } + + public function testIsEqual () + { + $this->PrepareForTest(); + + $fileHash = new FileHash("Тестовое слово"); + + $this->assertTrue($fileHash->IsEqual(new FileHash("Тестовое слово"))); + $this->assertFalse($fileHash->IsEqual(new FileHash("Тестовое слово2"))); + } +} \ No newline at end of file diff --git a/tests/classes/TwoDimSizeTest.php b/tests/classes/TwoDimSizeTest.php new file mode 100644 index 0000000..df7acf0 --- /dev/null +++ b/tests/classes/TwoDimSizeTest.php @@ -0,0 +1,66 @@ +PrepareForTest(); + + try { + $size = TwoDimSize::Parse("10x20", "x"); + } + catch (Exception $e) { + $this->fail($e->getMessage()); + } + + $this->assertEquals(10, $size->Width); + $this->assertEquals(20, $size->Height); + + } + + private function PrepareForTest (): void + { + require_once __DIR__ . '/../../sources/interfaces/ISerializable.php'; + require_once __DIR__ . '/../../sources/classes/TwoDimSize.php'; + } + + public function test__toString () + { + $this->PrepareForTest(); + + $size = new TwoDimSize(10, 20); + + $this->assertEquals("10:20", $size->__toString()); + } + + public function testSerialize () + { + $this->PrepareForTest(); + + $size = new TwoDimSize(10, 20); + + $this->assertEquals("10x20x1", $size->Serialize()); + + } + + public function testUnSerialize () + { + $this->PrepareForTest(); + + $serialized = "10x20x1"; + + $size = new TwoDimSize(); + + $size->UnSerialize($serialized); + + $this->assertEquals(10, $size->Width); + $this->assertEquals(20, $size->Height); + $this->assertTrue($size->NoNegativeValues); + } +} \ No newline at end of file