Skip to content

Commit

Permalink
feature: add pathMask and limit to getEntries, performance optimiza…
Browse files Browse the repository at this point in the history
…tion for `getInfo` and `getEntry` (no longer lists all files in the archive)
  • Loading branch information
Gemorroj committed Apr 3, 2022
1 parent 11501b9 commit 2abc276
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 23 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ Archive7z\Info Object

// $obj->setPassword('123');

// $obj->getEntries('test', 100)
foreach ($obj->getEntries() as $entry) {
print_r($entry);
/*
Expand Down
26 changes: 11 additions & 15 deletions src/Archive7z.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ private function decorateCmdExtract(): array
if (null !== $this->password) {
$out[] = '-p'.$this->password;
} else {
$out[] = '-p '; //todo
$out[] = '-p '; // todo
}

return $out;
Expand Down Expand Up @@ -331,35 +331,31 @@ public function getContent(string $path): string
*/
public function getEntry(string $path): ?Entry
{
$path = \str_replace('\\', '/', $path);
$entries = $this->getEntries($path, 1);

foreach ($this->getEntries() as $v) {
if ($v->getUnixPath() === $path) {
return $v;
}
}

return null;
return $entries ? $entries[0] : null;
}

/**
* @throws \Symfony\Component\Process\Exception\ProcessFailedException
*
* @return Entry[]
*/
public function getEntries(): array
public function getEntries(?string $pathMask = null, ?int $limit = null): array
{
$process = $this->makeProcess('l', \array_merge([
'-slt',
], $this->decorateCmdExtract()));
$process = $this->makeProcess('l', \array_merge(
['-slt'],
$this->decorateCmdExtract(),
null !== $pathMask ? [$pathMask] : [],
));

$this->execute($process);

$out = \explode(\PHP_EOL, $process->getOutput());

$list = [];
$parser = new Parser($out);
foreach ($parser->parseEntries() as $v) {
foreach ($parser->parseEntries($limit) as $v) {
$list[] = new Entry($this, $v);
}

Expand All @@ -373,7 +369,7 @@ public function getInfo(): Info
{
$process = $this->makeProcess('l', \array_merge([
'-slt',
], $this->decorateCmdExtract()));
], $this->decorateCmdExtract(), ['Archive7z fake path']));

$this->execute($process);

Expand Down
5 changes: 4 additions & 1 deletion src/Parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public function parseHeader(): array
/**
* @return array<int, array<string, string>>
*/
public function parseEntries(): array
public function parseEntries(?int $limit = null): array
{
$isHead = true;
$list = [];
Expand All @@ -85,6 +85,9 @@ public function parseEntries(): array
continue;
}

if (null !== $limit && $i >= $limit) {
break;
}
if ($value === $this->newFileListToken) {
++$i;
continue;
Expand Down
2 changes: 1 addition & 1 deletion src/SolidMode.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/**
* @see https://documentation.help/7-Zip/method.htm#Solid
*/
class SolidMode /* implements \Stringable*/
class SolidMode /* implements \Stringable */
{
public const ON = 'on';
public const OFF = 'off';
Expand Down
69 changes: 63 additions & 6 deletions tests/Archive7zTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,8 @@ public function entryProvider(): array
['totalcommander-9.21a/test.tar'],
['totalcommander-9.21a/test.zip'],
['winrar-5.61/test.zip'],
//['winrar-5.61/test4.rar'], // not supported
//['winrar-5.61/test5.rar'], // not supported
// ['winrar-5.61/test4.rar'], // not supported
// ['winrar-5.61/test5.rar'], // not supported
['linux/zip-0.3/test.zip'],
['linux/p7zip-16.02/test.7z'],
['linux/p7zip-16.02/test.tar'],
Expand Down Expand Up @@ -485,17 +485,17 @@ public function testAddEntryLocalPathSubFiles(): void
public function delProvider(): array
{
return [
//['zip.7z'], // 7-Zip 21.02+ swears now at this
//['warnings.zip'], // not supported
// ['zip.7z'], // 7-Zip 21.02+ swears now at this
// ['warnings.zip'], // not supported
['7zip-18.05/test.7z'],
['7zip-18.05/test.tar'],
['7zip-18.05/test.wim'],
['7zip-18.05/test.zip'],
['totalcommander-9.21a/test.tar'],
['totalcommander-9.21a/test.zip'],
['winrar-5.61/test.zip'],
//['winrar-5.61/test4.rar'], // not supported
//['winrar-5.61/test5.rar'], // not supported
// ['winrar-5.61/test4.rar'], // not supported
// ['winrar-5.61/test5.rar'], // not supported
['linux/zip-0.3/test.zip'],
['linux/p7zip-16.02/test.7z'],
['linux/p7zip-16.02/test.tar'],
Expand Down Expand Up @@ -805,4 +805,61 @@ public function testInfo(string $archiveName): void
self::assertIsString($info->getType());
self::assertGreaterThan(0, $info->getPhysicalSize());
}

/**
* @dataProvider extractProvider
*/
public function testGetEntriesLimit(string $archiveName): void
{
$obj = new Archive7z($this->fixturesDir.'/'.$archiveName);
$entries = $obj->getEntries(null, 2);

self::assertIsArray($entries);
self::assertCount(2, $entries);
self::assertInstanceOf(Entry::class, $entries[0]);
self::assertInstanceOf(Entry::class, $entries[1]);
}

/**
* @dataProvider extractProvider
*/
public function testGetEntriesPathMask(string $archiveName): void
{
$path = 'test/test.txt';
$obj = new Archive7z($this->fixturesDir.'/'.$archiveName);
$entries = $obj->getEntries($path);

self::assertIsArray($entries);
self::assertCount(1, $entries);
self::assertInstanceOf(Entry::class, $entries[0]);
self::assertSame($path, $entries[0]->getUnixPath());
}

/**
* @dataProvider extractProvider
*/
public function testGetEntriesPathMaskCyrillic(string $archiveName): void
{
$path = 'чавес.jpg';
$obj = new Archive7z($this->fixturesDir.'/'.$archiveName);
$entries = $obj->getEntries($path);

self::assertIsArray($entries);
self::assertCount(1, $entries);
self::assertInstanceOf(Entry::class, $entries[0]);
self::assertSame($path, $entries[0]->getUnixPath());
}

/**
* @dataProvider extractProvider
*/
public function testGetEntriesPathMaskWildcard(string $archiveName): void
{
$path = 'test';
$obj = new Archive7z($this->fixturesDir.'/'.$archiveName);
$entries = $obj->getEntries($path);

self::assertIsArray($entries);
self::assertCount(3, $entries); // 1 folder + 2 files in the folder
}
}

0 comments on commit 2abc276

Please sign in to comment.