| 
					
				 | 
			
			
				@@ -0,0 +1,361 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+<?php 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * This file is part of Zippy. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * (c) Alchemy <info@alchemy.fr> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * For the full copyright and license information, please view the LICENSE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * file that was distributed with this source code. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+namespace Alchemy\Zippy\Adapter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Adapter\Resource\ResourceInterface; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Adapter\Resource\ZipArchiveResource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Adapter\VersionProbe\ZipExtensionVersionProbe; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Archive\Archive; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Archive\Member; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Exception\NotSupportedException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Exception\RuntimeException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Exception\InvalidArgumentException; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Resource\Resource as ZippyResource; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+use Alchemy\Zippy\Resource\ResourceManager; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * ZipExtensionAdapter allows you to create and extract files from archives 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * using PHP Zip extension 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ * @see http://www.php.net/manual/en/book.zip.php 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ZipExtensionAdapter extends AbstractAdapter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private $errorCodesMapping = array( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_EXISTS => "File already exists", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_INCONS => "Zip archive inconsistent", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_INVAL  => "Invalid argument", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_MEMORY => "Malloc failure", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_NOENT  => "No such file", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_NOZIP  => "Not a zip archive", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_OPEN   => "Can't open file", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_READ   => "Read error", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        \ZipArchive::ER_SEEK   => "Seek error" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public function __construct(ResourceManager $manager) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        parent::__construct($manager); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->probe = new ZipExtensionVersionProbe(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doListMembers(ResourceInterface $resource) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $members = array(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        for ($i = 0; $i < $resource->getResource()->numFiles; $i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $stat = $resource->getResource()->statIndex($i); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $members[] = new Member( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $this, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $stat['name'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $stat['size'], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                new \DateTime('@' . $stat['mtime']), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                0 === strlen($resource->getResource()->getFromIndex($i, 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $members; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static function getName() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return 'zip-extension'; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doExtract(ResourceInterface $resource, $to) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $this->extractMembers($resource, null, $to); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doExtractMembers(ResourceInterface $resource, $members, $to, $overwrite = false) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (null === $to) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // if no destination is given, will extract to zip current folder 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $to = dirname(realpath($resource->getResource()->filename)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!is_dir($to)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException(sprintf("%s is not a directory", $to)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!is_writable($to)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException(sprintf("%s is not writable", $to)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (null !== $members) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $membersTemp = (array) $members; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (empty($membersTemp)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidArgumentException("no members provided"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $members = array(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // allows $members to be an array of strings or array of Members 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach ($membersTemp as $member) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if ($member instanceof Member) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $member = $member->getLocation(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if ($resource->getResource()->locateName($member) === false) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    throw new InvalidArgumentException(sprintf('%s is not in the zip file', $member)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if ($overwrite == false) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (file_exists($member)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        throw new RuntimeException('Target file ' . $member . ' already exists.'); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $members[] = $member; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!$resource->getResource()->extractTo($to, $members)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException(sprintf('Unable to extract archive : %s', $resource->getResource()->getStatusString())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new \SplFileInfo($to); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doRemove(ResourceInterface $resource, $files) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $files = (array) $files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (empty($files)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException("no files provided"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // either remove all files or none in case of error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        foreach ($files as $file) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if ($resource->getResource()->locateName($file) === false) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource->getResource()->unchangeAll(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new InvalidArgumentException(sprintf('%s is not in the zip file', $file)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (!$resource->getResource()->deleteName($file)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource->getResource()->unchangeAll(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                throw new RuntimeException(sprintf('unable to remove %s', $file)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->flush($resource->getResource()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doAdd(ResourceInterface $resource, $files, $recursive) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $files = (array) $files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (empty($files)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $resource->getResource()->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException("no files provided"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->addEntries($resource, $files, $recursive); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @inheritdoc 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function doCreate($path, $files, $recursive) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $files = (array) $files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (empty($files)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new NotSupportedException("Cannot create an empty zip"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $resource = $this->getResource($path, \ZipArchive::CREATE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->addEntries($resource, $files, $recursive); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new Archive($resource, $this, $this->manager); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Returns a new instance of the invoked adapter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @return AbstractAdapter 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @throws RuntimeException In case object could not be instanciated 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public static function newInstance() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new ZipExtensionAdapter(ResourceManager::create()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    protected function createResource($path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return $this->getResource($path, \ZipArchive::CHECKCONS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private function getResource($path, $mode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $zip = new \ZipArchive(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $res = $zip->open($path, $mode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ($res !== true) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new RuntimeException($this->errorCodesMapping[$res]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return new ZipArchiveResource($zip); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private function addEntries(ResourceInterface $zipResource, array $files, $recursive) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $stack = new \SplStack(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $error = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $cwd = getcwd(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $collection = $this->manager->handle($cwd, $files); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->chdir($collection->getContext()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $adapter = $this; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        try { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $collection->forAll(function($i, ZippyResource $resource) use ($zipResource, $stack, $recursive, $adapter) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $adapter->checkReadability($zipResource->getResource(), $resource->getTarget()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (is_dir($resource->getTarget())) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if ($recursive) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        $stack->push($resource->getTarget() . ((substr($resource->getTarget(), -1) === DIRECTORY_SEPARATOR) ? '' : DIRECTORY_SEPARATOR)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        $adapter->addEmptyDir($zipResource->getResource(), $resource->getTarget()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $adapter->addFileToZip($zipResource->getResource(), $resource->getTarget()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // recursively add dirs 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            while (!$stack->isEmpty()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $dir = $stack->pop(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // removes . and .. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                $files = array_diff(scandir($dir), array(".", "..")); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (count($files) > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    foreach ($files as $file) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        $file = $dir . $file; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        $this->checkReadability($zipResource->getResource(), $file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (is_dir($file)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            $stack->push($file . DIRECTORY_SEPARATOR); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            $this->addFileToZip($zipResource->getResource(), $file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    $this->addEmptyDir($zipResource->getResource(), $dir); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $this->flush($zipResource->getResource()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $this->manager->cleanup($collection); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } catch (\Exception $e) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $error = $e; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $this->chdir($cwd); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if ($error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw $error; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Is public for PHP 5.3 compatibility, should be private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param \ZipArchive $zip 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param string      $file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public function checkReadability(\ZipArchive $zip, $file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!is_readable($file)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->unchangeAll(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new InvalidArgumentException(sprintf('could not read %s', $file)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Is public for PHP 5.3 compatibility, should be private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param \ZipArchive $zip 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param string      $file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public function addFileToZip(\ZipArchive $zip, $file) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!$zip->addFile($file)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->unchangeAll(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new RuntimeException(sprintf('unable to add %s to the zip file', $file)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Is public for PHP 5.3 compatibility, should be private 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param \ZipArchive $zip 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param string      $dir 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    public function addEmptyDir(\ZipArchive $zip, $dir) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!$zip->addEmptyDir($dir)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->unchangeAll(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            $zip->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            throw new RuntimeException(sprintf('unable to add %s to the zip file', $dir)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * Flushes changes to the archive 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     * @param \ZipArchive $zip 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    private function flush(\ZipArchive $zip) // flush changes by reopening the file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $path = $zip->filename; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $zip->close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        $zip->open($path, \ZipArchive::CHECKCONS); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |