Fix tests for Zip streaming

This commit is contained in:
Arno DUBOIS
2023-05-26 19:33:21 +00:00
parent 88a1e6f8c2
commit 41d77394ad
8 changed files with 355 additions and 340 deletions

View File

@@ -68,7 +68,8 @@ return [
'zip_downloads' => env('ZIP_DOWNLOADS', true),
/**
* Compress Zip using Deflate
* Compress Zip using Deflate. The main drawback of enabling this option is that
* the file size cannot be estimated, and it can also prevent the resuming of the download.
*
* Default value: false
*/

View File

@@ -3,7 +3,8 @@
/**
* @copyright Copyright (c) 2015 Matthew Weier O'Phinney (https://mwop.net)
* @license http://opensource.org/licenses/BSD-2-Clause BSD-2-Clause
* @link https://github.com/phly/psr7examples/blob/master/src/CallbackStream.php
*
* @see https://github.com/phly/psr7examples/blob/master/src/CallbackStream.php
*/
namespace App;
@@ -20,39 +21,25 @@ use Psr\Http\Message\StreamInterface;
*/
class CallbackStream implements StreamInterface
{
/**
* @var callable|null
*/
/** @var callable|null */
private $callback;
/**
* Whether the callback has been previously invoked.
*
* @var bool
*/
/** Whether the callback has been previously invoked. */
private bool $called = false;
/**
* @param callable $callback The callback function that echos the body content
*/
/** @param callable $callback The callback function that echos the body content */
public function __construct(callable $callback)
{
$this->callback = $callback;
}
/**
* @return string
*/
/** @return string */
public function __toString()
{
return '';
}
/**
* Closes the stream and any underlying resources.
*
* @return void
*/
/** Closes the stream and any underlying resources. */
public function close()
{
}
@@ -74,7 +61,7 @@ class CallbackStream implements StreamInterface
/**
* Get the size of the stream if known.
*
* @return int|null Returns the size in bytes if known, or null if unknown.
* @return int|null returns the size in bytes if known, or null if unknown
*/
public function getSize()
{
@@ -82,9 +69,8 @@ class CallbackStream implements StreamInterface
}
/**
* Returns the current position of the file read/write pointer
* Returns the current position of the file read/write pointer.
*
* @throws \RuntimeException on error.
* @return int Position of the file pointer
*/
public function tell()
@@ -115,18 +101,16 @@ class CallbackStream implements StreamInterface
/**
* Seek to a position in the stream.
*
* @link http://www.php.net/manual/en/function.fseek.php
* @see http://www.php.net/manual/en/function.fseek.php
*
* @param int $offset Stream offset
* @param int $whence Specifies how the cursor position will be calculated
* based on the seek offset. Valid values are identical to the built-in
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
* offset bytes SEEK_CUR: Set position to current location plus offset
* SEEK_END: Set position to end-of-stream plus offset.
* @throws \RuntimeException on failure.
*
* @return void
* based on the seek offset. Valid values are identical to the built-in
* PHP $whence values for `fseek()`. SEEK_SET: Set position equal to
* offset bytes SEEK_CUR: Set position to current location plus offset
* SEEK_END: Set position to end-of-stream plus offset.
*/
public function seek($offset, $whence = SEEK_SET)
public function seek($offset, $whence = SEEK_SET): void
{
}
@@ -136,8 +120,7 @@ class CallbackStream implements StreamInterface
* If the stream is not seekable, this method will raise an exception;
* otherwise, it will perform a seek(0).
*
* @throws \RuntimeException on failure.
* @link http://www.php.net/manual/en/function.fseek.php
* @see http://www.php.net/manual/en/function.fseek.php
* @see seek()
*
* @return bool
@@ -160,9 +143,9 @@ class CallbackStream implements StreamInterface
/**
* Write data to the stream.
*
* @param string $string The string that is to be written.
* @throws \RuntimeException on failure.
* @return int Returns the number of bytes written to the stream.
* @param string $string the string that is to be written
*
* @return int returns the number of bytes written to the stream
*/
public function write($string)
{
@@ -183,15 +166,13 @@ class CallbackStream implements StreamInterface
* Read data from the stream.
*
* @param int $length Read up to $length bytes from the object and return them.
* Fewer than $length bytes may be returned if underlying stream call returns fewer bytes.
* Fewer than $length bytes may be returned if underlying stream call returns fewer bytes.
*
* @throws \RuntimeException if an error occurs.
*
* @return string Returns the data read from the stream, or an empty string if no bytes are available.
* @return string returns the data read from the stream, or an empty string if no bytes are available
*/
public function read($length)
{
if ($this->called || !$this->callback) {
if ($this->called || ! $this->callback) {
return '';
}
@@ -204,9 +185,7 @@ class CallbackStream implements StreamInterface
}
/**
* Returns the remaining contents in a string
*
* @throws \RuntimeException if unable to read or an error occurs while reading.
* Returns the remaining contents in a string.
*
* @return string
*/
@@ -221,11 +200,13 @@ class CallbackStream implements StreamInterface
* The keys returned are identical to the keys returned from PHP's
* stream_get_meta_data() function.
*
* @link http://php.net/manual/en/function.stream-get-meta-data.php
* @param string $key Specific metadata to retrieve.
* @see http://php.net/manual/en/function.stream-get-meta-data.php
*
* @param string $key specific metadata to retrieve
*
* @return array|mixed|null Returns an associative array if no key is
* provided. Returns a specific key value if a key is provided and the
* value is found, or null if the key is not found.
* provided. Returns a specific key value if a key is provided and the
* value is found, or null if the key is not found.
*/
public function getMetadata($key = null)
{
@@ -235,4 +216,4 @@ class CallbackStream implements StreamInterface
return null;
}
}
}

View File

@@ -1,33 +0,0 @@
<?php
namespace App;
class TemporaryFile
{
/** @var string Path to the temporary file */
private string $path;
/** Create a new TemporaryFile object. */
public function __construct(string $dir, string $prefix = '')
{
$this->path = (string) tempnam($dir, $prefix);
}
/** Destroy this TemporaryFile object. */
public function __destruct()
{
unlink($this->path);
}
/** Get the path to the temporary file. */
public function __toString(): string
{
return $this->path;
}
/** Get the raw contents of the file. */
public function getContents(): string
{
return (string) file_get_contents($this->path);
}
}

View File

@@ -42,6 +42,7 @@
"phpstan/phpstan": "^1.0",
"psy/psysh": "^0.12.0",
"symfony/var-dumper": "^6.0",
"timeweb/phpstan-enum": "^3.1",
"yoast/phpunit-polyfills": "^2.0"
},
"suggest": {

531
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -39,3 +39,4 @@ parameters:
includes:
- phpstan-baseline.neon
- phpstan-ignores.neon
- app/vendor/timeweb/phpstan-enum/extension.neon

View File

@@ -17,7 +17,6 @@ class ZipControllerTest extends TestCase
{
$controller = new ZipController(
$this->config,
$this->cache,
new Finder,
$this->container->get(TranslatorInterface::class)
);
@@ -30,16 +29,13 @@ class ZipControllerTest extends TestCase
$this->assertInstanceOf(ResponseInterface::class, $response);
$this->assertEquals(200, $response->getStatusCode());
$this->assertEquals('application/zip', finfo_buffer(
finfo_open(), (string) $response->getBody(), FILEINFO_MIME_TYPE
));
$this->assertEquals('application/zip', $response->getHeader('Content-Type')[0]);
}
public function test_it_returns_a_404_error_when_not_found(): void
{
$controller = new ZipController(
$this->config,
$this->cache,
new Finder,
$this->container->get(TranslatorInterface::class)
);
@@ -59,7 +55,6 @@ class ZipControllerTest extends TestCase
$this->container->set('zip_downloads', false);
$controller = new ZipController(
$this->config,
$this->cache,
new Finder,
$this->container->get(TranslatorInterface::class)
);

View File

@@ -1,38 +0,0 @@
<?php
namespace Tests;
use App\TemporaryFile;
/** @covers \App\TemporaryFile */
class TemporaryFileTest extends TestCase
{
public function test_it_can_create_a_temporary_file(): void
{
$tempFile = new TemporaryFile($this->filePath('app/cache'));
$this->assertFileExists((string) $tempFile);
}
public function test_it_can_write_to_and_read_from_a_temporary_file(): void
{
$tempFile = new TemporaryFile($this->filePath('app/cache'));
$this->assertFileIsReadable((string) $tempFile);
$this->assertFileIsWritable((string) $tempFile);
file_put_contents((string) $tempFile, 'Test file; please ignore');
$this->assertEquals('Test file; please ignore', $tempFile->getContents());
}
public function test_it_removes_the_underlying_file_on_destruction(): void
{
$tempFile = new TemporaryFile($this->filePath('app/cache'));
$filePath = (string) $tempFile;
unset($tempFile);
$this->assertFalse(is_file($filePath));
}
}