diff --git a/README.md b/README.md index 796de37..1a62197 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,11 @@ -`PhpZip` (ver 3.0.+) +`PhpZip` ==================== `PhpZip` - php library for manipulating zip archives. +[![Latest Stable Version](https://poser.pugx.org/nelexa/zip/v/stable)](https://packagist.org/packages/nelexa/zip) +[![Total Downloads](https://poser.pugx.org/nelexa/zip/downloads)](https://packagist.org/packages/nelexa/zip) +[![License](https://poser.pugx.org/nelexa/zip/license)](https://packagist.org/packages/nelexa/zip) + Features: --------- - Opening and unzipping zip files. diff --git a/src/PhpZip/Model/CentralDirectory.php b/src/PhpZip/Model/CentralDirectory.php index 9c8eb85..d8d9c7a 100644 --- a/src/PhpZip/Model/CentralDirectory.php +++ b/src/PhpZip/Model/CentralDirectory.php @@ -112,7 +112,11 @@ class CentralDirectory rewind($inputStream); // Constraint: A ZIP file must start with a Local File Header // or a (ZIP64) End Of Central Directory Record if it's empty. - $signature = unpack('V', fread($inputStream, 4))[1]; + $signatureBytes = fread($inputStream, 4); + if (strlen($signatureBytes) < 4) { + throw new ZipException("Invalid zip file."); + } + $signature = unpack('V', $signatureBytes)[1]; if ( ZipEntry::LOCAL_FILE_HEADER_SIG !== $signature && EndOfCentralDirectory::ZIP64_END_OF_CENTRAL_DIRECTORY_RECORD_SIG !== $signature @@ -342,7 +346,7 @@ class CentralDirectory $prototypeEntry->setExternalAttributes($entry->getExternalAttributes()); $prototypeEntry->setExtra($entry->getExtra()); $prototypeEntry->setPassword($this->password, $this->encryptionMethod); - if($this->clearPassword){ + if ($this->clearPassword) { $prototypeEntry->clearEncryption(); } } else { diff --git a/src/PhpZip/Model/EndOfCentralDirectory.php b/src/PhpZip/Model/EndOfCentralDirectory.php index 11b52ca..1730c0c 100644 --- a/src/PhpZip/Model/EndOfCentralDirectory.php +++ b/src/PhpZip/Model/EndOfCentralDirectory.php @@ -319,14 +319,6 @@ class EndOfCentralDirectory $this->newComment = $comment; } - /** - * @return bool - */ - public function isModified() - { - return $this->modified; - } - /** * Write end of central directory. * diff --git a/src/PhpZip/Model/Entry/ZipReadEntry.php b/src/PhpZip/Model/Entry/ZipReadEntry.php index bb5b5fe..01b2ee5 100644 --- a/src/PhpZip/Model/Entry/ZipReadEntry.php +++ b/src/PhpZip/Model/Entry/ZipReadEntry.php @@ -119,6 +119,10 @@ class ZipReadEntry extends ZipAbstractEntry public function getEntryContent() { if ($this->entryContent === null) { + if ($this->isDirectory()) { + $this->entryContent = null; + return $this->entryContent; + } $isEncrypted = $this->isEncrypted(); $password = $this->getPassword(); if ($isEncrypted && empty($password)) { diff --git a/src/PhpZip/ZipFile.php b/src/PhpZip/ZipFile.php index acbe97d..bb07cc3 100644 --- a/src/PhpZip/ZipFile.php +++ b/src/PhpZip/ZipFile.php @@ -433,7 +433,7 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator throw new InvalidArgumentException("Filename is null"); } if (!is_file($filename)) { - throw new InvalidArgumentException("File is not exists"); + throw new InvalidArgumentException("File $filename is not exists"); } if (null === $compressionMethod) { @@ -559,23 +559,17 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator } /** - * Add directory to the zip archive. + * Add directory not recursively to the zip archive. * * @param string $inputDir Input directory - * @param bool $recursive Recursive search files - * @param string|null $toLocalPath If not null then put $inputDir to path $outEntryDir - * @param array $ignoreFiles List of files to exclude from the folder $inputDir. - * @param int|null $compressionMethod Compression method - * @return bool + * @param string $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile * @throws InvalidArgumentException */ - public function addDir( - $inputDir, - $recursive = true, - $toLocalPath = "/", - array $ignoreFiles = [], - $compressionMethod = null - ) + public function addDir($inputDir, $localPath = "/", $compressionMethod = null) { $inputDir = (string)$inputDir; if ($inputDir === null || strlen($inputDir) === 0) { @@ -584,30 +578,102 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator if (!is_dir($inputDir)) { throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists'); } + $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR; - if (null !== $toLocalPath && is_string($toLocalPath) && !empty($toLocalPath)) { - $toLocalPath = rtrim($toLocalPath, '/') . '/'; - } else { - $toLocalPath = "/"; + $directoryIterator = new \DirectoryIterator($inputDir); + return $this->addFilesFromIterator($directoryIterator, $localPath, $compressionMethod); + } + + /** + * Add recursive directory to the zip archive. + * + * @param string $inputDir Input directory + * @param string $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @throws InvalidArgumentException + * @throws ZipUnsupportMethod + * @see ZipFile::METHOD_STORED + * @see ZipFile::METHOD_DEFLATED + * @see ZipFile::METHOD_BZIP2 + */ + public function addDirRecursive($inputDir, $localPath = "/", $compressionMethod = null) + { + $inputDir = (string)$inputDir; + if ($inputDir === null || strlen($inputDir) === 0) { + throw new InvalidArgumentException('Input dir empty'); + } + if (!is_dir($inputDir)) { + throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists'); } $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR; - $count = $this->count(); + $directoryIterator = new \RecursiveDirectoryIterator($inputDir); + return $this->addFilesFromIterator($directoryIterator, $localPath, $compressionMethod); + } - $files = FilesUtil::fileSearchWithIgnore($inputDir, $recursive, $ignoreFiles); + /** + * Add directories from directory iterator. + * + * @param \Iterator $iterator Directory iterator. + * @param string $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @throws InvalidArgumentException + * @throws ZipUnsupportMethod + * @see ZipFile::METHOD_STORED + * @see ZipFile::METHOD_DEFLATED + * @see ZipFile::METHOD_BZIP2 + */ + public function addFilesFromIterator( + \Iterator $iterator, + $localPath = '/', + $compressionMethod = null + ) + { + $localPath = (string)$localPath; + if (null !== $localPath && 0 !== strlen($localPath)) { + $localPath = rtrim($localPath, '/'); + } else { + $localPath = ""; + } + + $iterator = $iterator instanceof \RecursiveIterator ? + new \RecursiveIteratorIterator($iterator) : + new \IteratorIterator($iterator); /** - * @var \SplFileInfo $file + * @var string[] $files + * @var string $path */ - foreach ($files as $file) { - $filename = str_replace($inputDir, $toLocalPath, $file); - $filename = ltrim($filename, '/'); - if (is_dir($file)) { - FilesUtil::isEmptyDir($file) && $this->addEmptyDir($filename); - } elseif (is_file($file)) { - $this->addFile($file, $filename, $compressionMethod); + $files = []; + foreach ($iterator as $file) { + if ($file instanceof \SplFileInfo) { + empty($path) and $path = rtrim($file->getPath(), '/'); + if ('..' === $file->getBasename()) { + continue; + } + if ('.' === $file->getBasename()) { + $files[] = dirname($file->getPathname()); + } else { + $files[] = $file->getPathname(); + } } } - return $this->count() > $count; + + foreach ($files as $file) { + $relativePath = str_replace($path, $localPath, $file); + $relativePath = ltrim($relativePath, '/'); + if (is_dir($file)) { + FilesUtil::isEmptyDir($file) && $this->addEmptyDir($relativePath); + } elseif (is_file($file)) { + $this->addFile($file, $relativePath, $compressionMethod); + } + } + return $this; } /** @@ -615,33 +681,69 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator * * @param string $inputDir Input directory * @param string $globPattern Glob pattern. - * @param string|null $moveToPath Add files to this directory, or the root. - * @param bool $recursive Recursive search. - * @param int $compressionMethod Compression method. + * @param string|null $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. * @return ZipFile * @throws InvalidArgumentException * @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax */ - public function addFilesFromGlob( + public function addFilesFromGlob($inputDir, $globPattern, $localPath = '/', $compressionMethod = null) + { + return $this->addGlob($inputDir, $globPattern, $localPath, false, $compressionMethod); + } + + /** + * Add files recursively from glob pattern. + * + * @param string $inputDir Input directory + * @param string $globPattern Glob pattern. + * @param string|null $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @throws InvalidArgumentException + * @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax + */ + public function addFilesFromGlobRecursive($inputDir, $globPattern, $localPath = '/', $compressionMethod = null) + { + return $this->addGlob($inputDir, $globPattern, $localPath, true, $compressionMethod); + } + + /** + * Add files from glob pattern. + * + * @param string $inputDir Input directory + * @param string $globPattern Glob pattern. + * @param string|null $localPath Add files to this directory, or the root. + * @param bool $recursive Recursive search. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @throws InvalidArgumentException + * @sse https://en.wikipedia.org/wiki/Glob_(programming) Glob pattern syntax + */ + private function addGlob( $inputDir, $globPattern, - $moveToPath = '/', + $localPath = '/', $recursive = true, - $compressionMethod = self::METHOD_DEFLATED + $compressionMethod = null ) { $inputDir = (string)$inputDir; - if (empty($inputDir)) { + if (null === $inputDir || 0 === strlen($inputDir)) { throw new InvalidArgumentException('Input dir empty'); } if (!is_dir($inputDir)) { throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists'); } - if (null === $globPattern || strlen($globPattern) === 0) { - throw new InvalidArgumentException("globPattern null"); - } + $globPattern = (string)$globPattern; if (empty($globPattern)) { - throw new InvalidArgumentException("globPattern empty"); + throw new InvalidArgumentException("glob pattern empty"); } $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR; @@ -651,17 +753,17 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator if ($filesFound === false || empty($filesFound)) { return $this; } - if (!empty($moveToPath) && is_string($moveToPath)) { - $moveToPath = rtrim($moveToPath, '/') . '/'; + if (!empty($localPath) && is_string($localPath)) { + $localPath = rtrim($localPath, '/') . '/'; } else { - $moveToPath = "/"; + $localPath = "/"; } /** * @var string $file */ foreach ($filesFound as $file) { - $filename = str_replace($inputDir, $moveToPath, $file); + $filename = str_replace($inputDir, $localPath, $file); $filename = ltrim($filename, '/'); if (is_dir($file)) { FilesUtil::isEmptyDir($file) && $this->addEmptyDir($filename); @@ -677,29 +779,67 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator * * @param string $inputDir Search files in this directory. * @param string $regexPattern Regex pattern. - * @param string|null $moveToPath Add files to this directory, or the root. + * @param string|null $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @internal param bool $recursive Recursive search. + */ + public function addFilesFromRegex($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null) + { + return $this->addRegex($inputDir, $regexPattern, $localPath, false, $compressionMethod); + } + + /** + * Add files recursively from regex pattern. + * + * @param string $inputDir Search files in this directory. + * @param string $regexPattern Regex pattern. + * @param string|null $localPath Add files to this directory, or the root. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. + * @return ZipFile + * @internal param bool $recursive Recursive search. + */ + public function addFilesFromRegexRecursive($inputDir, $regexPattern, $localPath = "/", $compressionMethod = null) + { + return $this->addRegex($inputDir, $regexPattern, $localPath, true, $compressionMethod); + } + + + /** + * Add files from regex pattern. + * + * @param string $inputDir Search files in this directory. + * @param string $regexPattern Regex pattern. + * @param string|null $localPath Add files to this directory, or the root. * @param bool $recursive Recursive search. - * @param int $compressionMethod Compression method. + * @param int|null $compressionMethod Compression method. + * Use ZipFile::METHOD_STORED, ZipFile::METHOD_DEFLATED or ZipFile::METHOD_BZIP2. + * If null, then auto choosing method. * @return ZipFile * @throws InvalidArgumentException */ - public function addFilesFromRegex( + private function addRegex( $inputDir, $regexPattern, - $moveToPath = "/", + $localPath = "/", $recursive = true, - $compressionMethod = self::METHOD_DEFLATED + $compressionMethod = null ) { - if ($regexPattern === null || !is_string($regexPattern) || empty($regexPattern)) { + $regexPattern = (string)$regexPattern; + if (empty($regexPattern)) { throw new InvalidArgumentException("regex pattern empty"); } $inputDir = (string)$inputDir; - if (empty($inputDir)) { - throw new InvalidArgumentException('Invalid $inputDir value'); + if (null === $inputDir || 0 === strlen($inputDir)) { + throw new InvalidArgumentException('Input dir empty'); } if (!is_dir($inputDir)) { - throw new InvalidArgumentException('Path ' . $inputDir . ' can\'t directory.'); + throw new InvalidArgumentException('Directory ' . $inputDir . ' can\'t exists'); } $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR; @@ -707,10 +847,10 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator if ($files === false || empty($files)) { return $this; } - if (!empty($moveToPath) && is_string($moveToPath)) { - $moveToPath = rtrim($moveToPath, '/') . '/'; + if (!empty($localPath) && is_string($localPath)) { + $localPath = rtrim($localPath, '/') . '/'; } else { - $moveToPath = "/"; + $localPath = "/"; } $inputDir = rtrim($inputDir, '/\\') . DIRECTORY_SEPARATOR; @@ -718,7 +858,7 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator * @var string $file */ foreach ($files as $file) { - $filename = str_replace($inputDir, $moveToPath, $file); + $filename = str_replace($inputDir, $localPath, $file); $filename = ltrim($filename, '/'); if (is_dir($file)) { FilesUtil::isEmptyDir($file) && $this->addEmptyDir($filename); @@ -936,6 +1076,31 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator return $content; } + /** + * Rewrite and reopen zip archive. + * @return ZipFile + * @throws ZipException + */ + public function rewrite() + { + if($this->inputStream === null){ + throw new ZipException('input stream is null'); + } + $meta = stream_get_meta_data($this->inputStream); + $content = $this->outputAsString(); + $this->close(); + if ($meta['wrapper_type'] === 'plainfile') { + if (file_put_contents($meta['uri'], $content) === false) { + throw new ZipException("Can not overwrite the zip file in the {$meta['uri']} file."); + } + if (!($handle = @fopen($meta['uri'], 'rb'))) { + throw new ZipException("File {$meta['uri']} can't open."); + } + return $this->openFromStream($handle); + } + return $this->openFromString($content); + } + /** * Close zip archive and release input stream. */ @@ -976,12 +1141,11 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator * @link http://php.net/manual/en/arrayaccess.offsetget.php * @param string $entryName The offset to retrieve. * @return string|null + * @throws ZipNotFoundEntry */ public function offsetGet($entryName) { - return $this->offsetExists($entryName) ? - $this->centralDirectory->getEntry($entryName)->getEntryContent() : - null; + return $this->centralDirectory->getEntry($entryName)->getEntryContent(); } /** @@ -992,6 +1156,8 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator * @throws InvalidArgumentException * @see ZipFile::addFromString * @see ZipFile::addEmptyDir + * @see ZipFile::addFile + * @see ZipFile::addFilesFromIterator */ public function offsetSet($entryName, $contents) { @@ -1002,6 +1168,15 @@ class ZipFile implements \Countable, \ArrayAccess, \Iterator if (strlen($entryName) === 0) { throw new InvalidArgumentException('entryName is empty'); } + if ($contents instanceof \SplFileInfo) { + if ($contents instanceof \DirectoryIterator) { + $this->addFilesFromIterator($contents, $entryName); + return; + } + $this->addFile($contents->getPathname(), $entryName); + return; + } + $contents = (string)$contents; if ($entryName[strlen($entryName) - 1] === '/') { $this->addEmptyDir($entryName); } else { diff --git a/tests/PhpZip/ZipFileAddDirTest.php b/tests/PhpZip/ZipFileAddDirTest.php new file mode 100644 index 0000000..f4a4753 --- /dev/null +++ b/tests/PhpZip/ZipFileAddDirTest.php @@ -0,0 +1,359 @@ + 'Hidden file', + 'text file.txt' => 'Text file', + 'Текстовый документ.txt' => 'Текстовый документ', + 'empty dir/' => null, + 'empty dir2/ещё пустой каталог/' => null, + 'catalog/New File' => 'New Catalog File', + 'catalog/New File 2' => 'New Catalog File 2', + 'catalog/Empty Dir/' => null, + 'category/list.txt' => 'Category list', + 'category/Pictures/128x160/Car/01.jpg' => 'File 01.jpg', + 'category/Pictures/128x160/Car/02.jpg' => 'File 02.jpg', + 'category/Pictures/240x320/Car/01.jpg' => 'File 01.jpg', + 'category/Pictures/240x320/Car/02.jpg' => 'File 02.jpg', + ]; + + /** + * Before test + */ + protected function setUp() + { + parent::setUp(); + $this->fillDirectory(); + } + + protected function fillDirectory() + { + foreach (self::$files as $name => $content) { + $fullName = $this->outputDirname . '/' . $name; + if ($content === null) { + if (!is_dir($fullName)) { + mkdir($fullName, 0755, true); + } + } else { + $dirname = dirname($fullName); + if (!is_dir($dirname)) { + mkdir($dirname, 0755, true); + } + file_put_contents($fullName, $content); + } + } + } + + protected static function assertFilesResult(ZipFile $zipFile, array $actualResultFiles = [], $localPath = '/') + { + $localPath = rtrim($localPath, '/'); + $localPath = empty($localPath) ? "" : $localPath . '/'; + self::assertEquals(sizeof($zipFile), sizeof($actualResultFiles)); + $actualResultFiles = array_flip($actualResultFiles); + foreach (self::$files as $file => $content) { + $zipEntryName = $localPath . $file; + if (isset($actualResultFiles[$file])) { + self::assertTrue(isset($zipFile[$zipEntryName])); + self::assertEquals($zipFile[$zipEntryName], $content); + unset($actualResultFiles[$file]); + } else { + self::assertFalse(isset($zipFile[$zipEntryName])); + } + } + self::assertEmpty($actualResultFiles); + } + + public function testAddDirWithLocalPath() + { + $localPath = 'to/path'; + + $zipFile = new ZipFile(); + $zipFile->addDir($this->outputDirname, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + '.hidden', + 'text file.txt', + 'Текстовый документ.txt', + 'empty dir/', + ], $localPath); + $zipFile->close(); + } + + public function testAddDirWithoutLocalPath() + { + $zipFile = new ZipFile(); + $zipFile->addDir($this->outputDirname); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + '.hidden', + 'text file.txt', + 'Текстовый документ.txt', + 'empty dir/', + ]); + $zipFile->close(); + } + + public function testAddFilesFromIterator() + { + $localPath = 'to/project'; + + $directoryIterator = new \DirectoryIterator($this->outputDirname); + + $zipFile = new ZipFile(); + $zipFile->addFilesFromIterator($directoryIterator, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + '.hidden', + 'text file.txt', + 'Текстовый документ.txt', + 'empty dir/', + ], $localPath); + $zipFile->close(); + } + + public function testAddFilesFromRecursiveIterator() + { + $localPath = 'to/project'; + + $directoryIterator = new \RecursiveDirectoryIterator($this->outputDirname); + + $zipFile = new ZipFile(); + $zipFile->addFilesFromIterator($directoryIterator, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, array_keys(self::$files), $localPath); + $zipFile->close(); + } + + public function testAddRecursiveDirWithLocalPath() + { + $localPath = 'to/path'; + + $zipFile = new ZipFile(); + $zipFile->addDirRecursive($this->outputDirname, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, array_keys(self::$files), $localPath); + $zipFile->close(); + } + + public function testAddRecursiveDirWithoutLocalPath() + { + $zipFile = new ZipFile(); + $zipFile->addDirRecursive($this->outputDirname); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, array_keys(self::$files)); + $zipFile->close(); + } + + public function testAddFilesFromIteratorWithIgnoreFiles(){ + $localPath = 'to/project'; + $ignoreFiles = [ + 'Текстовый документ.txt', + 'empty dir/' + ]; + + $directoryIterator = new \DirectoryIterator($this->outputDirname); + $ignoreIterator = new IgnoreFilesFilterIterator($directoryIterator, $ignoreFiles); + + $zipFile = new ZipFile(); + $zipFile->addFilesFromIterator($ignoreIterator, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + '.hidden', + 'text file.txt', + ], $localPath); + $zipFile->close(); + } + + public function testAddFilesFromRecursiveIteratorWithIgnoreFiles(){ + $localPath = 'to/project'; + $ignoreFiles = [ + '.hidden', + 'empty dir2/ещё пустой каталог/', + 'list.txt', + 'category/Pictures/240x320', + ]; + + $directoryIterator = new \RecursiveDirectoryIterator($this->outputDirname); + $ignoreIterator = new IgnoreFilesRecursiveFilterIterator($directoryIterator, $ignoreFiles); + + $zipFile = new ZipFile(); + $zipFile->addFilesFromIterator($ignoreIterator, $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + 'text file.txt', + 'Текстовый документ.txt', + 'empty dir/', + 'catalog/New File', + 'catalog/New File 2', + 'catalog/Empty Dir/', + 'category/Pictures/128x160/Car/01.jpg', + 'category/Pictures/128x160/Car/02.jpg', + ], $localPath); + $zipFile->close(); + } + + /** + * Create archive and add files from glob pattern + */ + public function testAddFilesFromGlob() + { + $localPath = '/'; + + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob($this->outputDirname, '**.{txt,jpg}', $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + 'text file.txt', + 'Текстовый документ.txt', + ], $localPath); + $zipFile->close(); + } + + /** + * Create archive and add recursively files from glob pattern + */ + public function testAddFilesFromGlobRecursive() + { + $localPath = '/'; + + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive($this->outputDirname, '**.{txt,jpg}', $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + 'text file.txt', + 'Текстовый документ.txt', + 'category/list.txt', + 'category/Pictures/128x160/Car/01.jpg', + 'category/Pictures/128x160/Car/02.jpg', + 'category/Pictures/240x320/Car/01.jpg', + 'category/Pictures/240x320/Car/02.jpg', + ], $localPath); + $zipFile->close(); + } + + /** + * Create archive and add files from regex pattern + */ + public function testAddFilesFromRegex() + { + $localPath = 'path'; + + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex($this->outputDirname, '~\.(txt|jpe?g)$~i', $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + 'text file.txt', + 'Текстовый документ.txt', + ], $localPath); + $zipFile->close(); + } + + /** + * Create archive and add files recursively from regex pattern + */ + public function testAddFilesFromRegexRecursive() + { + $localPath = '/'; + + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegexRecursive($this->outputDirname, '~\.(txt|jpe?g)$~i', $localPath); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, [ + 'text file.txt', + 'Текстовый документ.txt', + 'category/list.txt', + 'category/Pictures/128x160/Car/01.jpg', + 'category/Pictures/128x160/Car/02.jpg', + 'category/Pictures/240x320/Car/01.jpg', + 'category/Pictures/240x320/Car/02.jpg', + ], $localPath); + $zipFile->close(); + } + + public function testArrayAccessAddDir() + { + $localPath = 'path/to'; + $iterator = new \RecursiveDirectoryIterator($this->outputDirname); + + $zipFile = new ZipFile(); + $zipFile[$localPath] = $iterator; + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertFilesResult($zipFile, array_keys(self::$files), $localPath); + $zipFile->close(); + } + + +} \ No newline at end of file diff --git a/tests/PhpZip/ZipFileTest.php b/tests/PhpZip/ZipFileTest.php index 714cfea..ff35a81 100644 --- a/tests/PhpZip/ZipFileTest.php +++ b/tests/PhpZip/ZipFileTest.php @@ -11,65 +11,12 @@ use PhpZip\Util\FilesUtil; */ class ZipFileTest extends ZipTestCase { - /** - * @var string - */ - private $outputFilename; - - /** - * Before test - */ - protected function setUp() - { - parent::setUp(); - - $this->outputFilename = sys_get_temp_dir() . '/' . uniqid() . '.zip'; - } - - /** - * After test - */ - protected function tearDown() - { - parent::tearDown(); - - if ($this->outputFilename !== null && file_exists($this->outputFilename)) { - unlink($this->outputFilename); - } - } - - /** - * Test create, open and extract empty archive. - */ - public function testEmptyArchive() - { - $zipFile = new ZipFile(); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectEmptyZip($this->outputFilename); - - $extractPath = sys_get_temp_dir() . '/extract-empty-dir'; - if (is_dir($extractPath)) { - FilesUtil::removeDir($extractPath); - } - self::assertTrue(mkdir($extractPath, 0755, true)); - - $zipFile->openFile($this->outputFilename); - self::assertEquals(count($zipFile), 0); - self::assertEquals($zipFile->count(), 0); - $zipFile->extractTo($extractPath); - $zipFile->close(); - - self::assertTrue(FilesUtil::isEmptyDir($extractPath)); - FilesUtil::removeDir($extractPath); - } /** * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage can't exists */ - public function testCantExistsOpenFile() + public function testOpenFileCantExists() { $zipFile = new ZipFile(); $zipFile->openFile(uniqid()); @@ -79,7 +26,7 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\ZipException * @expectedExceptionMessage can't open */ - public function testCantOpenFile() + public function testOpenFileCantOpen() { self::assertNotFalse(file_put_contents($this->outputFilename, 'content')); self::assertTrue(chmod($this->outputFilename, 0222)); @@ -88,11 +35,33 @@ class ZipFileTest extends ZipTestCase $zipFile->openFile($this->outputFilename); } + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Invalid zip file + */ + public function testOpenFileEmptyFile() + { + self::assertNotFalse(touch($this->outputFilename)); + $zipFile = new ZipFile(); + $zipFile->openFile($this->outputFilename); + } + + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record + */ + public function testOpenFileInvalidZip() + { + self::assertNotFalse(file_put_contents($this->outputFilename, CryptoUtil::randomBytes(255))); + $zipFile = new ZipFile(); + $zipFile->openFile($this->outputFilename); + } + /** * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Data not available */ - public function testOpenFromStringNull() + public function testOpenFromStringNullString() { $zipFile = new ZipFile(); $zipFile->openFromString(null); @@ -102,36 +71,36 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Data not available */ - public function testOpenFromStringEmpty() + public function testOpenFromStringEmptyString() { $zipFile = new ZipFile(); $zipFile->openFromString(""); } + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record + */ + public function testOpenFromStringInvalidZip() + { + $zipFile = new ZipFile(); + $zipFile->openFromString(CryptoUtil::randomBytes(255)); + } + public function testOpenFromString() { $zipFile = new ZipFile(); - $zipFile->addFromString('file', 'content', ZipFile::METHOD_DEFLATED); + $zipFile->addFromString('file', 'content'); + $zipFile['file2'] = 'content 2'; $zipContents = $zipFile->outputAsString(); $zipFile->close(); $zipFile->openFromString($zipContents); + self::assertEquals($zipFile->count(), 2); self::assertTrue(isset($zipFile['file'])); + self::assertTrue(isset($zipFile['file2'])); self::assertEquals($zipFile['file'], 'content'); - $zipFile->close(); - } - - public function testOpenFromStream() - { - $zipFile = new ZipFile(); - $zipFile->addFromString('file', 'content', ZipFile::METHOD_DEFLATED) - ->saveAsFile($this->outputFilename); - $zipFile->close(); - - $handle = fopen($this->outputFilename, 'rb'); - $zipFile->openFromStream($handle); - self::assertTrue(isset($zipFile['file'])); - self::assertEquals($zipFile['file'], 'content'); + self::assertEquals($zipFile['file2'], 'content 2'); $zipFile->close(); } @@ -139,7 +108,17 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Invalid stream resource */ - public function testOpenFromInvalidStream() + public function testOpenFromStreamNullStream() + { + $zipFile = new ZipFile(); + $zipFile->openFromStream(null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid stream resource + */ + public function testOpenFromStreamInvalidResourceType() { $zipFile = new ZipFile(); $zipFile->openFromStream("stream resource"); @@ -162,6 +141,65 @@ class ZipFileTest extends ZipTestCase $zipFile->openFromStream($fp); } + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Invalid zip file + */ + public function testOpenFromStreamEmptyContents() + { + $fp = fopen($this->outputFilename, 'w+b'); + $zipFile = new ZipFile(); + $zipFile->openFromStream($fp); + } + + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Expected Local File Header or (ZIP64) End Of Central Directory Record + */ + public function testOpenFromStreamInvalidZip() + { + $fp = fopen($this->outputFilename, 'w+b'); + fwrite($fp, CryptoUtil::randomBytes(255)); + $zipFile = new ZipFile(); + $zipFile->openFromStream($fp); + } + + public function testOpenFromStream() + { + $zipFile = new ZipFile(); + $zipFile + ->addFromString('file', 'content') + ->saveAsFile($this->outputFilename); + $zipFile->close(); + + $handle = fopen($this->outputFilename, 'rb'); + $zipFile->openFromStream($handle); + self::assertEquals($zipFile->count(), 1); + self::assertTrue(isset($zipFile['file'])); + self::assertEquals($zipFile['file'], 'content'); + $zipFile->close(); + } + + /** + * Test create, open and extract empty archive. + */ + public function testEmptyArchive() + { + $zipFile = new ZipFile(); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectEmptyZip($this->outputFilename); + self::assertTrue(mkdir($this->outputDirname, 0755, true)); + + $zipFile->openFile($this->outputFilename); + self::assertEquals($zipFile->count(), 0); + $zipFile->extractTo($this->outputDirname); + $zipFile->close(); + + self::assertTrue(FilesUtil::isEmptyDir($this->outputDirname)); + } + /** * No modified archive * @@ -169,18 +207,33 @@ class ZipFileTest extends ZipTestCase */ public function testNoModifiedArchive() { + self::assertTrue(mkdir($this->outputDirname, 0755, true)); + + $fileActual = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_actual.zip'; + $fileExpected = $this->outputDirname . DIRECTORY_SEPARATOR . 'file_expected.zip'; + $zipFile = new ZipFile(); - $zipFile->addDir(__DIR__); - $zipFile->saveAsFile($this->outputFilename); + $zipFile->addDirRecursive(__DIR__); + $zipFile->saveAsFile($fileActual); + self::assertCorrectZipArchive($fileActual); $zipFile->close(); - self::assertCorrectZipArchive($this->outputFilename); + $zipFile->openFile($fileActual); + $zipFile->saveAsFile($fileExpected); + self::assertCorrectZipArchive($fileExpected); - $zipFile->openFile($this->outputFilename); - $zipFile->saveAsFile($this->outputFilename); + $zipFileExpected = new ZipFile(); + $zipFileExpected->openFile($fileExpected); + + self::assertEquals($zipFileExpected->count(), $zipFile->count()); + self::assertEquals($zipFileExpected->getListFiles(), $zipFile->getListFiles()); + + foreach ($zipFile as $entryName => $content) { + self::assertEquals($zipFileExpected[$entryName], $content); + } + + $zipFileExpected->close(); $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); } /** @@ -281,170 +334,6 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } - /** - * Create archive and add directory recursively. - */ - public function testAddDirRecursively() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR . "src"; - - $zipFile = new ZipFile(); - $zipFile->addDir($inputDir); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add directory not recursively. - */ - public function testAddDirNotRecursively() - { - $inputDir = dirname(dirname(__DIR__)); - $recursive = false; - - $zipFile = new ZipFile(); - $zipFile->addDir($inputDir, $recursive); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add directory and put files to path. - */ - public function testAddDirAndMoveToPath() - { - $inputDir = __DIR__; - $files = array_slice(scandir($inputDir), 2); - - $recursive = true; - - $zipFile = new ZipFile(); - $moveToPath = 'Library/tests'; - $zipFile->addDir($inputDir, $recursive, $moveToPath); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - - $zipFile->openFile($this->outputFilename); - self::assertEquals(count($zipFile), count($files)); - foreach ($files as $file) { - self::assertTrue(isset($zipFile[$moveToPath . '/' . $file])); - self::assertEquals($zipFile[$moveToPath . '/' . $file], file_get_contents($inputDir . '/' . $file)); - } - $zipFile->close(); - } - - /** - * Create archive and add directory with ignore files list. - */ - public function testAddDirAndIgnoreFiles() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - - $recursive = false; - - $zipFile = new ZipFile(); - $ignoreFiles = ['tests/', '.git/', 'composer.lock', 'vendor/', ".idea/"]; - $moveToPath = 'PhpZip Library'; - $zipFile->addDir($inputDir, $recursive, $moveToPath, $ignoreFiles); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add directory recursively with ignore files list. - */ - public function testAddDirAndIgnoreFilesRecursively() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - - $recursive = true; - - $zipFile = new ZipFile(); - $ignoreFiles = ['tests/', '.git/', 'composer.lock', 'vendor/', ".idea/copyright/"]; - $moveToPath = 'PhpZip Library'; - $zipFile->addDir($inputDir, $recursive, $moveToPath, $ignoreFiles); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add files from glob pattern - */ - public function testAddFilesFromGlob() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - $moveToPath = null; - $recursive = false; - - $zipFile = new ZipFile(); - $zipFile->addFilesFromGlob($inputDir, '**.{php,xml}', $moveToPath, $recursive); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add recursively files from glob pattern - */ - public function testAddFilesFromGlobRecursive() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - $moveToPath = "PhpZip Library"; - $recursive = true; - - $zipFile = new ZipFile(); - $zipFile->addFilesFromGlob($inputDir, '**.{php,xml}', $moveToPath, $recursive); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add files from regex pattern - */ - public function testAddFilesFromRegex() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - $moveToPath = "Test"; - $recursive = false; - - $zipFile = new ZipFile(); - $zipFile->addFilesFromRegex($inputDir, '~\.(xml|php)$~i', $moveToPath, $recursive); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - - /** - * Create archive and add files recursively from regex pattern - */ - public function testAddFilesFromRegexRecursive() - { - $inputDir = dirname(dirname(__DIR__)) . DIRECTORY_SEPARATOR; - $moveToPath = "Test"; - $recursive = true; - - $zipFile = new ZipFile(); - $zipFile->addFilesFromRegex($inputDir, '~\.(xml|php)$~i', $recursive, $moveToPath); - $zipFile->saveAsFile($this->outputFilename); - $zipFile->close(); - - self::assertCorrectZipArchive($this->outputFilename); - } - /** * Rename zip entry name. */ @@ -454,7 +343,7 @@ class ZipFileTest extends ZipTestCase $newName = 'tests/' . $oldName; $zipFile = new ZipFile(); - $zipFile->addDir(__DIR__); + $zipFile->addDirRecursive(__DIR__); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -477,6 +366,60 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage name is null + */ + public function testRenameEntryNull() + { + $zipFile = new ZipFile(); + $zipFile->rename(null, 'new-file'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage name is null + */ + public function testRenameEntryNull2() + { + $zipFile = new ZipFile(); + $zipFile->rename('old-file', null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage is exists + */ + public function testRenameEntryNewEntyExists() + { + $zipFile = new ZipFile(); + $zipFile['file'] = 'content'; + $zipFile['file2'] = 'content 2'; + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + $zipFile = new ZipFile(); + $zipFile->openFile($this->outputFilename); + $zipFile->rename('file2', 'file'); + } + + /** + * @expectedException \PhpZip\Exception\ZipNotFoundEntry + * @expectedExceptionMessage Not found entry + */ + public function testRenameEntryNotFound() + { + $zipFile = new ZipFile(); + $zipFile['file'] = 'content'; + $zipFile['file2'] = 'content 2'; + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + $zipFile = new ZipFile(); + $zipFile->openFile($this->outputFilename); + $zipFile->rename('file2.bak', 'file3'); + } + /** * Delete entry from name. */ @@ -486,7 +429,7 @@ class ZipFileTest extends ZipTestCase $deleteEntryName = 'composer.json'; $zipFile = new ZipFile(); - $zipFile->addDir($inputDir, false); + $zipFile->addDir($inputDir); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -504,6 +447,30 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } + public function testDeleteNewEntry(){ + $zipFile = new ZipFile(); + $zipFile['entry1'] = ''; + $zipFile['entry2'] = ''; + $zipFile->deleteFromName('entry2'); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + $zipFile->openFile($this->outputFilename); + self::assertEquals(sizeof($zipFile), 1); + self::assertTrue(isset($zipFile['entry1'])); + self::assertFalse(isset($zipFile['entry2'])); + $zipFile->close(); + } + + /** + * @expectedException \PhpZip\Exception\ZipNotFoundEntry + * @expectedExceptionMessage Not found entry entry + */ + public function testDeleteFromNameNotFoundEntry(){ + $zipFile = new ZipFile(); + $zipFile->deleteFromName('entry'); + } + /** * Delete zip entries from glob pattern */ @@ -512,7 +479,7 @@ class ZipFileTest extends ZipTestCase $inputDir = dirname(dirname(__DIR__)); $zipFile = new ZipFile(); - $zipFile->addFilesFromGlob($inputDir, '**.{php,xml,json}', '/', true); + $zipFile->addFilesFromGlobRecursive($inputDir, '**.{php,xml,json}', '/'); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -535,7 +502,8 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Glob pattern is empty */ - public function testDeleteFromGlobFailNull(){ + public function testDeleteFromGlobFailNull() + { $zipFile = new ZipFile(); $zipFile->deleteFromGlob(null); } @@ -544,7 +512,8 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Glob pattern is empty */ - public function testDeleteFromGlobFailEmpty(){ + public function testDeleteFromGlobFailEmpty() + { $zipFile = new ZipFile(); $zipFile->deleteFromGlob(''); } @@ -557,7 +526,7 @@ class ZipFileTest extends ZipTestCase $inputDir = dirname(dirname(__DIR__)); $zipFile = new ZipFile(); - $zipFile->addFilesFromRegex($inputDir, '~\.(xml|php|json)$~i', 'Path', true); + $zipFile->addFilesFromRegexRecursive($inputDir, '~\.(xml|php|json)$~i', 'Path'); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -565,6 +534,8 @@ class ZipFileTest extends ZipTestCase $zipFile->openFile($this->outputFilename); $zipFile->deleteFromRegex('~\.(json)$~i'); + $zipFile->addFromString('test.txt', 'content'); + $zipFile->deleteFromRegex('~\.txt$~'); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -572,6 +543,7 @@ class ZipFileTest extends ZipTestCase $zipFile->openFile($this->outputFilename); self::assertFalse(isset($zipFile['Path/composer.json'])); + self::assertFalse(isset($zipFile['Path/test.txt'])); self::assertTrue(isset($zipFile['Path/bootstrap.xml'])); $zipFile->close(); } @@ -580,7 +552,8 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Regex pattern is empty. */ - public function testDeleteFromRegexFailNull(){ + public function testDeleteFromRegexFailNull() + { $zipFile = new ZipFile(); $zipFile->deleteFromRegex(null); } @@ -589,7 +562,8 @@ class ZipFileTest extends ZipTestCase * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage Regex pattern is empty. */ - public function testDeleteFromRegexFailEmpty(){ + public function testDeleteFromRegexFailEmpty() + { $zipFile = new ZipFile(); $zipFile->deleteFromRegex(''); } @@ -600,7 +574,7 @@ class ZipFileTest extends ZipTestCase public function testDeleteAll() { $zipFile = new ZipFile(); - $zipFile->addDir(__DIR__); + $zipFile->addDirRecursive(__DIR__); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -742,6 +716,7 @@ class ZipFileTest extends ZipTestCase * Test zip entry very long comment. * * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Comment too long */ public function testVeryLongEntryComment() { @@ -754,6 +729,16 @@ class ZipFileTest extends ZipTestCase $zipFile->setEntryComment('test', $comment); } + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Not found entry + */ + public function testSetEntryCommentNotFoundEntry() + { + $zipFile = new ZipFile(); + $zipFile->setEntryComment('test', 'comment'); + } + /** * Test all available support compression methods. */ @@ -801,6 +786,25 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9 + */ + public function testSetInvalidCompressionLevel(){ + $zipFile = new ZipFile(); + $zipFile->setCompressionLevel(-2); + } + + /** + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid compression level. Minimum level -1. Maximum level 9 + */ + public function testSetInvalidCompressionLevel2(){ + $zipFile = new ZipFile(); + $zipFile->setCompressionLevel(10); + } + /** * Test extract all files. */ @@ -975,7 +979,7 @@ class ZipFileTest extends ZipTestCase // create encryption password with ZipCrypto $zipFile = new ZipFile(); - $zipFile->addDir(__DIR__); + $zipFile->addDirRecursive(__DIR__); $zipFile->withNewPassword($password, ZipFile::ENCRYPTION_METHOD_TRADITIONAL); $zipFile->saveAsFile($this->outputFilename); $zipFile->close(); @@ -1051,6 +1055,18 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage Invalid encryption method + */ + public function testSetEncryptionMethodInvalid(){ + $zipFile = new ZipFile(); + $encryptionMethod = 9999; + $zipFile->withNewPassword('pass', $encryptionMethod); + $zipFile['entry'] = 'content'; + $zipFile->outputAsString(); + } + /** * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage entryName is null @@ -1216,7 +1232,7 @@ class ZipFileTest extends ZipTestCase /** * @expectedException \PhpZip\Exception\InvalidArgumentException - * @expectedExceptionMessage File is not exists + * @expectedExceptionMessage is not exists */ public function testAddFileCantExists() { @@ -1247,6 +1263,266 @@ class ZipFileTest extends ZipTestCase $zipFile->addFile($this->outputFilename); } + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddDirNullDirname() + { + $zipFile = new ZipFile(); + $zipFile->addDir(null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddDirEmptyDirname() + { + $zipFile = new ZipFile(); + $zipFile->addDir(""); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddDirCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addDir(uniqid()); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddDirRecursiveNullDirname() + { + $zipFile = new ZipFile(); + $zipFile->addDirRecursive(null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddDirRecursiveEmptyDirname() + { + $zipFile = new ZipFile(); + $zipFile->addDirRecursive(""); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddDirRecursiveCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addDirRecursive(uniqid()); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromGlobNull() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob(null, '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromGlobEmpty() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob("", '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddFilesFromGlobCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob("path/to/path", '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage glob pattern empty + */ + public function testAddFilesFromGlobNullPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob(__DIR__, null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage glob pattern empty + */ + public function testAddFilesFromGlobEmptyPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlob(__DIR__, ''); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromGlobRecursiveNull() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive(null, '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromGlobRecursiveEmpty() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive("", '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddFilesFromGlobRecursiveCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive("path/to/path", '*.png'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage glob pattern empty + */ + public function testAddFilesFromGlobRecursiveNullPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive(__DIR__, null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage glob pattern empty + */ + public function testAddFilesFromGlobRecursiveEmptyPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive(__DIR__, ''); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromRegexDirectoryNull() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex(null, '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromRegexDirectoryEmpty() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex("", '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddFilesFromRegexCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex("path/to/path", '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage regex pattern empty + */ + public function testAddFilesFromRegexNullPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex(__DIR__, null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage regex pattern empty + */ + public function testAddFilesFromRegexEmptyPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegex(__DIR__, ''); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromRegexRecursiveDirectoryNull() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegexRecursive(null, '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Input dir empty + */ + public function testAddFilesFromRegexRecursiveEmpty() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegexRecursive("", '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage can't exists + */ + public function testAddFilesFromRegexRecursiveCantExists() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromGlobRecursive("path/to/path", '~\.png$~i'); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage regex pattern empty + */ + public function testAddFilesFromRegexRecursiveNullPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegexRecursive(__DIR__, null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage regex pattern empty + */ + public function testAddFilesFromRegexRecursiveEmptyPattern() + { + $zipFile = new ZipFile(); + $zipFile->addFilesFromRegexRecursive(__DIR__, ''); + } + /** * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage handle is not resource @@ -1361,6 +1637,24 @@ class ZipFileTest extends ZipTestCase $zipFile->close(); } + public function testArrayAccessAddFile() + { + $entryName = 'path/to/file.dat'; + + $zipFile = new ZipFile(); + $zipFile[$entryName] = new \SplFileInfo(__FILE__); + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + self::assertCorrectZipArchive($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertEquals(sizeof($zipFile), 1); + self::assertTrue(isset($zipFile[$entryName])); + self::assertEquals($zipFile[$entryName], file_get_contents(__FILE__)); + $zipFile->close(); + } + /** * @expectedException \PhpZip\Exception\InvalidArgumentException * @expectedExceptionMessage DirName empty @@ -1381,6 +1675,97 @@ class ZipFileTest extends ZipTestCase $zipFile->addEmptyDir(""); } + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Output filename is empty. + */ + public function testOutputAsAttachmentNullName() + { + $zipFile = new ZipFile(); + $zipFile->outputAsAttachment(null); + } + + /** + * @expectedException \PhpZip\Exception\InvalidArgumentException + * @expectedExceptionMessage Output filename is empty. + */ + public function testOutputAsAttachmentEmptyName() + { + $zipFile = new ZipFile(); + $zipFile->outputAsAttachment(''); + } + + /** + * @expectedException \PhpZip\Exception\ZipNotFoundEntry + * @expectedExceptionMessage Zip entry bad entry name not found + */ + public function testNotFoundEntry(){ + $zipFile = new ZipFile(); + $zipFile['bad entry name']; + } + + /** + * Test rewrite input file. + */ + public function testRewriteFile() + { + $zipFile = new ZipFile(); + $zipFile['file'] = 'content'; + $zipFile['file2'] = 'content2'; + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + $md5file = md5_file($this->outputFilename); + + $zipFile->openFile($this->outputFilename); + self::assertEquals(count($zipFile), 2); + self::assertTrue(isset($zipFile['file'])); + self::assertTrue(isset($zipFile['file2'])); + $zipFile['file3'] = 'content3'; + self::assertEquals(count($zipFile), 2); + $zipFile = $zipFile->rewrite(); + self::assertEquals(count($zipFile), 3); + self::assertTrue(isset($zipFile['file'])); + self::assertTrue(isset($zipFile['file2'])); + self::assertTrue(isset($zipFile['file3'])); + $zipFile->close(); + + self::assertNotEquals(md5_file($this->outputFilename), $md5file); + } + + /** + * Test rewrite for string. + */ + public function testRewriteString() + { + $zipFile = new ZipFile(); + $zipFile['file'] = 'content'; + $zipFile['file2'] = 'content2'; + $zipFile->saveAsFile($this->outputFilename); + $zipFile->close(); + + $zipFile->openFromString(file_get_contents($this->outputFilename)); + self::assertEquals(count($zipFile), 2); + self::assertTrue(isset($zipFile['file'])); + self::assertTrue(isset($zipFile['file2'])); + $zipFile['file3'] = 'content3'; + $zipFile = $zipFile->rewrite(); + self::assertEquals(count($zipFile), 3); + self::assertTrue(isset($zipFile['file'])); + self::assertTrue(isset($zipFile['file2'])); + self::assertTrue(isset($zipFile['file3'])); + $zipFile->close(); + } + + /** + * @expectedException \PhpZip\Exception\ZipException + * @expectedExceptionMessage input stream is null + */ + public function testRewriteNullStream(){ + $zipFile = new ZipFile(); + $zipFile->rewrite(); + } + /** * Test zip alignment. */ diff --git a/tests/PhpZip/ZipTestCase.php b/tests/PhpZip/ZipTestCase.php index 9cd9dc2..8fcb8d8 100644 --- a/tests/PhpZip/ZipTestCase.php +++ b/tests/PhpZip/ZipTestCase.php @@ -1,12 +1,51 @@ outputFilename = sys_get_temp_dir() . '/' . $id . '.zip'; + $this->outputDirname = sys_get_temp_dir() . '/' . $id; + } + + /** + * After test + */ + protected function tearDown() + { + parent::tearDown(); + + if ($this->outputFilename !== null && file_exists($this->outputFilename)) { + unlink($this->outputFilename); + } + if ($this->outputDirname !== null && is_dir($this->outputDirname)) { + FilesUtil::removeDir($this->outputDirname); + } + } + /** * Assert correct zip archive. *