[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 3 namespace Box\Spout\Writer\Common\Helper; 4 5 /** 6 * Class ZipHelper 7 * This class provides helper functions to create zip files 8 * 9 * @package Box\Spout\Writer\Common\Helper 10 */ 11 class ZipHelper 12 { 13 const ZIP_EXTENSION = '.zip'; 14 15 /** Controls what to do when trying to add an existing file */ 16 const EXISTING_FILES_SKIP = 'skip'; 17 const EXISTING_FILES_OVERWRITE = 'overwrite'; 18 19 /** @var string Path of the folder where the zip file will be created */ 20 protected $tmpFolderPath; 21 22 /** @var \ZipArchive The ZipArchive instance */ 23 protected $zip; 24 25 /** 26 * @param string $tmpFolderPath Path of the temp folder where the zip file will be created 27 */ 28 public function __construct($tmpFolderPath) 29 { 30 $this->tmpFolderPath = $tmpFolderPath; 31 } 32 33 /** 34 * Returns the already created ZipArchive instance or 35 * creates one if none exists. 36 * 37 * @return \ZipArchive 38 */ 39 protected function createOrGetZip() 40 { 41 if (!isset($this->zip)) { 42 $this->zip = new \ZipArchive(); 43 $zipFilePath = $this->getZipFilePath(); 44 45 $this->zip->open($zipFilePath, \ZipArchive::CREATE|\ZipArchive::OVERWRITE); 46 } 47 48 return $this->zip; 49 } 50 51 /** 52 * @return string Path where the zip file of the given folder will be created 53 */ 54 public function getZipFilePath() 55 { 56 return $this->tmpFolderPath . self::ZIP_EXTENSION; 57 } 58 59 /** 60 * Adds the given file, located under the given root folder to the archive. 61 * The file will be compressed. 62 * 63 * Example of use: 64 * addFileToArchive('/tmp/xlsx/foo', 'bar/baz.xml'); 65 * => will add the file located at '/tmp/xlsx/foo/bar/baz.xml' in the archive, but only as 'bar/baz.xml' 66 * 67 * @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree. 68 * @param string $localFilePath Path of the file to be added, under the root folder 69 * @param string|void $existingFileMode Controls what to do when trying to add an existing file 70 * @return void 71 */ 72 public function addFileToArchive($rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) 73 { 74 $this->addFileToArchiveWithCompressionMethod( 75 $rootFolderPath, 76 $localFilePath, 77 $existingFileMode, 78 \ZipArchive::CM_DEFAULT 79 ); 80 } 81 82 /** 83 * Adds the given file, located under the given root folder to the archive. 84 * The file will NOT be compressed. 85 * 86 * Example of use: 87 * addUncompressedFileToArchive('/tmp/xlsx/foo', 'bar/baz.xml'); 88 * => will add the file located at '/tmp/xlsx/foo/bar/baz.xml' in the archive, but only as 'bar/baz.xml' 89 * 90 * @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree. 91 * @param string $localFilePath Path of the file to be added, under the root folder 92 * @param string|void $existingFileMode Controls what to do when trying to add an existing file 93 * @return void 94 */ 95 public function addUncompressedFileToArchive($rootFolderPath, $localFilePath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) 96 { 97 $this->addFileToArchiveWithCompressionMethod( 98 $rootFolderPath, 99 $localFilePath, 100 $existingFileMode, 101 \ZipArchive::CM_STORE 102 ); 103 } 104 105 /** 106 * Adds the given file, located under the given root folder to the archive. 107 * The file will NOT be compressed. 108 * 109 * Example of use: 110 * addUncompressedFileToArchive('/tmp/xlsx/foo', 'bar/baz.xml'); 111 * => will add the file located at '/tmp/xlsx/foo/bar/baz.xml' in the archive, but only as 'bar/baz.xml' 112 * 113 * @param string $rootFolderPath Path of the root folder that will be ignored in the archive tree. 114 * @param string $localFilePath Path of the file to be added, under the root folder 115 * @param string $existingFileMode Controls what to do when trying to add an existing file 116 * @param int $compressionMethod The compression method 117 * @return void 118 */ 119 protected function addFileToArchiveWithCompressionMethod($rootFolderPath, $localFilePath, $existingFileMode, $compressionMethod) 120 { 121 $zip = $this->createOrGetZip(); 122 123 if (!$this->shouldSkipFile($zip, $localFilePath, $existingFileMode)) { 124 $normalizedFullFilePath = $this->getNormalizedRealPath($rootFolderPath . '/' . $localFilePath); 125 $zip->addFile($normalizedFullFilePath, $localFilePath); 126 127 if (self::canChooseCompressionMethod()) { 128 $zip->setCompressionName($localFilePath, $compressionMethod); 129 } 130 } 131 } 132 133 /** 134 * @return bool Whether it is possible to choose the desired compression method to be used 135 */ 136 public static function canChooseCompressionMethod() 137 { 138 // setCompressionName() is a PHP7+ method... 139 return (method_exists(new \ZipArchive(), 'setCompressionName')); 140 } 141 142 /** 143 * @param string $folderPath Path to the folder to be zipped 144 * @param string|void $existingFileMode Controls what to do when trying to add an existing file 145 * @return void 146 */ 147 public function addFolderToArchive($folderPath, $existingFileMode = self::EXISTING_FILES_OVERWRITE) 148 { 149 $zip = $this->createOrGetZip(); 150 151 $folderRealPath = $this->getNormalizedRealPath($folderPath) . '/'; 152 $itemIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($folderPath, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); 153 154 foreach ($itemIterator as $itemInfo) { 155 $itemRealPath = $this->getNormalizedRealPath($itemInfo->getPathname()); 156 $itemLocalPath = str_replace($folderRealPath, '', $itemRealPath); 157 158 if ($itemInfo->isFile() && !$this->shouldSkipFile($zip, $itemLocalPath, $existingFileMode)) { 159 $zip->addFile($itemRealPath, $itemLocalPath); 160 } 161 } 162 } 163 164 /** 165 * @param \ZipArchive $zip 166 * @param string $itemLocalPath 167 * @param string $existingFileMode 168 * @return bool Whether the file should be added to the archive or skipped 169 */ 170 protected function shouldSkipFile($zip, $itemLocalPath, $existingFileMode) 171 { 172 // Skip files if: 173 // - EXISTING_FILES_SKIP mode chosen 174 // - File already exists in the archive 175 return ($existingFileMode === self::EXISTING_FILES_SKIP && $zip->locateName($itemLocalPath) !== false); 176 } 177 178 /** 179 * Returns canonicalized absolute pathname, containing only forward slashes. 180 * 181 * @param string $path Path to normalize 182 * @return string Normalized and canonicalized path 183 */ 184 protected function getNormalizedRealPath($path) 185 { 186 $realPath = realpath($path); 187 return str_replace(DIRECTORY_SEPARATOR, '/', $realPath); 188 } 189 190 /** 191 * Closes the archive and copies it into the given stream 192 * 193 * @param resource $streamPointer Pointer to the stream to copy the zip 194 * @return void 195 */ 196 public function closeArchiveAndCopyToStream($streamPointer) 197 { 198 $zip = $this->createOrGetZip(); 199 $zip->close(); 200 unset($this->zip); 201 202 $this->copyZipToStream($streamPointer); 203 } 204 205 /** 206 * Streams the contents of the zip file into the given stream 207 * 208 * @param resource $pointer Pointer to the stream to copy the zip 209 * @return void 210 */ 211 protected function copyZipToStream($pointer) 212 { 213 $zipFilePointer = fopen($this->getZipFilePath(), 'r'); 214 stream_copy_to_stream($zipFilePointer, $pointer); 215 fclose($zipFilePointer); 216 } 217 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |