diff --git a/README.md b/README.md index fc1d5ce..f4555bd 100644 --- a/README.md +++ b/README.md @@ -643,6 +643,27 @@ Removes a compression flag. **Returns**: The current instance of the SevenZip class. +### `rename(array $renameMap): string` + +Renames files within the archive. + +**Parameters** + +- `$renameMap`: An associative array where keys are the old names and values are the new names. + +**Returns**: The output of the 7-Zip command. + +**Throws** + +- `InvalidArgumentException`: If the source path is not set. + +**Example** + +```php +$sevenZip->source('/path/to/archive.7z') + ->rename(['old_name.txt' => 'new_name.txt']); +``` + ### `reset(): SevenZip` Resets the property values to their original state. diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 04a5ea4..470db3b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,17 +1,5 @@ parameters: ignoreErrors: - - - message: '#^Deprecated in PHP 8\.4\: Parameter \#3 \$previous \(Throwable\) is implicitly nullable via default value null\.$#' - identifier: parameter.implicitlyNullable - count: 1 - path: src/Exceptions/ExecutableNotFoundException.php - - - - message: '#^Deprecated in PHP 8\.4\: Parameter \#2 \$value \(string\) is implicitly nullable via default value null\.$#' - identifier: parameter.implicitlyNullable - count: 1 - path: src/SevenZip.php - - message: '#^Method Verseles\\SevenZip\\SevenZip\:\:addFlag\(\) should return \$this\(Verseles\\SevenZip\\SevenZip\) but returns Verseles\\SevenZip\\SevenZip\.$#' identifier: return.type diff --git a/src/Exceptions/ExecutableNotFoundException.php b/src/Exceptions/ExecutableNotFoundException.php index 3b1c30b..131bad2 100644 --- a/src/Exceptions/ExecutableNotFoundException.php +++ b/src/Exceptions/ExecutableNotFoundException.php @@ -6,7 +6,7 @@ class ExecutableNotFoundException extends \Exception { - public function __construct($message = 'Executable 7z not found.', $code = 0, Throwable $previous = null) + public function __construct($message = 'Executable 7z not found.', $code = 0, ?Throwable $previous = null) { parent::__construct($message, $code, $previous); } diff --git a/src/SevenZip.php b/src/SevenZip.php index 67eecbb..1a07049 100644 --- a/src/SevenZip.php +++ b/src/SevenZip.php @@ -315,7 +315,7 @@ public function mmt(int|bool|string $threads = "on"): self */ public function addFlag( string $flag, - string $value = null, + ?string $value = null, bool $glued = false, ): self { if ($glued && $value !== null) { @@ -1130,6 +1130,44 @@ public function testWithDetails(): string return $this->runCommand($command); } + /** + * Rename files in an archive. + * + * @param array $renameMap An associative array where keys are the old names and values are the new names. + * + * @return string The output of the 7-Zip command. + * @throws \InvalidArgumentException If source path is not set. + */ + public function rename(array $renameMap): string + { + if (!$this->getSourcePath()) { + throw new \InvalidArgumentException( + "Archive file path (source) must be set", + ); + } + + if ($this->getPassword()) { + $this->addFlag("p", $this->getPassword(), glued: true); + } + + $renames = []; + foreach ($renameMap as $oldName => $newName) { + $renames[] = $oldName; + $renames[] = $newName; + } + + $command = [ + $this->sevenZipPath, + "rn", + ...$this->flagrize($this->getAlwaysFlags()), + ...$this->flagrize($this->getCustomFlags()), + $this->getSourcePath(), + ...$renames, + ]; + + return $this->runCommand($command); + } + /** * Format flags and values into an array of strings suitable for passing to 7-Zip commands. * diff --git a/tests/SevenZipTest.php b/tests/SevenZipTest.php index 824e221..f90e8e2 100644 --- a/tests/SevenZipTest.php +++ b/tests/SevenZipTest.php @@ -274,9 +274,28 @@ public function testVerify(string $format): void $this->assertStringContainsString('Everything is Ok', $output); } - #[Covers('\Verseles\SevenZip\SevenZip::extract')] + #[Covers('\Verseles\SevenZip\SevenZip::rename')] #[DataProvider('compressAndExtractDataProvider')] #[Depends('testVerify')] + public function testRename(string $format): void + { + $archive = $this->testDir . '/target/archive.' . $format; + + if ($format === 'bzip2') { + $this->expectNotToPerformAssertions(); + return; + } + + $output = $this->sevenZip + ->source(path: $archive) + ->rename(['source/Avatart.svg' => 'source/Avatar-renamed.svg']); + + $this->assertStringContainsString('Everything is Ok', $output); + } + + #[Covers('\Verseles\SevenZip\SevenZip::extract')] + #[DataProvider('compressAndExtractDataProvider')] + #[Depends('testRename')] public function testExtract(string $format): void { $archive = $this->testDir . '/target/archive.' . $format; @@ -287,7 +306,12 @@ public function testExtract(string $format): void ->source(path: $archive) ->target(path: $target) ->extract(); - $this->assertFileExists(filename: $target . '/source/Avatart.svg'); + + if ($format === 'bzip2') { + $this->assertFileExists(filename: $target . '/source/Avatart.svg'); + } else { + $this->assertFileExists(filename: $target . '/source/Avatar-renamed.svg'); + } $this->assertFileExists(filename: $target . '/source/js_interop_usage.md'); unlink($archive);