diff --git a/src/Classes/App.php b/src/Classes/App.php index 74db9f49..14117969 100644 --- a/src/Classes/App.php +++ b/src/Classes/App.php @@ -63,11 +63,17 @@ public static function getConfigRoot(): string return self::getRoot() . '/' . self::$configDir; } + /** + * /Archives/ + */ public static function getArchivesRoot(): string { return self::getRoot() . '/' . self::$archivesDir; } + /** + * /Modules/ + */ public static function getModulesRoot(): string { return self::getRoot() . '/' . self::getModulesDirName(); diff --git a/src/Classes/Archive/Archive.php b/src/Classes/Archive/Archive.php new file mode 100644 index 00000000..0a034bf1 --- /dev/null +++ b/src/Classes/Archive/Archive.php @@ -0,0 +1,83 @@ +parse($version); + + return new Archive($archiveNameObj, $versionObj, $archivesRootPath); + } + + public function __construct( + ArchiveName $archiveName, + Version $version, + string $archivesRootPath + ) { + if (empty($archivesRootPath)) { + throw new \InvalidArgumentException('archivesRootPath cannot be empty.'); + } + + $this->archiveName = $archiveName; + $this->archivesRootPath = $archivesRootPath; + $this->version = $version; + } + + public function getArchiveName(): ArchiveName + { + return $this->archiveName; + } + + public function getVersion(): Version + { + return $this->version; + } + + /** + * Liefert den Root Path zum Archive Ordner + * z. B. /.../ModifiedModuleLoaderClient/Archives/ + */ + public function getArchivesRootPath(): string + { + return $this->archivesRootPath; + } + + /** + * Liefert den Dateinamen der .tar Datei + * z. B. robinthehood_modified-std-module_0.1.0.tar + */ + public function getFileName(): string + { + return + str_replace('/', '_', $this->getArchiveName()->__toString()) + . '_' + . $this->getVersion() + . '.tar'; + } + + /** + * Liefert den gesamten Path der .tar Datei. + * z. B. /.../ModifiedModuleLoaderClient/Archives/robinthehood_modified-std-module_0.1.0.tar + */ + public function getFilePath(): string + { + return $this->getArchivesRootPath() . '/' . $this->getFileName(); + } +} diff --git a/src/Classes/Archive/ArchiveHandler.php b/src/Classes/Archive/ArchiveHandler.php new file mode 100644 index 00000000..81f8721a --- /dev/null +++ b/src/Classes/Archive/ArchiveHandler.php @@ -0,0 +1,151 @@ +localModuleLoader = $localModuleLoader; + $this->modulesRootPath = $modulesRootPath; + } + + /** + * Packt ein Archive zu einer .tar Datei. + * + * Dabei ist in der .tar Datei die Verzeichnis-Struktur // enthalten + * + * @throws \RuntimeException if an error occurs + */ + public function pack(Archive $archive): void + { + $module = $this->localModuleLoader->loadByArchiveNameAndVersion( + (string) $archive->getArchiveName(), + (string) $archive->getVersion() + ); + + if (!$module) { + throw new \RuntimeException("Failed to load module for archive: " . $archive->getArchiveName()); + } + + $this->createDirIfNotExists($archive->getArchivesRootPath()); + $this->deleteFileIfExists($archive->getFilePath()); + + $filePaths = FileHelper::scanDirRecursive( + $this->getModulePathFromModule($module), + FileHelper::FILES_ONLY + ); + + set_time_limit(60 * 10); + $tarArchive = new \PharData($archive->getFilePath()); + foreach ($filePaths as $filePath) { + if (file_exists($filePath)) { + $tarPath = FileHelper::stripBasePath($this->modulesRootPath, $filePath); + $tarArchive->addFile($filePath, $tarPath); + } + } + } + + /** + * Entpack ein $archive. + * + * Dabei wird das Archive in Modules entpackt. Im .tar archive selbst liegen die Dateien in der Ordner-Strucktur + * /// vor. + * + * @param Archive $archive + * @param bool $external Wenn eine .tar Datei z. B. von Github kommt, ist die Ordner-Strucktur in der .tar Datei + * nicht kompatible. Im der .tar Datei fehlt das Verzeichnis ///. Es ist nur + * das Verzeichnis vorhandnen. In diesem Fall muss das Verzeichnis /// + * angelegt werden. + * + * @throws \RuntimeException if an error occurs + */ + public function extract(Archive $archive, bool $external = false): void + { + $modulePath = $this->getModulePathFromArchive($archive); + if (file_exists($modulePath)) { + throw new \RuntimeException("Module already exists for archive: " . $archive->getArchiveName()); + } + + $this->createDirIfNotExists($this->modulesRootPath); + + $tarArchive = new \PharData($archive->getFilePath()); + $tarArchive->extractTo($this->modulesRootPath); + + if ($external) { + $vendorDirPath = $this->modulesRootPath . '/' . $archive->getArchiveName()->getVendorName(); + $moduleDirPath = $this->modulesRootPath . '/' . $archive->getArchiveName(); + + $this->createDirIfNotExists($vendorDirPath); + $this->createDirIfNotExists($moduleDirPath); + + rename( + $this->modulesRootPath . '/' . $tarArchive->getFileName(), + $this->getModulePathFromArchive($archive) + ); + } + } + + /** + * Liefert zu einem Archive den ModulePath + * z. B. /.../ModifiedModuleLoaderClient/Modules/composer/autoload/1.0.0/ + */ + private function getModulePathFromArchive(Archive $archive): string + { + return $this->modulesRootPath . '/' . $archive->getArchiveName() . '/' . $archive->getVersion(); + } + + /** + * Liefert den gesatem Modul Path zu einem Modul + * z. B. /.../ModifiedModuleLoaderClient/Modules/composer/autoload/ + */ + private function getModulePathFromModule(Module $module): string + { + return $module->getLocalRootPath() . $module->getModulePath(); + } + + /** + * // TODO: Man könnte diese Methode in die Klasse FileHelper auslagern + */ + private function createDirIfNotExists(string $path): void + { + if (!@mkdir($path) && !is_dir($path)) { + throw new \RuntimeException("Failed to create directory: " . $path); + } + } + + /** + * // TODO: Man könnte diese Methode in die Klasse FileHelper auslagern + */ + private function deleteFileIfExists(string $path): void + { + if (!@unlink($path) && file_exists($path)) { + throw new \RuntimeException("Failed to delete file: " . $path); + } + } +} diff --git a/src/Classes/Archive/ArchiveName.php b/src/Classes/Archive/ArchiveName.php new file mode 100644 index 00000000..9098ec2e --- /dev/null +++ b/src/Classes/Archive/ArchiveName.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace RobinTheHood\ModifiedModuleLoaderClient\Archive; + +/** + * Eine VO (Value Object) Klasse + * + * Da der Name eines Archives nicht willkührlich gewählt sein darf, wir der Name eines Archives durch diese Klasse + * repräsentiert. Der Konstruktor kann beim Erstellen eines Objekts zudem überprüfen, ob es sich um einen validen + * ArchiveNamen-String handelt. + */ +class ArchiveName +{ + private string $value; + + private string $vendorName; + + private string $moduleName; + + public function __construct(string $value) + { + if (!$this->isValidArchiveName($value)) { + throw new \InvalidArgumentException('No valid ArchiveName'); + } + + $this->value = $value; + + $parts = explode('/', $value); + $this->vendorName = $parts[0]; + $this->moduleName = $parts[1]; + } + + public function getModuleName(): string + { + return $this->moduleName; + } + + public function getVendorName(): string + { + return $this->vendorName; + } + + public function __toString(): string + { + return $this->value; + } + + private function isValidArchiveName(string $archiveName): bool + { + $pattern = '/^([A-Za-z0-9_-]+)\/([A-Za-z0-9_-]+)$/'; + + return preg_match($pattern, $archiveName) === 1; + } +} diff --git a/src/Classes/Archive/ArchivePuller.php b/src/Classes/Archive/ArchivePuller.php new file mode 100644 index 00000000..dcc29808 --- /dev/null +++ b/src/Classes/Archive/ArchivePuller.php @@ -0,0 +1,88 @@ +httpRequest = $httpRequest; + $this->parser = $parser; + $this->archivesRootPath = $archivesRootPath; + } + + /** + * @throws RuntimeException wenn das Archive nicht vom Server geladen werden konnte. + */ + public function pull(string $archiveName, string $version, string $url): Archive + { + $archive = $this->createArchiveObjFromStrings($archiveName, $version); + + $tarArchiveContent = $this->httpRequest->sendGetRequest($url); + + if (!$tarArchiveContent || !$this->isTarArchive($tarArchiveContent)) { + throw new RuntimeException("Failed to pull Archive: {$archiveName}:{$version}"); + } + + $this->createDirIfNotExists($archive->getArchivesRootPath()); + file_put_contents($archive->getFilePath(), $tarArchiveContent); + + return $archive; + } + + private function createArchiveObjFromStrings(string $archiveName, string $version): Archive + { + $archiveNameObj = new ArchiveName($archiveName); + $versionObj = $this->parser->parse($version); + + return new Archive($archiveNameObj, $versionObj, $this->archivesRootPath); + } + + /** + * Überprüft, ob $content die Tarball-Signatur beinhaltet + * + * @param string $content .tar File as string + * + * // TODO: Man könnte diese Methode als eigenständige Klasse TarFileVerifier auslagern + */ + private function isTarArchive(string $content): bool + { + $tarballSignature = "ustar"; + $magic = substr($content, 257, 5); + + return ($magic === $tarballSignature); + } + + /** + * // TODO: Man könnte diese Methode in die Klasse FileHelper auslagern + */ + private function createDirIfNotExists(string $path): void + { + if (!@mkdir($path) && !is_dir($path)) { + throw new \RuntimeException("Failed to create directory: " . $path); + } + } +} diff --git a/src/Classes/Helpers/ServerHelper.php b/src/Classes/Helpers/ServerHelper.php index 5b726c4b..3506ff35 100644 --- a/src/Classes/Helpers/ServerHelper.php +++ b/src/Classes/Helpers/ServerHelper.php @@ -18,7 +18,9 @@ class ServerHelper public static function getUri(): string { $http = empty($_SERVER['HTTPS']) ? 'http://' : 'https://'; - $url = $_SERVER['SERVER_NAME'] . $_SERVER['SCRIPT_NAME']; + $serverName = $_SERVER['SERVER_NAME'] ?? 'unknown-server-name.de'; + $scriptName = $_SERVER['SCRIPT_NAME'] ?? '/unknown-scriptname.php'; + $url = $serverName . $scriptName; $parts = pathinfo($url); return $http . $parts['dirname']; } diff --git a/src/Classes/Loader/LocalModuleLoader.php b/src/Classes/Loader/LocalModuleLoader.php index 724cbf11..10e5db05 100644 --- a/src/Classes/Loader/LocalModuleLoader.php +++ b/src/Classes/Loader/LocalModuleLoader.php @@ -27,6 +27,9 @@ class LocalModuleLoader /** @var ModuleFilter */ private $moduleFilter; + /** @var string */ + private $modulesRootPath; + public static function create(int $mode): LocalModuleLoader { $moduleFilter = ModuleFilter::create($mode); @@ -37,6 +40,12 @@ public static function create(int $mode): LocalModuleLoader public function __construct(ModuleFilter $moduleFilter) { $this->moduleFilter = $moduleFilter; + $this->modulesRootPath = App::getModulesRoot(); + } + + public function setModulesRootPath(string $path): void + { + $this->modulesRootPath = $path; } /** @@ -127,11 +136,11 @@ public function loadAllInstalledVersions(): array public function getVendorDirs() { - return FileHelper::scanDir(App::getModulesRoot(), FileHelper::DIRS_ONLY); + return FileHelper::scanDir($this->modulesRootPath, FileHelper::DIRS_ONLY); } public function getModuleDirs() { - return FileHelper::scanDirRecursive(App::getModulesRoot(), FileHelper::DIRS_ONLY, false, 3); + return FileHelper::scanDirRecursive($this->modulesRootPath, FileHelper::DIRS_ONLY, false, 3); } } diff --git a/src/Classes/Module.php b/src/Classes/Module.php index 034fee3e..58698618 100644 --- a/src/Classes/Module.php +++ b/src/Classes/Module.php @@ -89,8 +89,7 @@ class Module extends ModuleInfo private $isLoadable; /** - * Liefert den absoluten Pfad zum MMLC - * MMLC-Root Verzeichnis. + * Liefert den absoluten Pfad zum MMLC-Root Verzeichnis. * * Beispiel: * /root/dir1/dir2/.../ModifiedModuleLoaderClient diff --git a/src/Classes/ModuleInstaller.php b/src/Classes/ModuleInstaller.php index 6f72236f..5116780a 100644 --- a/src/Classes/ModuleInstaller.php +++ b/src/Classes/ModuleInstaller.php @@ -18,6 +18,10 @@ use RobinTheHood\ModifiedModuleLoaderClient\Config; use RobinTheHood\ModifiedModuleLoaderClient\FileInfo; use RobinTheHood\ModifiedModuleLoaderClient\Api\V1\ApiRequest; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\Archive as ArchiveArchive; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchiveHandler; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchiveName; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchivePuller; use RobinTheHood\ModifiedModuleLoaderClient\DependencyManager\Combination; use RobinTheHood\ModifiedModuleLoaderClient\DependencyManager\DependencyManager; use RobinTheHood\ModifiedModuleLoaderClient\Loader\LocalModuleLoader; @@ -38,12 +42,29 @@ class ModuleInstaller /** @var LocalModuleLoader */ private $localModuleLoader; + /** @var ArchivePuller */ + private $archivePuller; + + /** @var ArchiveHandler */ + private $archiveHandler; + + + + // new ArchiveHandler($this->localModuleLoader, App::getModulesRoot()); public static function create(int $mode): ModuleInstaller { $dependencyManager = DependencyManager::create($mode); $moduleFilter = ModuleFilter::create($mode); $localModuleLoader = LocalModuleLoader::create($mode); - $moduleInstaller = new ModuleInstaller($dependencyManager, $moduleFilter, $localModuleLoader); + $archivePuller = ArchivePuller::create(); + $archiveHandler = ArchiveHandler::create($mode); + $moduleInstaller = new ModuleInstaller( + $dependencyManager, + $moduleFilter, + $localModuleLoader, + $archivePuller, + $archiveHandler + ); return $moduleInstaller; } @@ -55,11 +76,15 @@ public static function createFromConfig(): ModuleInstaller public function __construct( DependencyManager $dependencyManager, ModuleFilter $moduleFilter, - LocalModuleLoader $localModuleLoader + LocalModuleLoader $localModuleLoader, + ArchivePuller $archivePuller, + ArchiveHandler $archiveHandler ) { $this->dependencyManager = $dependencyManager; $this->moduleFilter = $moduleFilter; $this->localModuleLoader = $localModuleLoader; + $this->archivePuller = $archivePuller; + $this->archiveHandler = $archiveHandler; } public function pull(Module $module): bool @@ -83,6 +108,12 @@ public function pull(Module $module): bool } try { + // New + $archive = $this->archivePuller->pull($module->getArchiveName(), $module->getVersion(), $archiveUrl); + $this->archiveHandler->extract($archive); + return true; + + // Old $archive = Archive::pullArchive($archiveUrl, $module->getArchiveName(), $module->getVersion()); $archive->untarArchive(); return true; diff --git a/tests/unit/ArchiveTests/ArchiveHandlerTest.php b/tests/unit/ArchiveTests/ArchiveHandlerTest.php new file mode 100644 index 00000000..b2386eea --- /dev/null +++ b/tests/unit/ArchiveTests/ArchiveHandlerTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace RobinTheHood\ModifiedModuleLoaderClient\Tests\Unit\ArchiveTests; + +use PHPUnit\Framework\TestCase; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\Archive; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchiveHandler; +use RobinTheHood\ModifiedModuleLoaderClient\Loader\LocalModuleLoader; + +class ArchiveHandlerTest extends TestCase +{ + /** @var string */ + protected $testDir; + + protected function setUp(): void + { + parent::setUp(); + + // Testordner erstellen + $this->testDir = __DIR__ . '/test_files/'; + @mkdir($this->testDir, 0777, true); + + // Testorder und Dateo im Ordner erstellen + @mkdir($this->testDir . 'ModulesExtracted', 0777, true); + @mkdir($this->testDir . 'Modules/robinthehood/modified-std-module/1.2.3', 0777, true); + file_put_contents( + $this->testDir . 'Modules/robinthehood/modified-std-module/1.2.3/moduleinfo.json', + '{ + "archiveName": "robinthehood/modified-std-module", + "version": "1.2.3" + }' + ); + + @mkdir($this->testDir . 'Archives', 0777, true); + } + + protected function tearDown(): void + { + parent::tearDown(); + + // Testdateien löschen + unlink($this->testDir . 'Modules/robinthehood/modified-std-module/1.2.3/moduleinfo.json'); + rmdir($this->testDir . 'Modules/robinthehood/modified-std-module/1.2.3'); + rmdir($this->testDir . 'Modules/robinthehood/modified-std-module'); + rmdir($this->testDir . 'Modules/robinthehood'); + rmdir($this->testDir . 'Modules'); + + unlink($this->testDir . 'ModulesExtracted/robinthehood/modified-std-module/1.2.3/moduleinfo.json'); + rmdir($this->testDir . 'ModulesExtracted/robinthehood/modified-std-module/1.2.3'); + rmdir($this->testDir . 'ModulesExtracted/robinthehood/modified-std-module'); + rmdir($this->testDir . 'ModulesExtracted/robinthehood'); + rmdir($this->testDir . 'ModulesExtracted'); + + unlink($this->testDir . 'Archives/robinthehood_modified-std-module_1.2.3.tar'); + rmdir($this->testDir . 'Archives'); + + rmdir($this->testDir); + } + + public function testPackAndExtract(): void + { + $mode = 0; // Set the appropriate mode + $archiveName = 'robinthehood/modified-std-module'; + $version = '1.2.3'; + $archivesRootPath = $this->testDir . 'Archives'; + $modulesRootPath = $this->testDir . 'Modules'; + $modulesExtractedRootPath = $this->testDir . 'ModulesExtracted'; + + // Create archive + $archive = Archive::create($archiveName, $version, $archivesRootPath); + + // Create ArchiveHandler + $localModuleLoader = LocalModuleLoader::create(0); + $localModuleLoader->setModulesRootPath($modulesRootPath); + $archiveHandler = new ArchiveHandler($localModuleLoader, $modulesRootPath); + + // Pack archive + $archiveHandler->pack($archive); + + // Check if archive file exists + $this->assertFileExists($archive->getFilePath()); + + // Create archive + $archiveHandlerExtract = new ArchiveHandler($localModuleLoader, $modulesExtractedRootPath); + + // Extract archive + $archiveHandlerExtract->extract($archive); + + // Check if module directory exists + $modulePath = $modulesExtractedRootPath . '/' . $archiveName . '/' . $version; + $this->assertDirectoryExists($modulePath); + } +} diff --git a/tests/unit/ArchiveTests/ArchiveNameTest.php b/tests/unit/ArchiveTests/ArchiveNameTest.php new file mode 100644 index 00000000..c07546f1 --- /dev/null +++ b/tests/unit/ArchiveTests/ArchiveNameTest.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace RobinTheHood\ModifiedModuleLoaderClient\Tests\Unit\ArchiveTests; + +use PHPUnit\Framework\TestCase; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchiveName; + +class ArchiveNameTest extends TestCase +{ + public function testConstructorValidArchiveName(): void + { + $archiveName = new ArchiveName('vendor/module'); + + $this->assertInstanceOf(ArchiveName::class, $archiveName); + $this->assertSame('module', $archiveName->getModuleName()); + $this->assertSame('vendor', $archiveName->getVendorName()); + $this->assertSame('vendor/module', $archiveName->__toString()); + } + + public function testConstructorInvalidArchiveName1(): void + { + $this->expectException(\InvalidArgumentException::class); + + new ArchiveName('invalid'); + } + + public function testConstructorInvalidArchiveName2(): void + { + $this->expectException(\InvalidArgumentException::class); + + new ArchiveName('invalid/invalid/'); + } + + public function testConstructorInvalidArchiveName3(): void + { + $this->expectException(\InvalidArgumentException::class); + + new ArchiveName('in.valid/invalid'); + } +} diff --git a/tests/unit/ArchiveTests/ArchivePullerTest.php b/tests/unit/ArchiveTests/ArchivePullerTest.php new file mode 100644 index 00000000..bf17d6ee --- /dev/null +++ b/tests/unit/ArchiveTests/ArchivePullerTest.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace RobinTheHood\ModifiedModuleLoaderClient\Tests\Unit\ArchiveTests; + +use PHPUnit\Framework\TestCase; +use RobinTheHood\ModifiedModuleLoaderClient\Api\V1\ApiRequest; +use RobinTheHood\ModifiedModuleLoaderClient\Api\V1\HttpRequest; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\Archive; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchivePuller; +use RobinTheHood\ModifiedModuleLoaderClient\Semver\Parser; +use RuntimeException; + +class ArchivePullerTest extends TestCase +{ + /** @var string */ + protected $testDir; + + protected function setUp(): void + { + parent::setUp(); + + // Testordner erstellen + $this->testDir = __DIR__ . '/test_files/'; + @mkdir($this->testDir, 0777, true); + + // Testorder und Dateo im Ordner erstellen + + @mkdir($this->testDir . 'Archives', 0777, true); + } + + protected function tearDown(): void + { + parent::tearDown(); + + // Testdateien löschen + @unlink($this->testDir . 'Archives/robinthehood_modified-std-module_0.9.0.tar'); + @rmdir($this->testDir . 'Archives'); + + @rmdir($this->testDir); + } + + public function testPullValidArchive(): void + { + $archivesRootPath = $this->testDir . 'Archives'; + + $archivePuller = new ArchivePuller( + new HttpRequest(), + Parser::create(), + $archivesRootPath + ); + + $apiRequest = new ApiRequest(); + $result = $apiRequest->getArchive('robinthehood/modified-std-module', '0.9.0'); + $content = $result['content'] ?? []; + $archiveUrl = $content['archiveUrl'] ?? ''; + $archive = $archivePuller->pull('robinthehood/modified-std-module', '0.9.0', $archiveUrl); + + $this->assertInstanceOf(Archive::class, $archive); + $this->assertSame('robinthehood/modified-std-module', $archive->getArchiveName()->__toString()); + $this->assertSame('0.9.0', $archive->getVersion()->__toString()); + $this->assertSame($archivesRootPath . '/robinthehood_modified-std-module_0.9.0.tar', $archive->getFilePath()); + } + + public function testPullArchiveFromInvalidUrl(): void + { + $archivesRootPath = $this->testDir . 'Archives'; + + $archivePuller = new ArchivePuller( + new HttpRequest(), + Parser::create(), + $archivesRootPath + ); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessageMatches( + '/Error sending the GET request:/' + ); + + $archivePuller->pull('robinthehood/modified-std-module', '0.9.0', 'this-is-a-not-working-url.local'); + } + + public function testPullInvalidArchive(): void + { + $archivesRootPath = $this->testDir . 'Archives'; + + $archivePuller = new ArchivePuller( + new HttpRequest(), + Parser::create(), + $archivesRootPath + ); + + $this->expectException(RuntimeException::class); + $this->expectExceptionMessage('Failed to pull Archive: robinthehood/modified-std-module:0.9.0'); + + $archivePuller->pull('robinthehood/modified-std-module', '0.9.0', 'https://postman-echo.com/get'); + } +} diff --git a/tests/unit/ArchiveTests/ArchiveTest.php b/tests/unit/ArchiveTests/ArchiveTest.php new file mode 100644 index 00000000..e0fc53ea --- /dev/null +++ b/tests/unit/ArchiveTests/ArchiveTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +declare(strict_types=1); + +namespace RobinTheHood\ModifiedModuleLoaderClient\Tests\Unit\ArchiveTests; + +use PHPUnit\Framework\TestCase; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\Archive; +use RobinTheHood\ModifiedModuleLoaderClient\Archive\ArchiveName; +use RobinTheHood\ModifiedModuleLoaderClient\Semver\Version; + +class ArchiveTest extends TestCase +{ + public function testCreate(): void + { + $archiveName = 'robinthehood/modified-std-module'; + $version = '1.0.0'; + $archivesRootPath = '/path/to/archives'; + + $archive = Archive::create($archiveName, $version, $archivesRootPath); + + $this->assertInstanceOf(Archive::class, $archive); + $this->assertInstanceOf(ArchiveName::class, $archive->getArchiveName()); + $this->assertInstanceOf(Version::class, $archive->getVersion()); + $this->assertSame($archiveName, $archive->getArchiveName()->__toString()); + $this->assertSame($version, $archive->getVersion()->__toString()); + $this->assertSame($archivesRootPath, $archive->getArchivesRootPath()); + } + + public function testGetFileName(): void + { + $archiveName = new ArchiveName('robinthehood/modified-std-module'); + $version = new Version(1, 2, 3); + $archivesRootPath = '/path/to/archives'; + + $archive = new Archive($archiveName, $version, $archivesRootPath); + + $expectedFileName = 'robinthehood_modified-std-module_1.2.3.tar'; + $this->assertSame($expectedFileName, $archive->getFileName()); + } + + public function testGetFilePath(): void + { + $archiveName = new ArchiveName('robinthehood/modified-std-module'); + $version = new Version(1, 2, 3); + $archivesRootPath = '/path/to/archives'; + + $archive = new Archive($archiveName, $version, $archivesRootPath); + + $expectedFilePath = '/path/to/archives/robinthehood_modified-std-module_1.2.3.tar'; + $this->assertSame($expectedFilePath, $archive->getFilePath()); + } +}