Bladeren bron

issue #8 - Support inline Content-Disposition and empty output filename.

Ne-Lexa 8 jaren geleden
bovenliggende
commit
e62e51efb5
4 gewijzigde bestanden met toevoegingen van 69 en 75 verwijderingen
  1. 15 2
      phpunit.xml
  2. 40 28
      src/PhpZip/ZipFile.php
  3. 10 9
      src/PhpZip/ZipFileInterface.php
  4. 4 36
      tests/PhpZip/ZipFileTest.php

+ 15 - 2
phpunit.xml

@@ -1,10 +1,23 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<phpunit bootstrap="./vendor/autoload.php" colors="true">
+
+<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
+         backupGlobals="false"
+         colors="true"
+         bootstrap="vendor/autoload.php">
+    <php>
+        <ini name="error_reporting" value="-1"/>
+    </php>
 
     <testsuites>
         <testsuite name="PhpZip test suite">
-            <directory>./tests</directory>
+            <directory>tests</directory>
         </testsuite>
     </testsuites>
 
+    <filter>
+        <whitelist>
+            <directory>src</directory>
+        </whitelist>
+    </filter>
 </phpunit>

+ 40 - 28
src/PhpZip/ZipFile.php

@@ -1226,61 +1226,64 @@ class ZipFile implements ZipFileInterface
      * Output .ZIP archive as attachment.
      * Die after output.
      *
-     * @param string $outputFilename
-     * @param string|null $mimeType
+     * @param string $outputFilename Output filename
+     * @param string|null $mimeType Mime-Type
+     * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
      * @throws InvalidArgumentException
      */
-    public function outputAsAttachment($outputFilename, $mimeType = null)
+    public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true)
     {
         $outputFilename = (string)$outputFilename;
-        if (strlen($outputFilename) === 0) {
-            throw new InvalidArgumentException("Output filename is empty.");
-        }
-        if (empty($mimeType) || !is_string($mimeType)) {
+
+        if (empty($mimeType) || !is_string($mimeType) && !empty($outputFilename)) {
             $ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
 
             if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
                 $mimeType = self::$defaultMimeTypes[$ext];
-            } else {
-                $mimeType = self::$defaultMimeTypes['zip'];
             }
         }
-        $outputFilename = basename($outputFilename);
+        if (empty($mimeType)) {
+            $mimeType = self::$defaultMimeTypes['zip'];
+        }
 
         $content = $this->outputAsString();
         $this->close();
 
+        $headerContentDisposition = 'Content-Disposition: ' . ($attachment ? 'attachment' : 'inline');
+        if (!empty($outputFilename)) {
+            $headerContentDisposition .= '; filename="' . basename($outputFilename) . '"';
+        }
+
+        header($headerContentDisposition);
         header("Content-Type: " . $mimeType);
-        header('Content-Disposition: attachment; filename="' . $outputFilename . '"');
         header("Content-Length: " . strlen($content));
         exit($content);
     }
 
     /**
-     * Output .ZIP archive as PSR-Message Response.
+     * Output .ZIP archive as PSR-7 Response.
      *
-     * @param ResponseInterface $response
-     * @param string $outputFilename
-     * @param string|null $mimeType
+     * @param ResponseInterface $response Instance PSR-7 Response
+     * @param string $outputFilename Output filename
+     * @param string|null $mimeType Mime-Type
+     * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
      * @return ResponseInterface
      * @throws InvalidArgumentException
      */
-    public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null)
+    public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true)
     {
         $outputFilename = (string)$outputFilename;
-        if (strlen($outputFilename) === 0) {
-            throw new InvalidArgumentException("Output filename is empty.");
-        }
-        if (empty($mimeType) || !is_string($mimeType)) {
+
+        if (empty($mimeType) || !is_string($mimeType) && !empty($outputFilename)) {
             $ext = strtolower(pathinfo($outputFilename, PATHINFO_EXTENSION));
 
             if (!empty($ext) && isset(self::$defaultMimeTypes[$ext])) {
                 $mimeType = self::$defaultMimeTypes[$ext];
-            } else {
-                $mimeType = self::$defaultMimeTypes['zip'];
             }
         }
-        $outputFilename = basename($outputFilename);
+        if (empty($mimeType)) {
+            $mimeType = self::$defaultMimeTypes['zip'];
+        }
 
         if (!($handle = fopen('php://memory', 'w+b'))) {
             throw new InvalidArgumentException("Memory can not open from write.");
@@ -1288,9 +1291,14 @@ class ZipFile implements ZipFileInterface
         $this->writeZipToStream($handle);
         rewind($handle);
 
+        $contentDispositionValue = ($attachment ? 'attachment' : 'inline');
+        if (!empty($outputFilename)) {
+            $contentDispositionValue .= '; filename="' . basename($outputFilename) . '"';
+        }
+
         $stream = new ResponseStream($handle);
         $response->withHeader('Content-Type', $mimeType);
-        $response->withHeader('Content-Disposition', 'attachment; filename="' . $outputFilename . '"');
+        $response->withHeader('Content-Disposition', $contentDispositionValue);
         $response->withHeader('Content-Length', $stream->getSize());
         $response->withBody($stream);
         return $response;
@@ -1348,11 +1356,15 @@ class ZipFile implements ZipFileInterface
         $content = $this->outputAsString();
         $this->close();
         if ('plainfile' === $meta['wrapper_type']) {
-            if (file_put_contents($meta['uri'], $content) === false) {
-                throw new ZipException("Can not overwrite the zip file in the {$meta['uri']} file.");
+            /**
+             * @var resource $uri
+             */
+            $uri = $meta['uri'];
+            if (file_put_contents($uri, $content) === false) {
+                throw new ZipException("Can not overwrite the zip file in the {$uri} file.");
             }
-            if (!($handle = @fopen($meta['uri'], 'rb'))) {
-                throw new ZipException("File {$meta['uri']} can't open.");
+            if (!($handle = @fopen($uri, 'rb'))) {
+                throw new ZipException("File {$uri} can't open.");
             }
             return $this->openFromStream($handle);
         }

+ 10 - 9
src/PhpZip/ZipFileInterface.php

@@ -592,22 +592,23 @@ interface ZipFileInterface extends \Countable, \ArrayAccess, \Iterator
      * Output .ZIP archive as attachment.
      * Die after output.
      *
-     * @param string $outputFilename
-     * @param string|null $mimeType
-     * @throws InvalidArgumentException
+     * @param string $outputFilename Output filename
+     * @param string|null $mimeType Mime-Type
+     * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
      */
-    public function outputAsAttachment($outputFilename, $mimeType = null);
+    public function outputAsAttachment($outputFilename, $mimeType = null, $attachment = true);
 
     /**
-     * Output .ZIP archive as PSR-Message Response.
+     * Output .ZIP archive as PSR-7 Response.
      *
-     * @param ResponseInterface $response
-     * @param string $outputFilename
-     * @param string|null $mimeType
+     * @param ResponseInterface $response Instance PSR-7 Response
+     * @param string $outputFilename Output filename
+     * @param string|null $mimeType Mime-Type
+     * @param bool $attachment Http Header 'Content-Disposition' if true then attachment otherwise inline
      * @return ResponseInterface
      * @throws InvalidArgumentException
      */
-    public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null);
+    public function outputAsResponse(ResponseInterface $response, $outputFilename, $mimeType = null, $attachment = true);
 
     /**
      * Returns the zip archive as a string.

+ 4 - 36
tests/PhpZip/ZipFileTest.php

@@ -30,7 +30,7 @@ class ZipFileTest extends ZipTestCase
      */
     public function testOpenFileCantOpen()
     {
-        if (0 === posix_getuid()){
+        if (0 === posix_getuid()) {
             $this->markTestSkipped('Skip the test for a user with root privileges');
         }
 
@@ -1007,7 +1007,7 @@ class ZipFileTest extends ZipTestCase
      */
     public function testExtractFail3()
     {
-        if (0 === posix_getuid()){
+        if (0 === posix_getuid()) {
             $this->markTestSkipped('Skip the test for a user with root privileges');
         }
 
@@ -1213,7 +1213,7 @@ class ZipFileTest extends ZipTestCase
      */
     public function testAddFileCantOpen()
     {
-        if (0 === posix_getuid()){
+        if (0 === posix_getuid()) {
             $this->markTestSkipped('Skip the test for a user with root privileges');
         }
 
@@ -1501,7 +1501,7 @@ class ZipFileTest extends ZipTestCase
      */
     public function testSaveAsFileNotWritable()
     {
-        if (0 === posix_getuid()){
+        if (0 === posix_getuid()) {
             $this->markTestSkipped('Skip the test for a user with root privileges');
         }
 
@@ -1662,26 +1662,6 @@ 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
@@ -1916,18 +1896,6 @@ class ZipFileTest extends ZipTestCase
         $this->assertInstanceOf(ResponseInterface::class, $response);
     }
 
-    /**
-     * @expectedException \PhpZip\Exception\InvalidArgumentException
-     * @expectedExceptionMessage Output filename is empty.
-     */
-    public function testInvalidPsrResponse()
-    {
-        $zipFile = new ZipFile();
-        $zipFile['file'] = 'content';
-        $response = $this->getMock(ResponseInterface::class);
-        $zipFile->outputAsResponse($response, '');
-    }
-
     public function testCompressionLevel()
     {
         $zipFile = new ZipFile();