From f5f03a5b2bc9380af071e23f9cc601be41bce38f Mon Sep 17 00:00:00 2001 From: Ivan Lanin Date: Fri, 18 Apr 2014 01:58:03 +0700 Subject: [PATCH] Emulate \ZipArchive::extractTo for PCLZip --- samples/Sample_07_TemplateCloneRow.php | 3 +- samples/Sample_23_TemplateBlock.php | 3 +- src/PhpWord/Element/Image.php | 4 +- src/PhpWord/Reader/Word2007.php | 1 - src/PhpWord/Shared/ZipArchive.php | 96 +++++++++++-------- src/PhpWord/Writer/HTML.php | 4 +- src/PhpWord/Writer/ODText.php | 1 - src/PhpWord/Writer/PDF/AbstractRenderer.php | 2 +- src/PhpWord/Writer/Word2007.php | 11 ++- src/PhpWord/Writer/Word2007/WebSettings.php | 2 - tests/PhpWord/Tests/Shared/ZipArchiveTest.php | 87 +++++++++-------- 11 files changed, 118 insertions(+), 96 deletions(-) diff --git a/samples/Sample_07_TemplateCloneRow.php b/samples/Sample_07_TemplateCloneRow.php index 0e79e69f..899bc82b 100755 --- a/samples/Sample_07_TemplateCloneRow.php +++ b/samples/Sample_07_TemplateCloneRow.php @@ -60,8 +60,7 @@ echo date('H:i:s'), " Write to Word2007 format", EOL; $document->saveAs($name); rename($name, "results/{$name}"); -$writers = array('Word2007' => 'docx'); -echo getEndingNotes($writers); +echo getEndingNotes(array('Word2007' => 'docx')); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/samples/Sample_23_TemplateBlock.php b/samples/Sample_23_TemplateBlock.php index d0856ec2..8ee8fc6d 100644 --- a/samples/Sample_23_TemplateBlock.php +++ b/samples/Sample_23_TemplateBlock.php @@ -18,8 +18,7 @@ echo date('H:i:s'), " Write to Word2007 format", EOL; $document->saveAs($name); rename($name, "results/{$name}"); -$writers = array('Word2007' => 'docx'); -echo getEndingNotes($writers); +echo getEndingNotes(array('Word2007' => 'docx')); if (!CLI) { include_once 'Sample_Footer.php'; } diff --git a/src/PhpWord/Element/Image.php b/src/PhpWord/Element/Image.php index b9eeb23e..a2a33793 100755 --- a/src/PhpWord/Element/Image.php +++ b/src/PhpWord/Element/Image.php @@ -9,6 +9,7 @@ namespace PhpOffice\PhpWord\Element; +use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Exception\InvalidImageException; use PhpOffice\PhpWord\Exception\UnsupportedImageTypeException; use PhpOffice\PhpWord\Style\Image as ImageStyle; @@ -283,7 +284,8 @@ class Image extends AbstractElement list($zipFilename, $imageFilename) = explode('#', $source); $tempFilename = tempnam(sys_get_temp_dir(), 'PHPWordImage'); - $zip = new \ZipArchive(); + $zipClass = Settings::getZipClass(); + $zip = new $zipClass(); if ($zip->open($zipFilename) !== false) { if ($zip->locateName($imageFilename)) { $imageContent = $zip->getFromName($imageFilename); diff --git a/src/PhpWord/Reader/Word2007.php b/src/PhpWord/Reader/Word2007.php index c28daf7b..8cb081cd 100644 --- a/src/PhpWord/Reader/Word2007.php +++ b/src/PhpWord/Reader/Word2007.php @@ -12,7 +12,6 @@ namespace PhpOffice\PhpWord\Reader; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Settings; use PhpOffice\PhpWord\Footnote; -use PhpOffice\PhpWord\Endnotes; use PhpOffice\PhpWord\DocumentProperties; use PhpOffice\PhpWord\Shared\XMLReader; use PhpOffice\PhpWord\Element\Section; diff --git a/src/PhpWord/Shared/ZipArchive.php b/src/PhpWord/Shared/ZipArchive.php index 5485ea14..65c54e8d 100644 --- a/src/PhpWord/Shared/ZipArchive.php +++ b/src/PhpWord/Shared/ZipArchive.php @@ -11,9 +11,9 @@ namespace PhpOffice\PhpWord\Shared; use PhpOffice\PhpWord\Exception\Exception; +// PCLZIP needs the temp path to end in a back slash // @codeCoverageIgnoreStart if (!defined('PCLZIP_TEMPORARY_DIR')) { - // PCLZIP needs the temp path to end in a back slash define('PCLZIP_TEMPORARY_DIR', sys_get_temp_dir() . '/'); } require_once 'PCLZip/pclzip.lib.php'; @@ -67,7 +67,7 @@ class ZipArchive } /** - * Close this zip archive + * Close this zip archive (emulate \ZipArchive) * * @codeCoverageIgnore */ @@ -76,7 +76,7 @@ class ZipArchive } /** - * Add a new file to the zip archive. + * Add a new file to the zip archive (emulate \ZipArchive) * * @param string $filename Directory/Name of the file to add to the zip archive * @param string $localname Directory/Name of the file added to the zip @@ -104,15 +104,11 @@ class ZipArchive $localnameParts["dirname"] ); - if ($res == 0) { - throw new Exception("Error zipping files : " . $this->zip->errorInfo(true)); - } - - return true; + return ($res == 0) ? false : true; } /** - * Add a new file to the zip archive from a string of raw data. + * Add a new file to the zip archive from a string of raw data (emulate \ZipArchive) * * @param string $localname Directory/Name of the file to add to the zip archive * @param string $contents String of data to add to the zip archive @@ -134,21 +130,18 @@ class ZipArchive PCLZIP_OPT_ADD_PATH, $filenameParts["dirname"] ); - if ($res == 0) { - throw new Exception("Error zipping files : " . $this->zip->errorInfo(true)); - } // Remove temp file - unlink($this->tempDir . '/' . $filenameParts["basename"]); + @unlink($this->tempDir . '/' . $filenameParts["basename"]); - return true; + return ($res == 0) ? false : true; } /** - * Find if given file name exist in archive (Emulate ZipArchive locateName()) + * Returns the index of the entry in the archive (emulate \ZipArchive) * - * @param string $filename Filename for the file in zip archive - * @return boolean + * @param string $filename Filename for the file in zip archive + * @return integer|false */ public function locateName($filename) { @@ -163,42 +156,25 @@ class ZipArchive } } - return ($listIndex > -1); + return ($listIndex > -1) ? $listIndex : false; } /** - * Extract file from archive by given file name (Emulate ZipArchive getFromName()) + * Extract file from archive by given file name (emulate \ZipArchive) * * @param string $filename Filename for the file in zip archive - * @return string $contents File string contents + * @return string|false $contents File string contents */ public function getFromName($filename) { - $list = $this->zip->listContent(); - $listCount = count($list); - $listIndex = -1; - $contents = null; + $listIndex = $this->locateName($filename); + $contents = false; - for ($i = 0; $i < $listCount; ++$i) { - if (strtolower($list[$i]["filename"]) == strtolower($filename) || - strtolower($list[$i]["stored_filename"]) == strtolower($filename)) { - $listIndex = $i; - break; - } - } - - if ($listIndex != -1) { + if ($listIndex !== false) { $extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING); } else { $filename = substr($filename, 1); - $listIndex = -1; - for ($i = 0; $i < $listCount; ++$i) { - if (strtolower($list[$i]["filename"]) == strtolower($filename) || - strtolower($list[$i]["stored_filename"]) == strtolower($filename)) { - $listIndex = $i; - break; - } - } + $listIndex = $this->locateName($filename); $extracted = $this->zip->extractByIndex($listIndex, PCLZIP_OPT_EXTRACT_AS_STRING); } if ((is_array($extracted)) && ($extracted != 0)) { @@ -209,10 +185,11 @@ class ZipArchive } /** - * Returns the name of an entry using its index + * Returns the name of an entry using its index (emulate \ZipArchive) * * @param integer $index * @return string|false + * @since 0.10.0 */ public function getNameIndex($index) { @@ -223,4 +200,39 @@ class ZipArchive return false; } } + + /** + * Extract the archive contents (emulate \ZipArchive) + * + * @param string $destination + * @param string|array $entries + * @return boolean + * @since 0.10.0 + */ + public function extractTo($destination, $entries = null) + { + if (!is_dir($destination)) { + return false; + } + + // Extract all files + if (is_null($entries)) { + $result = $this->zip->extract(PCLZIP_OPT_PATH, $destination); + return ($result > 0) ? true : false; + } + + // Extract by entries + if (!is_array($entries)) { + $entries = array($entries); + } + foreach ($entries as $entry) { + $entryIndex = $this->locateName($entry); + $result = $this->zip->extractByIndex($entryIndex, PCLZIP_OPT_PATH, $destination); + if ($result <= 0) { + return false; + } + } + + return true; + } } diff --git a/src/PhpWord/Writer/HTML.php b/src/PhpWord/Writer/HTML.php index aee3f27a..31a7ca61 100644 --- a/src/PhpWord/Writer/HTML.php +++ b/src/PhpWord/Writer/HTML.php @@ -714,7 +714,9 @@ class HTML extends AbstractWriter implements WriterInterface if ($element->getSourceType() == Image::SOURCE_ARCHIVE) { $source = substr($source, 6); list($zipFilename, $imageFilename) = explode('#', $source); - $zip = new \ZipArchive(); + + $zipClass = \PhpOffice\PhpWord\Settings::getZipClass(); + $zip = new $zipClass(); if ($zip->open($zipFilename) !== false) { if ($zip->locateName($imageFilename)) { $zip->extractTo($this->getTempDir(), $imageFilename); diff --git a/src/PhpWord/Writer/ODText.php b/src/PhpWord/Writer/ODText.php index be1fe459..b050ef44 100755 --- a/src/PhpWord/Writer/ODText.php +++ b/src/PhpWord/Writer/ODText.php @@ -50,7 +50,6 @@ class ODText extends AbstractWriter implements WriterInterface * * @param string $filename * @throws \PhpOffice\PhpWord\Exception\Exception - * @todo Not in \ZipArchive::CM_STORE mode */ public function save($filename = null) { diff --git a/src/PhpWord/Writer/PDF/AbstractRenderer.php b/src/PhpWord/Writer/PDF/AbstractRenderer.php index 64f196e9..354e2ed1 100644 --- a/src/PhpWord/Writer/PDF/AbstractRenderer.php +++ b/src/PhpWord/Writer/PDF/AbstractRenderer.php @@ -109,7 +109,7 @@ abstract class AbstractRenderer extends \PhpOffice\PhpWord\Writer\HTML /** * Set Paper Size * - * @param string $pValue Paper size = PAPERSIZE_A4 + * @param int $pValue Paper size = PAPERSIZE_A4 * @return self */ public function setPaperSize($pValue = 9) diff --git a/src/PhpWord/Writer/Word2007.php b/src/PhpWord/Writer/Word2007.php index a046408c..44df6ccc 100755 --- a/src/PhpWord/Writer/Word2007.php +++ b/src/PhpWord/Writer/Word2007.php @@ -9,20 +9,20 @@ namespace PhpOffice\PhpWord\Writer; -use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\PhpWord; use PhpOffice\PhpWord\Media; use PhpOffice\PhpWord\Element\Section; +use PhpOffice\PhpWord\Exception\Exception; use PhpOffice\PhpWord\Writer\Word2007\ContentTypes; -use PhpOffice\PhpWord\Writer\Word2007\Rels; use PhpOffice\PhpWord\Writer\Word2007\DocProps; use PhpOffice\PhpWord\Writer\Word2007\Document; use PhpOffice\PhpWord\Writer\Word2007\Footer; +use PhpOffice\PhpWord\Writer\Word2007\Header; use PhpOffice\PhpWord\Writer\Word2007\Notes; use PhpOffice\PhpWord\Writer\Word2007\Numbering; -use PhpOffice\PhpWord\Writer\Word2007\Header; -use PhpOffice\PhpWord\Writer\Word2007\Styles; +use PhpOffice\PhpWord\Writer\Word2007\Rels; use PhpOffice\PhpWord\Writer\Word2007\Settings; +use PhpOffice\PhpWord\Writer\Word2007\Styles; use PhpOffice\PhpWord\Writer\Word2007\WebSettings; /** @@ -199,7 +199,8 @@ class Word2007 extends AbstractWriter implements WriterInterface $source = substr($source, 6); list($zipFilename, $imageFilename) = explode('#', $source); - $zip = new \ZipArchive(); + $zipClass = \PhpOffice\PhpWord\Settings::getZipClass(); + $zip = new $zipClass(); if ($zip->open($zipFilename) !== false) { if ($zip->locateName($imageFilename)) { $zip->extractTo($this->getTempDir(), $imageFilename); diff --git a/src/PhpWord/Writer/Word2007/WebSettings.php b/src/PhpWord/Writer/Word2007/WebSettings.php index 3edd1ac1..f52be909 100644 --- a/src/PhpWord/Writer/Word2007/WebSettings.php +++ b/src/PhpWord/Writer/Word2007/WebSettings.php @@ -9,8 +9,6 @@ namespace PhpOffice\PhpWord\Writer\Word2007; -use PhpOffice\PhpWord\Shared\XMLWriter; - /** * Word2007 web settings part writer */ diff --git a/tests/PhpWord/Tests/Shared/ZipArchiveTest.php b/tests/PhpWord/Tests/Shared/ZipArchiveTest.php index 40bdde68..2e45fcf8 100644 --- a/tests/PhpWord/Tests/Shared/ZipArchiveTest.php +++ b/tests/PhpWord/Tests/Shared/ZipArchiveTest.php @@ -14,62 +14,73 @@ use PhpOffice\PhpWord\Shared\ZipArchive; /** * Test class for PhpOffice\PhpWord\Shared\ZipArchive * + * @coversDefaultClass \PhpOffice\PhpWord\Shared\ZipArchive * @runTestsInSeparateProcesses */ class ZipArchiveTest extends \PHPUnit_Framework_TestCase { /** - * Test add from file and string + * Test all methods + * + * @covers :: */ - public function testAdd() + public function testAllMethods() { + // Preparation $existingFile = __DIR__ . "/../_files/documents/sheet.xls"; $zipFile = __DIR__ . "/../_files/documents/ziptest.zip"; - $object = new ZipArchive(); + $destination1 = __DIR__ . "/../_files/extract1"; + $destination2 = __DIR__ . "/../_files/extract2"; + $destination3 = __DIR__ . "/../_files/extract3"; + @mkdir($destination1); + @mkdir($destination2); + @mkdir($destination3); + + $object = new ZipArchive(); $object->open($zipFile); $object->addFile($existingFile, 'xls/new.xls'); $object->addFromString('content/string.txt', 'Test'); + $object->close(); - $this->assertTrue($object->locateName('xls/new.xls')); - $this->assertEquals('Test', $object->getFromName('content/string.txt')); - $this->assertEquals('Test', $object->getFromName('/content/string.txt')); - - unlink($zipFile); - } - - /** - * Test find if a given name exists in the archive - */ - public function testLocate() - { - $existingFile = __DIR__ . "/../_files/documents/sheet.xls"; - $zipFile = __DIR__ . "/../_files/documents/ziptest.zip"; - $object = new ZipArchive(); - $object->open($zipFile); - $object->addFile($existingFile, 'xls/new.xls'); - $object->addFromString('content/string.txt', 'Test'); - - $this->assertEquals(1, $object->locateName('content/string.txt')); + // Run tests + $this->assertEquals(0, $object->locateName('xls/new.xls')); $this->assertFalse($object->locateName('blablabla')); - unlink($zipFile); - } - - /** - * Test returns the name of an entry using its index - */ - public function testNameIndex() - { - $existingFile = __DIR__ . "/../_files/documents/sheet.xls"; - $zipFile = __DIR__ . "/../_files/documents/ziptest.zip"; - $object = new ZipArchive(); - $object->open($zipFile); - $object->addFile($existingFile, 'xls/new.xls'); - $object->addFromString('content/string.txt', 'Test'); + $this->assertEquals('Test', $object->getFromName('content/string.txt')); + $this->assertEquals('Test', $object->getFromName('/content/string.txt')); $this->assertFalse($object->getNameIndex(-1)); $this->assertEquals('content/string.txt', $object->getNameIndex(1)); - unlink($zipFile); + $this->assertFalse($object->extractTo('blablabla')); + $this->assertTrue($object->extractTo($destination1)); + $this->assertTrue($object->extractTo($destination2, 'xls/new.xls')); + $this->assertFalse($object->extractTo($destination2, 'blablabla')); + + // Cleanup + $this->deleteDir($destination1); + $this->deleteDir($destination2); + $this->deleteDir($destination3); + @unlink($zipFile); + } + + /** + * Delete directory + * + * @param string $dir + */ + private function deleteDir($dir) + { + foreach (scandir($dir) as $file) { + if ($file === '.' || $file === '..') { + continue; + } elseif (is_file($dir . "/" . $file)) { + unlink($dir . "/" . $file); + } elseif (is_dir($dir . "/" . $file)) { + $this->deleteDir($dir . "/" . $file); + } + } + + rmdir($dir); } }