init
This commit is contained in:
309
vendor/nelexa/zip/src/IO/Stream/ZipEntryStreamWrapper.php
vendored
Normal file
309
vendor/nelexa/zip/src/IO/Stream/ZipEntryStreamWrapper.php
vendored
Normal file
@@ -0,0 +1,309 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
* This file is part of the nelexa/zip package.
|
||||
* (c) Ne-Lexa <https://github.com/Ne-Lexa/php-zip>
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace PhpZip\IO\Stream;
|
||||
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\Model\ZipEntry;
|
||||
|
||||
/**
|
||||
* The class provides stream reuse functionality.
|
||||
*
|
||||
* Stream will not be closed at {@see fclose}.
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper
|
||||
*/
|
||||
final class ZipEntryStreamWrapper
|
||||
{
|
||||
/** @var string the registered protocol */
|
||||
public const PROTOCOL = 'zipentry';
|
||||
|
||||
/** @var resource */
|
||||
public $context;
|
||||
|
||||
/** @var resource */
|
||||
private $fp;
|
||||
|
||||
public static function register(): bool
|
||||
{
|
||||
$protocol = self::PROTOCOL;
|
||||
|
||||
if (!\in_array($protocol, stream_get_wrappers(), true)) {
|
||||
if (!stream_wrapper_register($protocol, self::class)) {
|
||||
throw new \RuntimeException("Failed to register '{$protocol}://' protocol");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function unregister(): void
|
||||
{
|
||||
stream_wrapper_unregister(self::PROTOCOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return resource
|
||||
*/
|
||||
public static function wrap(ZipEntry $entry)
|
||||
{
|
||||
self::register();
|
||||
|
||||
$context = stream_context_create(
|
||||
[
|
||||
self::PROTOCOL => [
|
||||
'entry' => $entry,
|
||||
],
|
||||
]
|
||||
);
|
||||
|
||||
$uri = self::PROTOCOL . '://' . $entry->getName();
|
||||
$fp = fopen($uri, 'r+b', false, $context);
|
||||
|
||||
if ($fp === false) {
|
||||
throw new \RuntimeException('Error open ' . $uri);
|
||||
}
|
||||
|
||||
return $fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens file or URL.
|
||||
*
|
||||
* This method is called immediately after the wrapper is
|
||||
* initialized (f.e. by {@see fopen()} and {@see file_get_contents()}).
|
||||
*
|
||||
* @param string $path specifies the URL that was passed to
|
||||
* the original function
|
||||
* @param string $mode the mode used to open the file, as detailed
|
||||
* for {@see fopen()}
|
||||
* @param int $options Holds additional flags set by the streams
|
||||
* API. It can hold one or more of the
|
||||
* following values OR'd together.
|
||||
* @param string|null $opened_path if the path is opened successfully, and
|
||||
* STREAM_USE_PATH is set in options,
|
||||
* opened_path should be set to the
|
||||
* full path of the file/resource that
|
||||
* was actually opened
|
||||
*
|
||||
* @throws ZipException
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-open
|
||||
*/
|
||||
public function stream_open(string $path, string $mode, int $options, ?string &$opened_path): bool
|
||||
{
|
||||
if ($this->context === null) {
|
||||
throw new \RuntimeException('stream context is null');
|
||||
}
|
||||
$streamOptions = stream_context_get_options($this->context);
|
||||
|
||||
if (!isset($streamOptions[self::PROTOCOL]['entry'])) {
|
||||
throw new \RuntimeException('no stream option ["' . self::PROTOCOL . '"]["entry"]');
|
||||
}
|
||||
$zipEntry = $streamOptions[self::PROTOCOL]['entry'];
|
||||
|
||||
if (!$zipEntry instanceof ZipEntry) {
|
||||
throw new \RuntimeException('invalid stream context');
|
||||
}
|
||||
|
||||
$zipData = $zipEntry->getData();
|
||||
|
||||
if ($zipData === null) {
|
||||
throw new ZipException(sprintf('No data for zip entry "%s"', $zipEntry->getName()));
|
||||
}
|
||||
$this->fp = $zipData->getDataAsStream();
|
||||
|
||||
return $this->fp !== false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from stream.
|
||||
*
|
||||
* This method is called in response to {@see fread()} and {@see fgets()}.
|
||||
*
|
||||
* Note: Remember to update the read/write position of the stream
|
||||
* (by the number of bytes that were successfully read).
|
||||
*
|
||||
* @param int $count how many bytes of data from the current
|
||||
* position should be returned
|
||||
*
|
||||
* @return false|string If there are less than count bytes available,
|
||||
* return as many as are available. If no more data
|
||||
* is available, return either FALSE or
|
||||
* an empty string.
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-read
|
||||
*/
|
||||
public function stream_read(int $count)
|
||||
{
|
||||
return fread($this->fp, $count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seeks to specific location in a stream.
|
||||
*
|
||||
* This method is called in response to {@see fseek()}.
|
||||
* The read/write position of the stream should be updated according
|
||||
* to the offset and whence.
|
||||
*
|
||||
* @param int $offset the stream offset to seek to
|
||||
* @param int $whence Possible values:
|
||||
* {@see \SEEK_SET} - Set position equal to offset bytes.
|
||||
* {@see \SEEK_CUR} - Set position to current location plus offset.
|
||||
* {@see \SEEK_END} - Set position to end-of-file plus offset.
|
||||
*
|
||||
* @return bool return TRUE if the position was updated, FALSE otherwise
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-seek
|
||||
*/
|
||||
public function stream_seek(int $offset, int $whence = \SEEK_SET): bool
|
||||
{
|
||||
return fseek($this->fp, $offset, $whence) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the current position of a stream.
|
||||
*
|
||||
* This method is called in response to {@see fseek()} to determine
|
||||
* the current position.
|
||||
*
|
||||
* @return int should return the current position of the stream
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-tell
|
||||
*/
|
||||
public function stream_tell(): int
|
||||
{
|
||||
$pos = ftell($this->fp);
|
||||
|
||||
if ($pos === false) {
|
||||
throw new \RuntimeException('Cannot get stream position.');
|
||||
}
|
||||
|
||||
return $pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests for end-of-file on a file pointer.
|
||||
*
|
||||
* This method is called in response to {@see feof()}.
|
||||
*
|
||||
* @return bool should return TRUE if the read/write position is at
|
||||
* the end of the stream and if no more data is available
|
||||
* to be read, or FALSE otherwise
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-eof
|
||||
*/
|
||||
public function stream_eof(): bool
|
||||
{
|
||||
return feof($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve information about a file resource.
|
||||
*
|
||||
* This method is called in response to {@see fstat()}.
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-stat
|
||||
* @see https://www.php.net/stat
|
||||
* @see https://www.php.net/fstat
|
||||
*/
|
||||
public function stream_stat(): array
|
||||
{
|
||||
return fstat($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the output.
|
||||
*
|
||||
* This method is called in response to {@see fflush()} and when the
|
||||
* stream is being closed while any unflushed data has been written to
|
||||
* it before.
|
||||
* If you have cached data in your stream but not yet stored it into
|
||||
* the underlying storage, you should do so now.
|
||||
*
|
||||
* @return bool should return TRUE if the cached data was successfully
|
||||
* stored (or if there was no data to store), or FALSE
|
||||
* if the data could not be stored
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-flush
|
||||
*/
|
||||
public function stream_flush(): bool
|
||||
{
|
||||
return fflush($this->fp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate stream.
|
||||
*
|
||||
* Will respond to truncation, e.g., through {@see ftruncate()}.
|
||||
*
|
||||
* @param int $newSize the new size
|
||||
*
|
||||
* @return bool returns TRUE on success or FALSE on failure
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-truncate
|
||||
*/
|
||||
public function stream_truncate(int $newSize): bool
|
||||
{
|
||||
return ftruncate($this->fp, $newSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to stream.
|
||||
*
|
||||
* This method is called in response to {@see fwrite().}
|
||||
*
|
||||
* Note: Remember to update the current position of the stream by
|
||||
* number of bytes that were successfully written.
|
||||
*
|
||||
* @param string $data should be stored into the underlying stream
|
||||
*
|
||||
* @return int should return the number of bytes that were successfully stored, or 0 if none could be stored
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-write
|
||||
*/
|
||||
public function stream_write(string $data): int
|
||||
{
|
||||
$bytes = fwrite($this->fp, $data);
|
||||
|
||||
return $bytes === false ? 0 : $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the underlaying resource.
|
||||
*
|
||||
* This method is called in response to {@see stream_select()}.
|
||||
*
|
||||
* @param int $cast_as can be {@see STREAM_CAST_FOR_SELECT} when {@see stream_select()}
|
||||
* is callingstream_cast() or {@see STREAM_CAST_AS_STREAM} when
|
||||
* stream_cast() is called for other uses
|
||||
*
|
||||
* @return resource
|
||||
*/
|
||||
public function stream_cast(int $cast_as)
|
||||
{
|
||||
return $this->fp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a resource.
|
||||
*
|
||||
* This method is called in response to {@see fclose()}.
|
||||
* All resources that were locked, or allocated, by the wrapper should be released.
|
||||
*
|
||||
* @see https://www.php.net/streamwrapper.stream-close
|
||||
*/
|
||||
public function stream_close(): void
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user