Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,28 @@ Removes a compression flag.

**Returns**: The current instance of the SevenZip class.

### `rename(array $renames): string`

Renames files within an archive. Note that the rename operation is not natively supported for `bzip2` archives.

**Parameters**

- `$renames`: An associative array mapping old file names to new file names.

**Returns**: The output of the 7-Zip command.

**Throws**

- `InvalidArgumentException`: If the archive path is not set or the renames array is empty.
- `RuntimeException`: If the format is not supported (e.g., `bzip2`).

**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.
Expand Down
12 changes: 0 additions & 12 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
@@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptions/ExecutableNotFoundException.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
55 changes: 54 additions & 1 deletion src/SevenZip.php
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -1086,6 +1086,59 @@ public function fileInfo(): array
return $this->parseFileInfoOutput($output);
}

/**
* Rename files in an archive.
*
* @param array $renames An associative array mapping old file names to new file names.
*
* @return string The output of the 7-Zip command.
* @throws \InvalidArgumentException If source path is not set or the renames array is empty.
* @throws \RuntimeException If the archive format is unsupported.
*/
public function rename(array $renames): string
{
if (!$this->getSourcePath()) {
throw new \InvalidArgumentException(
"Archive file path (source) must be set",
);
}

if (empty($renames)) {
throw new \InvalidArgumentException(
"Renames array cannot be empty",
);
}

$extension = strtolower(pathinfo($this->getSourcePath(), PATHINFO_EXTENSION));

if (in_array($this->getFormat(), ['bzip2', 'bz2']) || in_array($extension, ['bzip2', 'bz2'])) {
throw new \RuntimeException(
"Rename operation is not supported for bzip2 archives",
);
}

if ($this->getPassword()) {
$this->addFlag("p", $this->getPassword(), glued: true);
}

$renameArgs = [];
foreach ($renames as $oldName => $newName) {
$renameArgs[] = $oldName;
$renameArgs[] = $newName;
}

$command = [
$this->sevenZipPath,
"rn",
...$this->flagrize($this->getAlwaysFlags()),
...$this->flagrize($this->getCustomFlags()),
$this->getSourcePath(),
...$renameArgs,
];

return $this->runCommand($command);
}

/**
* Test the integrity of an archive.
*
Expand Down
34 changes: 32 additions & 2 deletions tests/SevenZipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -274,9 +274,35 @@ 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 (in_array($format, ['bzip2', 'bz2'])) {
$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Rename operation is not supported for bzip2 archives');
}

$renames = [
'source/Avatart.svg' => 'source/RenamedAvatar.svg'
];

// Do not set format explicitly so that we rely on source file extension for unsupported tests
$output = $this->sevenZip
->source(path: $archive)
->rename($renames);

if (!in_array($format, ['bzip2', 'bz2'])) {
$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;
Expand All @@ -287,7 +313,11 @@ public function testExtract(string $format): void
->source(path: $archive)
->target(path: $target)
->extract();
$this->assertFileExists(filename: $target . '/source/Avatart.svg');
if (in_array($format, ['bzip2', 'bz2'])) {
$this->assertFileExists(filename: $target . '/source/Avatart.svg');
} else {
$this->assertFileExists(filename: $target . '/source/RenamedAvatar.svg');
}
$this->assertFileExists(filename: $target . '/source/js_interop_usage.md');

unlink($archive);
Expand Down
Loading