first commit
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
use _JchOptimizeVendor\Interop\Container\ContainerInterface;
|
||||
// phpcs:disable WebimpressCodingStandard.PHP.CorrectClassNameCase
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\AdapterPluginManager;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\Factory\InvokableFactory;
|
||||
|
||||
final class AdapterPluginManagerDelegatorFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container, string $name, callable $callback): AdapterPluginManager
|
||||
{
|
||||
$pluginManager = $callback();
|
||||
\assert($pluginManager instanceof AdapterPluginManager);
|
||||
$pluginManager->configure(['factories' => [Filesystem::class => InvokableFactory::class], 'aliases' => ['filesystem' => Filesystem::class, 'Filesystem' => Filesystem::class]]);
|
||||
|
||||
return $pluginManager;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\AdapterPluginManager;
|
||||
|
||||
final class ConfigProvider
|
||||
{
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function __invoke(): array
|
||||
{
|
||||
return ['dependencies' => $this->getServiceDependencies()];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function getServiceDependencies(): array
|
||||
{
|
||||
return ['delegators' => [AdapterPluginManager::class => [AdapterPluginManagerDelegatorFactory::class]]];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\RuntimeException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
final class MetadataException extends RuntimeException
|
||||
{
|
||||
public const METADATA_ATIME = Filesystem::METADATA_ATIME;
|
||||
public const METADATA_CTIME = Filesystem::METADATA_CTIME;
|
||||
public const METADATA_MTIME = Filesystem::METADATA_MTIME;
|
||||
public const METADATA_FILESIZE = Filesystem::METADATA_FILESIZE;
|
||||
|
||||
/** @var \ErrorException */
|
||||
private $error;
|
||||
|
||||
/**
|
||||
* @psalm-param MetadataException::METADATA_* $metadata
|
||||
*/
|
||||
public function __construct(string $metadata, \ErrorException $error)
|
||||
{
|
||||
parent::__construct(\sprintf('Could not detected metadata "%s"', $metadata), 0, $error);
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
public function getErrorSeverity(): int
|
||||
{
|
||||
return $this->error->getSeverity();
|
||||
}
|
||||
|
||||
public function getErrorMessage(): string
|
||||
{
|
||||
return $this->error->getMessage();
|
||||
}
|
||||
|
||||
public function getErrorFile(): string
|
||||
{
|
||||
return $this->error->getFile();
|
||||
}
|
||||
|
||||
public function getErrorLine(): int
|
||||
{
|
||||
return $this->error->getLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\RuntimeException;
|
||||
|
||||
final class UnlinkException extends RuntimeException
|
||||
{
|
||||
/** @var \ErrorException */
|
||||
private $error;
|
||||
|
||||
public function __construct(string $path, \ErrorException $error)
|
||||
{
|
||||
parent::__construct(\sprintf('Error unlinking file \'%s\'; file still exists', $path), 0, $error);
|
||||
$this->error = $error;
|
||||
}
|
||||
|
||||
public function getErrorSeverity(): int
|
||||
{
|
||||
return $this->error->getSeverity();
|
||||
}
|
||||
|
||||
public function getErrorMessage(): string
|
||||
{
|
||||
return $this->error->getMessage();
|
||||
}
|
||||
|
||||
public function getErrorFile(): string
|
||||
{
|
||||
return $this->error->getFile();
|
||||
}
|
||||
|
||||
public function getErrorLine(): int
|
||||
{
|
||||
return $this->error->getLine();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\RuntimeException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception\MetadataException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception\UnlinkException;
|
||||
|
||||
interface FilesystemInteractionInterface
|
||||
{
|
||||
/**
|
||||
* @throws UnlinkException if the file could not be deleted and still exists
|
||||
*/
|
||||
public function delete(string $file): bool;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function write(string $file, string $contents, ?int $umask, ?int $permissions, bool $lock, bool $block, ?bool &$wouldBlock): bool;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function read(string $file, bool $lock, bool $block, ?bool &$wouldBlock): string;
|
||||
|
||||
public function exists(string $file): bool;
|
||||
|
||||
/**
|
||||
* @throws MetadataException
|
||||
*/
|
||||
public function lastModifiedTime(string $file): int;
|
||||
|
||||
/**
|
||||
* @throws MetadataException
|
||||
*/
|
||||
public function lastAccessedTime(string $file): int;
|
||||
|
||||
/**
|
||||
* @throws MetadataException
|
||||
*/
|
||||
public function createdTime(string $file): int;
|
||||
|
||||
/**
|
||||
* @throws MetadataException
|
||||
*/
|
||||
public function filesize(string $file): int;
|
||||
|
||||
public function clearStatCache(): void;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function availableBytes(string $directory): int;
|
||||
|
||||
/**
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function totalBytes(string $directory): int;
|
||||
|
||||
public function touch(string $file): bool;
|
||||
|
||||
/**
|
||||
* @return int the previous set umask
|
||||
*/
|
||||
public function umask(int $umask): int;
|
||||
|
||||
public function createDirectory(string $directory, int $permissions, bool $recursive, ?int $umask = null): void;
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\RuntimeException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception\MetadataException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem\Exception\UnlinkException;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\ErrorHandler;
|
||||
|
||||
use function file_get_contents;
|
||||
use function file_put_contents;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class LocalFilesystemInteraction implements FilesystemInteractionInterface
|
||||
{
|
||||
public function delete(string $file): bool
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$res = @\unlink($file);
|
||||
$err = ErrorHandler::stop();
|
||||
if (!$res && \file_exists($file)) {
|
||||
\assert(null !== $err);
|
||||
|
||||
throw new UnlinkException($file, $err);
|
||||
}
|
||||
|
||||
return \true;
|
||||
}
|
||||
|
||||
public function write(string $file, string $contents, ?int $umask, ?int $permissions, bool $lock, bool $block, ?bool &$wouldBlock): bool
|
||||
{
|
||||
$nonBlocking = $lock && $block;
|
||||
$wouldBlock = null;
|
||||
if (null !== $umask && null !== $permissions) {
|
||||
$permissions &= ~$umask;
|
||||
}
|
||||
ErrorHandler::start();
|
||||
// if locking and non blocking is enabled -> file_put_contents can't used
|
||||
if ($lock && $nonBlocking) {
|
||||
$umask = null !== $umask ? \umask($umask) : null;
|
||||
$fp = \fopen($file, 'cb');
|
||||
if ($umask) {
|
||||
\umask($umask);
|
||||
}
|
||||
if (!$fp) {
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error opening file '{$file}'", 0, $err);
|
||||
}
|
||||
if (null !== $permissions && !\chmod($file, $permissions)) {
|
||||
\fclose($fp);
|
||||
$oct = \decoct($permissions);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
|
||||
}
|
||||
$wouldblockFromFileLock = null;
|
||||
if (!\flock($fp, \LOCK_EX | \LOCK_NB, $wouldblockFromFileLock)) {
|
||||
\fclose($fp);
|
||||
$err = ErrorHandler::stop();
|
||||
if ($wouldblockFromFileLock) {
|
||||
$wouldBlock = \true;
|
||||
|
||||
return \false;
|
||||
}
|
||||
|
||||
throw new RuntimeException("Error locking file '{$file}'", 0, $err);
|
||||
}
|
||||
if (\false === \fwrite($fp, $contents)) {
|
||||
\flock($fp, \LOCK_UN);
|
||||
\fclose($fp);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error writing file '{$file}'", 0, $err);
|
||||
}
|
||||
if (!\ftruncate($fp, \strlen($contents))) {
|
||||
\flock($fp, \LOCK_UN);
|
||||
\fclose($fp);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error truncating file '{$file}'", 0, $err);
|
||||
}
|
||||
\flock($fp, \LOCK_UN);
|
||||
\fclose($fp);
|
||||
// else -> file_put_contents can be used
|
||||
} else {
|
||||
$flags = 0;
|
||||
if ($lock) {
|
||||
$flags |= \LOCK_EX;
|
||||
}
|
||||
$umask = null !== $umask ? \umask($umask) : null;
|
||||
$rs = \file_put_contents($file, $contents, $flags);
|
||||
if ($umask) {
|
||||
\umask($umask);
|
||||
}
|
||||
if (\false === $rs) {
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error writing file '{$file}'", 0, $err);
|
||||
}
|
||||
if (null !== $permissions && !\chmod($file, $permissions)) {
|
||||
$oct = \decoct($permissions);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("chmod('{$file}', 0{$oct}) failed", 0, $err);
|
||||
}
|
||||
}
|
||||
ErrorHandler::stop();
|
||||
|
||||
return \true;
|
||||
}
|
||||
|
||||
public function read(string $file, bool $lock, bool $block, ?bool &$wouldBlock): string
|
||||
{
|
||||
$wouldBlock = null;
|
||||
ErrorHandler::start();
|
||||
// if file locking enabled -> file_get_contents can't be used
|
||||
if ($lock) {
|
||||
$fp = \fopen($file, 'rb');
|
||||
if (\false === $fp) {
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error opening file '{$file}'", 0, $err);
|
||||
}
|
||||
if ($block) {
|
||||
$wouldblockFromFileLock = null;
|
||||
$locked = \flock($fp, \LOCK_SH | \LOCK_NB, $wouldblockFromFileLock);
|
||||
if ($wouldblockFromFileLock) {
|
||||
\fclose($fp);
|
||||
ErrorHandler::stop();
|
||||
$wouldBlock = \true;
|
||||
|
||||
return '';
|
||||
}
|
||||
} else {
|
||||
$locked = \flock($fp, \LOCK_SH);
|
||||
}
|
||||
if (!$locked) {
|
||||
\fclose($fp);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error locking file '{$file}'", 0, $err);
|
||||
}
|
||||
$res = \stream_get_contents($fp);
|
||||
if (\false === $res) {
|
||||
\flock($fp, \LOCK_UN);
|
||||
\fclose($fp);
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException('Error getting stream contents', 0, $err);
|
||||
}
|
||||
\flock($fp, \LOCK_UN);
|
||||
\fclose($fp);
|
||||
// if file locking disabled -> file_get_contents can be used
|
||||
} else {
|
||||
$res = \file_get_contents($file, \false);
|
||||
if (\false === $res) {
|
||||
$err = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("Error getting file contents for file '{$file}'", 0, $err);
|
||||
}
|
||||
}
|
||||
ErrorHandler::stop();
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
public function exists(string $file): bool
|
||||
{
|
||||
return \file_exists($file);
|
||||
}
|
||||
|
||||
public function lastModifiedTime(string $file): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$mtime = \filemtime($file);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $mtime) {
|
||||
\assert(null !== $error);
|
||||
|
||||
throw new MetadataException(MetadataException::METADATA_MTIME, $error);
|
||||
}
|
||||
|
||||
return $mtime;
|
||||
}
|
||||
|
||||
public function lastAccessedTime(string $file): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$atime = \fileatime($file);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $atime) {
|
||||
\assert(null !== $error);
|
||||
|
||||
throw new MetadataException(MetadataException::METADATA_ATIME, $error);
|
||||
}
|
||||
|
||||
return $atime;
|
||||
}
|
||||
|
||||
public function createdTime(string $file): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$ctime = \filectime($file);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $ctime) {
|
||||
\assert(null !== $error);
|
||||
|
||||
throw new MetadataException(MetadataException::METADATA_CTIME, $error);
|
||||
}
|
||||
|
||||
return $ctime;
|
||||
}
|
||||
|
||||
public function filesize(string $file): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$filesize = \filesize($file);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $filesize) {
|
||||
\assert(null !== $error);
|
||||
|
||||
throw new MetadataException(MetadataException::METADATA_FILESIZE, $error);
|
||||
}
|
||||
|
||||
return $filesize;
|
||||
}
|
||||
|
||||
public function clearStatCache(): void
|
||||
{
|
||||
\clearstatcache();
|
||||
}
|
||||
|
||||
public function availableBytes(string $directory): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$bytes = \disk_free_space($directory);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $bytes) {
|
||||
throw new RuntimeException('Could not detect disk free space', 0, $error);
|
||||
}
|
||||
|
||||
return (int) $bytes;
|
||||
}
|
||||
|
||||
public function totalBytes(string $directory): int
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$bytes = \disk_total_space($directory);
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $bytes) {
|
||||
throw new RuntimeException('Could not detect disk total space', 0, $error);
|
||||
}
|
||||
|
||||
return (int) $bytes;
|
||||
}
|
||||
|
||||
public function touch(string $file): bool
|
||||
{
|
||||
ErrorHandler::start();
|
||||
$touch = \touch($file);
|
||||
$error = ErrorHandler::stop();
|
||||
if (!$touch) {
|
||||
throw new RuntimeException("Error touching file '{$file}'", 0, $error);
|
||||
}
|
||||
|
||||
return \true;
|
||||
}
|
||||
|
||||
public function umask(int $umask): int
|
||||
{
|
||||
return \umask($umask);
|
||||
}
|
||||
|
||||
public function createDirectory(string $directory, int $permissions, bool $recursive = \false, ?int $umask = null): void
|
||||
{
|
||||
$umaskToRestore = null;
|
||||
if ($umask) {
|
||||
$umaskToRestore = \umask($umask);
|
||||
}
|
||||
$created = \mkdir($directory, $permissions, $recursive);
|
||||
$error = ErrorHandler::stop();
|
||||
if ($umaskToRestore) {
|
||||
\umask($umaskToRestore);
|
||||
}
|
||||
if (\false === $created && !\is_dir($directory)) {
|
||||
throw new RuntimeException(\sprintf('Could not create directory "%s"', $directory), 0, $error);
|
||||
}
|
||||
ErrorHandler::start();
|
||||
if (!\chmod($directory, $permissions)) {
|
||||
$oct = \decoct($permissions);
|
||||
$error = ErrorHandler::stop();
|
||||
|
||||
throw new RuntimeException("chmod('{$directory}', 0{$oct}) failed", 0, $error);
|
||||
}
|
||||
ErrorHandler::stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter\Filesystem;
|
||||
|
||||
final class Module
|
||||
{
|
||||
public function getConfig(): array
|
||||
{
|
||||
$config = (new ConfigProvider())();
|
||||
$dependencies = $config['dependencies'] ?? [];
|
||||
\assert(\is_array($dependencies));
|
||||
$config['service_manager'] = $dependencies;
|
||||
unset($config['dependencies']);
|
||||
|
||||
return $config;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\IteratorInterface;
|
||||
use GlobIterator;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
final class FilesystemIterator implements IteratorInterface
|
||||
{
|
||||
/**
|
||||
* The Filesystem storage instance.
|
||||
*
|
||||
* @var Filesystem
|
||||
*/
|
||||
private $storage;
|
||||
|
||||
/**
|
||||
* The iterator mode.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $mode = IteratorInterface::CURRENT_AS_KEY;
|
||||
|
||||
/**
|
||||
* The GlobIterator instance.
|
||||
*
|
||||
* @var \GlobIterator
|
||||
*/
|
||||
private $globIterator;
|
||||
|
||||
/**
|
||||
* The namespace sprefix.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* String length of namespace prefix.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $prefixLength;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $path
|
||||
* @param string $prefix
|
||||
*/
|
||||
public function __construct(Filesystem $storage, $path, $prefix)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
$this->globIterator = new \GlobIterator($path, \GlobIterator::KEY_AS_FILENAME);
|
||||
$this->prefix = $prefix;
|
||||
$this->prefixLength = \strlen($prefix);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage instance.
|
||||
*
|
||||
* @return Filesystem
|
||||
*/
|
||||
public function getStorage()
|
||||
{
|
||||
return $this->storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iterator mode.
|
||||
*
|
||||
* @return int Value of IteratorInterface::CURRENT_AS_*
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set iterator mode.
|
||||
*
|
||||
* @param int $mode
|
||||
*
|
||||
* @return FilesystemIterator Provides a fluent interface
|
||||
*/
|
||||
public function setMode($mode)
|
||||
{
|
||||
$this->mode = (int) $mode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Iterator
|
||||
/**
|
||||
* Get current key, value or metadata.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
if (IteratorInterface::CURRENT_AS_SELF === $this->mode) {
|
||||
return $this;
|
||||
}
|
||||
$key = $this->key();
|
||||
if (IteratorInterface::CURRENT_AS_VALUE === $this->mode) {
|
||||
return $this->storage->getItem($key);
|
||||
}
|
||||
if (IteratorInterface::CURRENT_AS_METADATA === $this->mode) {
|
||||
return $this->storage->getMetadata($key);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current key.
|
||||
*/
|
||||
public function key(): string
|
||||
{
|
||||
$filename = $this->globIterator->key();
|
||||
// return without namespace prefix and file suffix
|
||||
return \substr($filename, $this->prefixLength, -4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element.
|
||||
*/
|
||||
public function next(): void
|
||||
{
|
||||
$this->globIterator->next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid.
|
||||
*/
|
||||
public function valid(): bool
|
||||
{
|
||||
return $this->globIterator->valid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element.
|
||||
*/
|
||||
public function rewind(): void
|
||||
{
|
||||
$this->globIterator->rewind();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,432 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
final class FilesystemOptions extends AdapterOptions
|
||||
{
|
||||
public const KEY_PATTERN = '/^[a-z0-9_\\+\\-]*$/Di';
|
||||
|
||||
/**
|
||||
* Overwrite default key pattern.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyPattern = self::KEY_PATTERN;
|
||||
|
||||
/**
|
||||
* Directory to store cache files.
|
||||
*
|
||||
* @var string The cache directory
|
||||
*/
|
||||
private $cacheDir;
|
||||
|
||||
/**
|
||||
* Call clearstatcache enabled?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $clearStatCache = \true;
|
||||
|
||||
/**
|
||||
* How much sub-directaries should be created?
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
private $dirLevel = 1;
|
||||
|
||||
/**
|
||||
* Permission creating new directories.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
private $dirPermission = 0700;
|
||||
|
||||
/**
|
||||
* Lock files on writing.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $fileLocking = \true;
|
||||
|
||||
/**
|
||||
* Permission creating new files.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
private $filePermission = 0600;
|
||||
|
||||
/**
|
||||
* Namespace separator.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $namespaceSeparator = '-';
|
||||
|
||||
/**
|
||||
* Don't get 'fileatime' as 'atime' on metadata.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $noAtime = \true;
|
||||
|
||||
/**
|
||||
* Don't get 'filectime' as 'ctime' on metadata.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $noCtime = \true;
|
||||
|
||||
/**
|
||||
* Umask to create files and directories.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
private $umask = \false;
|
||||
|
||||
/**
|
||||
* Suffix for cache files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $suffix = 'dat';
|
||||
|
||||
/**
|
||||
* Suffix for tag files.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $tagSuffix = 'tag';
|
||||
|
||||
/**
|
||||
* @param null|array|\Traversable $options
|
||||
*/
|
||||
public function __construct($options = null)
|
||||
{
|
||||
// disable file/directory permissions by default on windows systems
|
||||
if (0 === \stripos(\PHP_OS, 'WIN')) {
|
||||
$this->filePermission = \false;
|
||||
$this->dirPermission = \false;
|
||||
}
|
||||
// $this->setCacheDir(null);
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setCacheDir(?string $cacheDir): self
|
||||
{
|
||||
$cacheDir = $cacheDir ?? \sys_get_temp_dir();
|
||||
$cacheDir = $this->normalizeCacheDirectory($cacheDir);
|
||||
if ($this->cacheDir === $cacheDir) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('cache_dir', $cacheDir);
|
||||
$this->cacheDir = $cacheDir;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCacheDir(): string
|
||||
{
|
||||
return $this->cacheDir;
|
||||
}
|
||||
|
||||
public function setClearStatCache(bool $clearStatCache): self
|
||||
{
|
||||
if ($this->clearStatCache === $clearStatCache) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('clear_stat_cache', $clearStatCache);
|
||||
$this->clearStatCache = $clearStatCache;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getClearStatCache(): bool
|
||||
{
|
||||
return $this->clearStatCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setDirLevel(int $dirLevel): self
|
||||
{
|
||||
if ($dirLevel < 0 || $dirLevel > 16) {
|
||||
throw new Exception\InvalidArgumentException("Directory level '{$dirLevel}' must be between 0 and 16");
|
||||
}
|
||||
if ($this->dirLevel === $dirLevel) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('dir_level', $dirLevel);
|
||||
$this->dirLevel = $dirLevel;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDirLevel(): int
|
||||
{
|
||||
return $this->dirLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permission to create directories on unix systems.
|
||||
*
|
||||
* @see http://php.net/manual/function.chmod.php
|
||||
* @see FilesystemOptions::setUmask
|
||||
* @see FilesystemOptions::setFilePermission
|
||||
*
|
||||
* @param false|int|string $dirPermission FALSE to disable explicit permission or an octal number
|
||||
*/
|
||||
public function setDirPermission($dirPermission): self
|
||||
{
|
||||
if (\false !== $dirPermission) {
|
||||
if (\is_string($dirPermission)) {
|
||||
$dirPermission = \octdec($dirPermission);
|
||||
} else {
|
||||
$dirPermission = (int) $dirPermission;
|
||||
}
|
||||
// validate
|
||||
if (($dirPermission & 0700) !== 0700) {
|
||||
throw new Exception\InvalidArgumentException('Invalid directory permission: need permission to execute, read and write by owner');
|
||||
}
|
||||
}
|
||||
if ($this->dirPermission === $dirPermission) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('dir_permission', $dirPermission);
|
||||
$this->dirPermission = $dirPermission;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get permission to create directories on unix systems.
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getDirPermission()
|
||||
{
|
||||
return $this->dirPermission;
|
||||
}
|
||||
|
||||
public function setFileLocking(bool $fileLocking): self
|
||||
{
|
||||
$this->triggerOptionEvent('file_locking', $fileLocking);
|
||||
$this->fileLocking = $fileLocking;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getFileLocking(): bool
|
||||
{
|
||||
return $this->fileLocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set permission to create files on unix systems.
|
||||
*
|
||||
* @see http://php.net/manual/function.chmod.php
|
||||
* @see FilesystemOptions::setUmask
|
||||
* @see FilesystemOptions::setDirPermission
|
||||
*
|
||||
* @param false|int|string $filePermission FALSE to disable explicit permission or an octal number
|
||||
*/
|
||||
public function setFilePermission($filePermission): self
|
||||
{
|
||||
if (\false !== $filePermission) {
|
||||
if (\is_string($filePermission)) {
|
||||
$filePermission = \octdec($filePermission);
|
||||
} else {
|
||||
$filePermission = (int) $filePermission;
|
||||
}
|
||||
// validate
|
||||
if (($filePermission & 0600) !== 0600) {
|
||||
throw new Exception\InvalidArgumentException('Invalid file permission: need permission to read and write by owner');
|
||||
}
|
||||
if ($filePermission & 0111) {
|
||||
throw new Exception\InvalidArgumentException("Invalid file permission: Cache files shouldn't be executable");
|
||||
}
|
||||
}
|
||||
if ($this->filePermission === $filePermission) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('file_permission', $filePermission);
|
||||
$this->filePermission = $filePermission;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get permission to create files on unix systems.
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getFilePermission()
|
||||
{
|
||||
return $this->filePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function setNamespace($namespace): self
|
||||
{
|
||||
if (\strlen($namespace) >= 250) {
|
||||
throw new Exception\InvalidArgumentException('Provided namespace is too long.');
|
||||
}
|
||||
parent::setNamespace($namespace);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setNamespaceSeparator(string $namespaceSeparator): self
|
||||
{
|
||||
$this->triggerOptionEvent('namespace_separator', $namespaceSeparator);
|
||||
$this->namespaceSeparator = $namespaceSeparator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNamespaceSeparator(): string
|
||||
{
|
||||
return $this->namespaceSeparator;
|
||||
}
|
||||
|
||||
public function setNoAtime(bool $noAtime): self
|
||||
{
|
||||
if ($this->noAtime === $noAtime) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('no_atime', $noAtime);
|
||||
$this->noAtime = $noAtime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNoAtime(): bool
|
||||
{
|
||||
return $this->noAtime;
|
||||
}
|
||||
|
||||
public function setNoCtime(bool $noCtime): self
|
||||
{
|
||||
if ($this->noCtime === $noCtime) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('no_ctime', $noCtime);
|
||||
$this->noCtime = $noCtime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getNoCtime(): bool
|
||||
{
|
||||
return $this->noCtime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the umask to create files and directories on unix systems.
|
||||
*
|
||||
* Note: On multithreaded webservers it's better to explicit set file and dir permission.
|
||||
*
|
||||
* @see http://php.net/manual/function.umask.php
|
||||
* @see http://en.wikipedia.org/wiki/Umask
|
||||
* @see FilesystemOptions::setFilePermission
|
||||
* @see FilesystemOptions::setDirPermission
|
||||
*
|
||||
* @param false|int|string $umask false to disable umask or an octal number
|
||||
*/
|
||||
public function setUmask($umask): self
|
||||
{
|
||||
if (\false !== $umask) {
|
||||
if (\is_string($umask)) {
|
||||
$umask = \octdec($umask);
|
||||
} else {
|
||||
$umask = (int) $umask;
|
||||
}
|
||||
// validate
|
||||
if ($umask & 0700) {
|
||||
throw new Exception\InvalidArgumentException('Invalid umask: need permission to execute, read and write by owner');
|
||||
}
|
||||
// normalize
|
||||
$umask &= ~02;
|
||||
}
|
||||
if ($this->umask === $umask) {
|
||||
return $this;
|
||||
}
|
||||
$this->triggerOptionEvent('umask', $umask);
|
||||
$this->umask = $umask;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the umask to create files and directories on unix systems.
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getUmask()
|
||||
{
|
||||
return $this->umask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the suffix for cache files.
|
||||
*/
|
||||
public function getSuffix(): string
|
||||
{
|
||||
return $this->suffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the suffix for cache files.
|
||||
*/
|
||||
public function setSuffix(string $suffix): self
|
||||
{
|
||||
$this->suffix = $suffix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the suffix for tag files.
|
||||
*/
|
||||
public function getTagSuffix(): string
|
||||
{
|
||||
return $this->tagSuffix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the suffix for cache files.
|
||||
*/
|
||||
public function setTagSuffix(string $tagSuffix): self
|
||||
{
|
||||
$this->tagSuffix = $tagSuffix;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
private function normalizeCacheDirectory(string $cacheDir): string
|
||||
{
|
||||
if (!\is_dir($cacheDir)) {
|
||||
throw new Exception\InvalidArgumentException("Cache directory '{$cacheDir}' not found or not a directory");
|
||||
}
|
||||
if (!\is_writable($cacheDir)) {
|
||||
throw new Exception\InvalidArgumentException("Cache directory '{$cacheDir}' not writable");
|
||||
}
|
||||
if (!\is_readable($cacheDir)) {
|
||||
throw new Exception\InvalidArgumentException("Cache directory '{$cacheDir}' not readable");
|
||||
}
|
||||
|
||||
return \rtrim(\realpath($cacheDir), \DIRECTORY_SEPARATOR);
|
||||
}
|
||||
}
|
||||
1194
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/psalm-baseline.xml
vendored
Normal file
1194
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/psalm-baseline.xml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
27
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/psalm.xml
vendored
Normal file
27
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/psalm.xml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0"?>
|
||||
<psalm
|
||||
errorLevel="1"
|
||||
resolveFromConfigFile="true"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="https://getpsalm.org/schema/config"
|
||||
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
|
||||
errorBaseline="psalm-baseline.xml"
|
||||
>
|
||||
<projectFiles>
|
||||
<directory name="src"/>
|
||||
<directory name="test"/>
|
||||
<ignoreFiles>
|
||||
<directory name="vendor"/>
|
||||
</ignoreFiles>
|
||||
</projectFiles>
|
||||
<issueHandlers>
|
||||
<InternalMethod>
|
||||
<errorLevel type="suppress">
|
||||
<referencedMethod name="_JchOptimizeVendor\Laminas\Cache\Command\DeprecatedStorageFactoryConfigurationCheckCommand::__construct"/>
|
||||
</errorLevel>
|
||||
</InternalMethod>
|
||||
</issueHandlers>
|
||||
<plugins>
|
||||
<pluginClass class="_JchOptimizeVendor\Psalm\PhpUnitPlugin\Plugin"/>
|
||||
</plugins>
|
||||
</psalm>
|
||||
6
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/renovate.json
vendored
Normal file
6
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/renovate.json
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"local>laminas/.github:renovate-config"
|
||||
]
|
||||
}
|
||||
53
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/ConfigProvider.php
vendored
Normal file
53
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/ConfigProvider.php
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Command\DeprecatedStorageFactoryConfigurationCheckCommand;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Command\DeprecatedStorageFactoryConfigurationCheckCommandFactory;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StorageAdapterFactory;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StorageAdapterFactoryFactory;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StorageAdapterFactoryInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StoragePluginFactory;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StoragePluginFactoryFactory;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Service\StoragePluginFactoryInterface;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
class ConfigProvider
|
||||
{
|
||||
/**
|
||||
* Return default configuration for laminas-cache.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return ['dependencies' => $this->getDependencyConfig(), 'laminas-cli' => $this->getCliConfig()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default service mappings for laminas-cache.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getDependencyConfig()
|
||||
{
|
||||
$dependencies = ['abstract_factories' => [Service\StorageCacheAbstractServiceFactory::class], 'factories' => [Storage\AdapterPluginManager::class => Service\StorageAdapterPluginManagerFactory::class, Storage\PluginManager::class => Service\StoragePluginManagerFactory::class, StoragePluginFactory::class => StoragePluginFactoryFactory::class, StoragePluginFactoryInterface::class => StoragePluginFactoryFactory::class, StorageAdapterFactory::class => StorageAdapterFactoryFactory::class, StorageAdapterFactoryInterface::class => StorageAdapterFactoryFactory::class]];
|
||||
if (\class_exists(Command::class)) {
|
||||
$dependencies['factories'] += [DeprecatedStorageFactoryConfigurationCheckCommand::class => DeprecatedStorageFactoryConfigurationCheckCommandFactory::class];
|
||||
}
|
||||
|
||||
return $dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,mixed>
|
||||
*/
|
||||
public function getCliConfig(): array
|
||||
{
|
||||
if (!\class_exists(Command::class)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['commands' => [DeprecatedStorageFactoryConfigurationCheckCommand::NAME => DeprecatedStorageFactoryConfigurationCheckCommand::class]];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class BadMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
interface ExceptionInterface extends \Throwable
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class ExtensionNotLoadedException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class LogicException extends \LogicException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class MissingDependencyException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class MissingKeyException extends RuntimeException
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class OutOfSpaceException extends \OverflowException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class RuntimeException extends \RuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class UnexpectedValueException extends \UnexpectedValueException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class UnsupportedMethodCallException extends \BadMethodCallException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
18
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/Module.php
vendored
Normal file
18
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/Module.php
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache;
|
||||
|
||||
class Module
|
||||
{
|
||||
/**
|
||||
* Return default laminas-cache configuration for laminas-mvc context.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
$provider = new ConfigProvider();
|
||||
|
||||
return ['service_manager' => $provider->getDependencyConfig(), 'laminas-cli' => $provider->getCliConfig()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
abstract class AbstractPattern implements PatternInterface
|
||||
{
|
||||
/** @var null|PatternOptions */
|
||||
protected $options;
|
||||
|
||||
public function __construct(?PatternOptions $options = null)
|
||||
{
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AbstractPattern
|
||||
*/
|
||||
public function setOptions(PatternOptions $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PatternOptions
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
if (null === $this->options) {
|
||||
$this->setOptions(new PatternOptions());
|
||||
}
|
||||
|
||||
return $this->options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
|
||||
abstract class AbstractStorageCapablePattern extends AbstractPattern implements StorageCapableInterface
|
||||
{
|
||||
/** @var StorageInterface */
|
||||
protected $storage;
|
||||
|
||||
public function __construct(StorageInterface $storage, ?PatternOptions $options = null)
|
||||
{
|
||||
parent::__construct($options);
|
||||
$this->storage = $storage;
|
||||
}
|
||||
|
||||
public function getStorage(): StorageInterface
|
||||
{
|
||||
return $this->storage;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\ErrorHandler;
|
||||
|
||||
class CallbackCache extends AbstractStorageCapablePattern
|
||||
{
|
||||
/**
|
||||
* function call handler.
|
||||
*
|
||||
* @param string $function Function name to call
|
||||
* @param array $args Function arguments
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __call($function, array $args)
|
||||
{
|
||||
return $this->call($function, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call the specified callback or get the result from cache.
|
||||
*
|
||||
* @param callable $callback A valid callback
|
||||
* @param array $args Callback arguments
|
||||
*
|
||||
* @return mixed Result
|
||||
*
|
||||
* @throws Exception\RuntimeException if invalid cached data
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function call($callback, array $args = [])
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
$storage = $this->getStorage();
|
||||
$success = null;
|
||||
$key = $this->generateCallbackKey($callback, $args);
|
||||
$result = $storage->getItem($key, $success);
|
||||
if ($success) {
|
||||
if (!\array_key_exists(0, $result)) {
|
||||
throw new Exception\RuntimeException("Invalid cached data for key '{$key}'");
|
||||
}
|
||||
echo $result[1] ?? '';
|
||||
|
||||
return $result[0];
|
||||
}
|
||||
$cacheOutput = $options->getCacheOutput();
|
||||
if ($cacheOutput) {
|
||||
\ob_start();
|
||||
\ob_implicit_flush(0);
|
||||
}
|
||||
// TODO: do not cache on errors using [set|restore]_error_handler
|
||||
try {
|
||||
$ret = $callback(...$args);
|
||||
} catch (\Exception $e) {
|
||||
if ($cacheOutput) {
|
||||
\ob_end_flush();
|
||||
}
|
||||
|
||||
throw $e;
|
||||
}
|
||||
if ($cacheOutput) {
|
||||
$data = [$ret, \ob_get_flush()];
|
||||
} else {
|
||||
$data = [$ret];
|
||||
}
|
||||
$storage->setItem($key, $data);
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique key in base of a key representing the callback part
|
||||
* and a key representing the arguments part.
|
||||
*
|
||||
* @param callable $callback A valid callback
|
||||
* @param array $args Callback arguments
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function generateKey($callback, array $args = [])
|
||||
{
|
||||
return $this->generateCallbackKey($callback, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique key in base of a key representing the callback part
|
||||
* and a key representing the arguments part.
|
||||
*
|
||||
* @param callable $callback A valid callback
|
||||
* @param array $args Callback arguments
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception\RuntimeException if callback not serializable
|
||||
* @throws Exception\InvalidArgumentException if invalid callback
|
||||
*/
|
||||
protected function generateCallbackKey($callback, array $args)
|
||||
{
|
||||
if (!\is_callable($callback, \false, $callbackKey)) {
|
||||
throw new Exception\InvalidArgumentException('Invalid callback');
|
||||
}
|
||||
// functions, methods and classnames are case-insensitive
|
||||
$callbackKey = \strtolower($callbackKey);
|
||||
// generate a unique key of object callbacks
|
||||
if (\is_object($callback)) {
|
||||
// Closures & __invoke
|
||||
$object = $callback;
|
||||
} elseif (isset($callback[0])) {
|
||||
// array($object, 'method')
|
||||
$object = $callback[0];
|
||||
}
|
||||
if (isset($object)) {
|
||||
ErrorHandler::start();
|
||||
|
||||
try {
|
||||
$serializedObject = \serialize($object);
|
||||
} catch (\Exception $e) {
|
||||
ErrorHandler::stop();
|
||||
|
||||
throw new Exception\RuntimeException("Can't serialize callback: see previous exception", 0, $e);
|
||||
}
|
||||
$error = ErrorHandler::stop();
|
||||
if (!$serializedObject) {
|
||||
throw new Exception\RuntimeException(\sprintf('Cannot serialize callback%s', $error ? ': '.$error->getMessage() : ''), 0, $error);
|
||||
}
|
||||
$callbackKey .= $serializedObject;
|
||||
}
|
||||
|
||||
return \md5($callbackKey).$this->generateArgumentsKey($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique key of the argument part.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
*/
|
||||
protected function generateArgumentsKey(array $args)
|
||||
{
|
||||
if (!$args) {
|
||||
return '';
|
||||
}
|
||||
ErrorHandler::start();
|
||||
|
||||
try {
|
||||
$serializedArgs = \serialize(\array_values($args));
|
||||
} catch (\Exception $e) {
|
||||
ErrorHandler::stop();
|
||||
|
||||
throw new Exception\RuntimeException("Can't serialize arguments: see previous exception", 0, $e);
|
||||
}
|
||||
$error = ErrorHandler::stop();
|
||||
if (!$serializedArgs) {
|
||||
throw new Exception\RuntimeException(\sprintf('Cannot serialize arguments%s', $error ? ': '.$error->getMessage() : ''), 0, $error);
|
||||
}
|
||||
|
||||
return \md5($serializedArgs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class ObjectCache extends CallbackCache
|
||||
{
|
||||
/**
|
||||
* Class method call handler.
|
||||
*
|
||||
* @param string $method Method name to call
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function __call($method, array $args)
|
||||
{
|
||||
return $this->call($method, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writing data to properties.
|
||||
*
|
||||
* NOTE:
|
||||
* Magic properties will be cached too if the option cacheMagicProperties
|
||||
* is enabled and the property doesn't exist in real. If so it calls __set
|
||||
* and removes cached data of previous __get and __isset calls.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
||||
*
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.InvalidReturnVoid
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
return $this->call('__set', [$name, $value]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reading data from properties.
|
||||
*
|
||||
* NOTE:
|
||||
* Magic properties will be cached too if the option cacheMagicProperties
|
||||
* is enabled and the property doesn't exist in real. If so it calls __get.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->call('__get', [$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checking existing properties.
|
||||
*
|
||||
* NOTE:
|
||||
* Magic properties will be cached too if the option cacheMagicProperties
|
||||
* is enabled and the property doesn't exist in real. If so it calls __get.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function __isset($name)
|
||||
{
|
||||
return $this->call('__isset', [$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unseting a property.
|
||||
*
|
||||
* NOTE:
|
||||
* Magic properties will be cached too if the option cacheMagicProperties
|
||||
* is enabled and the property doesn't exist in real. If so it removes
|
||||
* previous cached __isset and __get calls.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.overloading.php#language.oop5.overloading.members
|
||||
*
|
||||
* @phpcs:disable Squiz.Commenting.FunctionComment.InvalidReturnVoid
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function __unset($name)
|
||||
{
|
||||
return $this->call('__unset', [$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle casting to string.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.tostring
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->call('__toString');
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle invoke calls.
|
||||
*
|
||||
* @see http://php.net/manual/language.oop5.magic.php#language.oop5.magic.invoke
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function __invoke()
|
||||
{
|
||||
return $this->call('__invoke', \func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ObjectCache
|
||||
*/
|
||||
public function setOptions(PatternOptions $options)
|
||||
{
|
||||
parent::setOptions($options);
|
||||
if (!$options->getObject()) {
|
||||
throw new Exception\InvalidArgumentException("Missing option 'object'");
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call and cache a class method.
|
||||
*
|
||||
* @param string $method Method name to call
|
||||
* @param array $args Method arguments
|
||||
*
|
||||
* @return mixed
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function call($method, array $args = [])
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
$object = $options->getObject();
|
||||
$method = \strtolower($method);
|
||||
// handle magic methods
|
||||
switch ($method) {
|
||||
case '__set':
|
||||
$property = \array_shift($args);
|
||||
$value = \array_shift($args);
|
||||
$object->{$property} = $value;
|
||||
if (!$options->getObjectCacheMagicProperties() || \property_exists($object, $property)) {
|
||||
// no caching if property isn't magic
|
||||
// or caching magic properties is disabled
|
||||
return;
|
||||
}
|
||||
// remove cached __get and __isset
|
||||
$removeKeys = null;
|
||||
if (\method_exists($object, '__get')) {
|
||||
$removeKeys[] = $this->generateKey('__get', [$property]);
|
||||
}
|
||||
if (\method_exists($object, '__isset')) {
|
||||
$removeKeys[] = $this->generateKey('__isset', [$property]);
|
||||
}
|
||||
if ($removeKeys) {
|
||||
$storage = $this->getStorage();
|
||||
$storage->removeItems($removeKeys);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
case '__get':
|
||||
$property = \array_shift($args);
|
||||
if (!$options->getObjectCacheMagicProperties() || \property_exists($object, $property)) {
|
||||
// no caching if property isn't magic
|
||||
// or caching magic properties is disabled
|
||||
return $object->{$property};
|
||||
}
|
||||
\array_unshift($args, $property);
|
||||
|
||||
return parent::call([$object, '__get'], $args);
|
||||
|
||||
case '__isset':
|
||||
$property = \array_shift($args);
|
||||
if (!$options->getObjectCacheMagicProperties() || \property_exists($object, $property)) {
|
||||
// no caching if property isn't magic
|
||||
// or caching magic properties is disabled
|
||||
return isset($object->{$property});
|
||||
}
|
||||
|
||||
return parent::call([$object, '__isset'], [$property]);
|
||||
|
||||
case '__unset':
|
||||
$property = \array_shift($args);
|
||||
unset($object->{$property});
|
||||
if (!$options->getObjectCacheMagicProperties() || \property_exists($object, $property)) {
|
||||
// no caching if property isn't magic
|
||||
// or caching magic properties is disabled
|
||||
return;
|
||||
}
|
||||
// remove previous cached __get and __isset calls
|
||||
$removeKeys = null;
|
||||
if (\method_exists($object, '__get')) {
|
||||
$removeKeys[] = $this->generateKey('__get', [$property]);
|
||||
}
|
||||
if (\method_exists($object, '__isset')) {
|
||||
$removeKeys[] = $this->generateKey('__isset', [$property]);
|
||||
}
|
||||
if ($removeKeys) {
|
||||
$storage = $this->getStorage();
|
||||
$storage->removeItems($removeKeys);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$cache = $options->getCacheByDefault();
|
||||
if ($cache) {
|
||||
$cache = !\in_array($method, $options->getObjectNonCacheMethods());
|
||||
} else {
|
||||
$cache = \in_array($method, $options->getObjectCacheMethods());
|
||||
}
|
||||
if (!$cache) {
|
||||
return $object->{$method}(...$args);
|
||||
}
|
||||
|
||||
return parent::call([$object, $method], $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique key in base of a key representing the callback part
|
||||
* and a key representing the arguments part.
|
||||
*
|
||||
* @param string $method The method
|
||||
* @param array $args Callback arguments
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
*/
|
||||
public function generateKey($method, array $args = [])
|
||||
{
|
||||
return $this->generateCallbackKey([$this->getOptions()->getObject(), $method], $args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a unique key in base of a key representing the callback part
|
||||
* and a key representing the arguments part.
|
||||
*
|
||||
* @param callable $callback A valid callback
|
||||
* @param array $args Callback arguments
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* @throws Exception\RuntimeException
|
||||
*/
|
||||
protected function generateCallbackKey($callback, array $args = [])
|
||||
{
|
||||
$callbackKey = \md5($this->getOptions()->getObjectKey().'::'.\strtolower($callback[1]));
|
||||
$argumentKey = $this->generateArgumentsKey($args);
|
||||
|
||||
return $callbackKey.$argumentKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
class OutputCache extends AbstractStorageCapablePattern
|
||||
{
|
||||
/**
|
||||
* The key stack.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $keyStack = [];
|
||||
|
||||
/**
|
||||
* if there is a cached item with the given key display it's data and return true
|
||||
* else start buffering output until end() is called or the script ends.
|
||||
*
|
||||
* @param string $key Key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws Exception\MissingKeyException if key is missing
|
||||
*/
|
||||
public function start($key)
|
||||
{
|
||||
if (($key = (string) $key) === '') {
|
||||
throw new Exception\MissingKeyException('Missing key to read/write output from cache');
|
||||
}
|
||||
$success = null;
|
||||
$storage = $this->getStorage();
|
||||
$data = $storage->getItem($key, $success);
|
||||
if ($success) {
|
||||
echo $data;
|
||||
|
||||
return \true;
|
||||
}
|
||||
\ob_start();
|
||||
\ob_implicit_flush(0);
|
||||
$this->keyStack[] = $key;
|
||||
|
||||
return \false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops buffering output, write buffered data to cache using the given key on start()
|
||||
* and displays the buffer.
|
||||
*
|
||||
* @return bool TRUE on success, FALSE on failure writing to cache
|
||||
*
|
||||
* @throws Exception\RuntimeException if output cache not started or buffering not active
|
||||
*/
|
||||
public function end()
|
||||
{
|
||||
$key = \array_pop($this->keyStack);
|
||||
if (null === $key) {
|
||||
throw new Exception\RuntimeException('Output cache not started');
|
||||
}
|
||||
$output = \ob_get_flush();
|
||||
if (\false === $output) {
|
||||
throw new Exception\RuntimeException('Output buffering not active');
|
||||
}
|
||||
$storage = $this->getStorage();
|
||||
|
||||
return $storage->setItem($key, $output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
interface PatternInterface
|
||||
{
|
||||
/**
|
||||
* Get all pattern options.
|
||||
*
|
||||
* @return PatternOptions
|
||||
*/
|
||||
public function getOptions();
|
||||
}
|
||||
@@ -0,0 +1,598 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\AbstractOptions;
|
||||
|
||||
class PatternOptions extends AbstractOptions
|
||||
{
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $cacheByDefault = \true;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CallbackCache
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $cacheOutput = \true;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
protected $umask = \false;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
protected $dirPermission = 0700;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var false|int
|
||||
*/
|
||||
protected $filePermission = 0600;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $fileLocking = \true;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $indexFilename = 'index.html';
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var null|object
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $objectCacheMagicProperties = \false;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $objectCacheMethods = [];
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
protected $objectKey;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ObjectCache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $objectNonCacheMethods = ['__tostring'];
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - CaptureCache.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
protected $publicDir;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param null|array|\Traversable $options
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function __construct($options = null)
|
||||
{
|
||||
// disable file/directory permissions by default on windows systems
|
||||
if (0 === \stripos(\PHP_OS, 'WIN')) {
|
||||
$this->filePermission = \false;
|
||||
$this->dirPermission = \false;
|
||||
}
|
||||
parent::__construct($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag indicating whether or not to cache by default.
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @param bool $cacheByDefault
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setCacheByDefault($cacheByDefault)
|
||||
{
|
||||
$this->cacheByDefault = $cacheByDefault;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do we cache by default?
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getCacheByDefault()
|
||||
{
|
||||
return $this->cacheByDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not to cache output.
|
||||
*
|
||||
* Used by:
|
||||
* - CallbackCache
|
||||
* - ObjectCache
|
||||
*
|
||||
* @param bool $cacheOutput
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setCacheOutput($cacheOutput)
|
||||
{
|
||||
$this->cacheOutput = (bool) $cacheOutput;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will we cache output?
|
||||
*
|
||||
* Used by:
|
||||
* - CallbackCache
|
||||
* - ObjectCache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getCacheOutput()
|
||||
{
|
||||
return $this->cacheOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set directory permission.
|
||||
*
|
||||
* @param false|float|int|string $dirPermission
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setDirPermission($dirPermission)
|
||||
{
|
||||
if (\false !== $dirPermission) {
|
||||
if (\is_string($dirPermission)) {
|
||||
$dirPermission = \octdec($dirPermission);
|
||||
} else {
|
||||
$dirPermission = (int) $dirPermission;
|
||||
}
|
||||
/*
|
||||
* Code is untested, applying strict type check might lead to unexpected errors.
|
||||
*
|
||||
* @phpcs:disable SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
|
||||
*/
|
||||
if (($dirPermission & 0700) != 0700) {
|
||||
throw new Exception\InvalidArgumentException('Invalid directory permission: need permission to execute, read and write by owner');
|
||||
}
|
||||
}
|
||||
$this->dirPermission = $dirPermission;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets directory permission.
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getDirPermission()
|
||||
{
|
||||
return $this->dirPermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set umask.
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @param false|float|int|string $umask
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setUmask($umask)
|
||||
{
|
||||
if (\false !== $umask) {
|
||||
if (\is_string($umask)) {
|
||||
$umask = \octdec($umask);
|
||||
} else {
|
||||
$umask = (int) $umask;
|
||||
}
|
||||
// validate
|
||||
if ($umask & 0700) {
|
||||
throw new Exception\InvalidArgumentException('Invalid umask: need permission to execute, read and write by owner');
|
||||
}
|
||||
// normalize
|
||||
$umask &= ~02;
|
||||
}
|
||||
$this->umask = $umask;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get umask.
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getUmask()
|
||||
{
|
||||
return $this->umask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not file locking should be used.
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @param bool $fileLocking
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setFileLocking($fileLocking)
|
||||
{
|
||||
$this->fileLocking = (bool) $fileLocking;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is file locking enabled?
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getFileLocking()
|
||||
{
|
||||
return $this->fileLocking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set file permission.
|
||||
*
|
||||
* @param false|float|int|string $filePermission
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setFilePermission($filePermission)
|
||||
{
|
||||
if (\false !== $filePermission) {
|
||||
if (\is_string($filePermission)) {
|
||||
$filePermission = \octdec($filePermission);
|
||||
} else {
|
||||
$filePermission = (int) $filePermission;
|
||||
}
|
||||
/*
|
||||
* Code is untested, applying strict type check might lead to unexpected errors.
|
||||
*
|
||||
* @phpcs:disable SlevomatCodingStandard.Operators.DisallowEqualOperators.DisallowedNotEqualOperator
|
||||
*/
|
||||
if (($filePermission & 0600) != 0600) {
|
||||
throw new Exception\InvalidArgumentException('Invalid file permission: need permission to read and write by owner');
|
||||
}
|
||||
if ($filePermission & 0111) {
|
||||
throw new Exception\InvalidArgumentException("Invalid file permission: Files shouldn't be executable");
|
||||
}
|
||||
}
|
||||
$this->filePermission = $filePermission;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets file permission.
|
||||
*
|
||||
* @return false|int
|
||||
*/
|
||||
public function getFilePermission()
|
||||
{
|
||||
return $this->filePermission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value for index filename.
|
||||
*
|
||||
* @param string $indexFilename
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setIndexFilename($indexFilename)
|
||||
{
|
||||
$this->indexFilename = (string) $indexFilename;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value for index filename.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getIndexFilename()
|
||||
{
|
||||
return $this->indexFilename;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set object to cache.
|
||||
*
|
||||
* @param mixed $object
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setObject($object)
|
||||
{
|
||||
if (!\is_object($object)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('%s expects an object; received "%s"', __METHOD__, \gettype($object)));
|
||||
}
|
||||
$this->object = $object;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object to cache.
|
||||
*
|
||||
* @return null|object
|
||||
*/
|
||||
public function getObject()
|
||||
{
|
||||
return $this->object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag indicating whether or not to cache magic properties.
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @param bool $objectCacheMagicProperties
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setObjectCacheMagicProperties($objectCacheMagicProperties)
|
||||
{
|
||||
$this->objectCacheMagicProperties = (bool) $objectCacheMagicProperties;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we cache magic properties?
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getObjectCacheMagicProperties()
|
||||
{
|
||||
return $this->objectCacheMagicProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set list of object methods for which to cache return values.
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setObjectCacheMethods(array $objectCacheMethods)
|
||||
{
|
||||
$this->objectCacheMethods = $this->normalizeObjectMethods($objectCacheMethods);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of object methods for which to cache return values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getObjectCacheMethods()
|
||||
{
|
||||
return $this->objectCacheMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the object key part.
|
||||
*
|
||||
* Used to generate a callback key in order to speed up key generation.
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @param null|string $objectKey The object key or NULL to use the objects class name
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*/
|
||||
public function setObjectKey($objectKey)
|
||||
{
|
||||
if (null !== $objectKey) {
|
||||
$this->objectKey = (string) $objectKey;
|
||||
} else {
|
||||
$this->objectKey = null;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get object key.
|
||||
*
|
||||
* Used by:
|
||||
* - ObjectCache
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getObjectKey()
|
||||
{
|
||||
if (null === $this->objectKey) {
|
||||
return \get_class($this->getObject());
|
||||
}
|
||||
|
||||
return $this->objectKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set list of object methods for which NOT to cache return values.
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setObjectNonCacheMethods(array $objectNonCacheMethods)
|
||||
{
|
||||
$this->objectNonCacheMethods = $this->normalizeObjectMethods($objectNonCacheMethods);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of object methods for which NOT to cache return values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getObjectNonCacheMethods()
|
||||
{
|
||||
return $this->objectNonCacheMethods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set location of public directory.
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @param string $publicDir
|
||||
*
|
||||
* @return PatternOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setPublicDir($publicDir)
|
||||
{
|
||||
$publicDir = (string) $publicDir;
|
||||
if (!\is_dir($publicDir)) {
|
||||
throw new Exception\InvalidArgumentException("Public directory '{$publicDir}' not found or not a directory");
|
||||
}
|
||||
if (!\is_writable($publicDir)) {
|
||||
throw new Exception\InvalidArgumentException("Public directory '{$publicDir}' not writable");
|
||||
}
|
||||
if (!\is_readable($publicDir)) {
|
||||
throw new Exception\InvalidArgumentException("Public directory '{$publicDir}' not readable");
|
||||
}
|
||||
$this->publicDir = \rtrim(\realpath($publicDir), \DIRECTORY_SEPARATOR);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get location of public directory.
|
||||
*
|
||||
* Used by:
|
||||
* - CaptureCache
|
||||
*
|
||||
* @return null|string
|
||||
*/
|
||||
public function getPublicDir()
|
||||
{
|
||||
return $this->publicDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively apply strtolower on all values of an array, and return as a
|
||||
* list of unique values.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function recursiveStrtolower(array $array)
|
||||
{
|
||||
return \array_values(\array_unique(\array_map('strtolower', $array)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize object methods.
|
||||
*
|
||||
* Recursively casts values to lowercase, then determines if any are in a
|
||||
* list of methods not handled, raising an exception if so.
|
||||
*
|
||||
* @return array
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
protected function normalizeObjectMethods(array $methods)
|
||||
{
|
||||
$methods = $this->recursiveStrtolower($methods);
|
||||
$intersect = \array_intersect(['__set', '__get', '__unset', '__isset'], $methods);
|
||||
if (!empty($intersect)) {
|
||||
throw new Exception\InvalidArgumentException("Magic properties are handled by option 'cache_magic_properties'");
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Pattern;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
|
||||
interface StorageCapableInterface extends PatternInterface
|
||||
{
|
||||
public function getStorage(): ?StorageInterface;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
final class DeprecatedSchemaDetector implements DeprecatedSchemaDetectorInterface
|
||||
{
|
||||
public function isDeprecatedStorageFactorySchema(array $configuration): bool
|
||||
{
|
||||
if (!\is_string($configuration['adapter'])) {
|
||||
return \true;
|
||||
}
|
||||
if (!isset($configuration['plugins'])) {
|
||||
return \false;
|
||||
}
|
||||
if (!\is_array($configuration['plugins'])) {
|
||||
return \true;
|
||||
}
|
||||
foreach ($configuration['plugins'] as $index => $plugin) {
|
||||
if (\is_string($index) || !\is_array($plugin)) {
|
||||
return \true;
|
||||
}
|
||||
if (!isset($plugin['name'])) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
interface DeprecatedSchemaDetectorInterface
|
||||
{
|
||||
/**
|
||||
* @param array<string,mixed> $configuration
|
||||
*/
|
||||
public function isDeprecatedStorageFactorySchema(array $configuration): bool;
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PluginAwareInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\PluginManagerInterface;
|
||||
use _JchOptimizeVendor\Webmozart\Assert\Assert;
|
||||
|
||||
use function assert;
|
||||
|
||||
/**
|
||||
* @psalm-import-type PluginArrayConfigurationWithPriorityType from StorageAdapterFactoryInterface
|
||||
*/
|
||||
final class StorageAdapterFactory implements StorageAdapterFactoryInterface
|
||||
{
|
||||
public const DEFAULT_PLUGIN_PRIORITY = 1;
|
||||
|
||||
/** @var PluginManagerInterface */
|
||||
private $adapters;
|
||||
|
||||
/** @var StoragePluginFactoryInterface */
|
||||
private $pluginFactory;
|
||||
|
||||
public function __construct(PluginManagerInterface $adapters, StoragePluginFactoryInterface $pluginFactory)
|
||||
{
|
||||
$this->adapters = $adapters;
|
||||
$this->pluginFactory = $pluginFactory;
|
||||
}
|
||||
|
||||
public function createFromArrayConfiguration(array $configuration): StorageInterface
|
||||
{
|
||||
$adapterName = $configuration['adapter'] ?? $configuration['name'] ?? null;
|
||||
Assert::stringNotEmpty($adapterName, 'Configuration must contain a "adapter" key.');
|
||||
$adapterOptions = $configuration['options'] ?? [];
|
||||
$plugins = $configuration['plugins'] ?? [];
|
||||
|
||||
return $this->create($adapterName, $adapterOptions, $plugins);
|
||||
}
|
||||
|
||||
public function create(string $storage, array $options = [], array $plugins = []): StorageInterface
|
||||
{
|
||||
$adapter = $this->adapters->build($storage, $options);
|
||||
\assert($adapter instanceof StorageInterface);
|
||||
if ([] === $plugins) {
|
||||
return $adapter;
|
||||
}
|
||||
if (!$adapter instanceof PluginAwareInterface) {
|
||||
throw new Exception\RuntimeException(\sprintf("The adapter '%s' doesn't implement '%s' and therefore can't handle plugins", \get_class($adapter), PluginAwareInterface::class));
|
||||
}
|
||||
foreach ($plugins as $pluginConfiguration) {
|
||||
$plugin = $this->pluginFactory->createFromArrayConfiguration($pluginConfiguration);
|
||||
$pluginPriority = $pluginConfiguration['priority'] ?? self::DEFAULT_PLUGIN_PRIORITY;
|
||||
if (!$adapter->hasPlugin($plugin)) {
|
||||
$adapter->addPlugin($plugin, $pluginPriority);
|
||||
}
|
||||
}
|
||||
|
||||
return $adapter;
|
||||
}
|
||||
|
||||
public function assertValidConfigurationStructure(array $configuration): void
|
||||
{
|
||||
try {
|
||||
Assert::isNonEmptyMap($configuration, 'Configuration must be a non-empty array.');
|
||||
$adapter = $configuration['adapter'] ?? $configuration['name'] ?? null;
|
||||
if (!\is_string($adapter)) {
|
||||
throw new \InvalidArgumentException('Configuration must contain a "adapter" key.');
|
||||
}
|
||||
Assert::stringNotEmpty($adapter, 'Storage "adapter" has to be a non-empty string.');
|
||||
Assert::nullOrIsMap($configuration['options'] ?? null, 'Storage "options" must be an array with string keys.');
|
||||
if (isset($configuration['plugins'])) {
|
||||
Assert::isList($configuration['plugins'], 'Storage "plugins" must be a list of plugin configurations.');
|
||||
$this->assertValidPluginConfigurationStructure($adapter, $configuration['plugins']);
|
||||
}
|
||||
} catch (\InvalidArgumentException $exception) {
|
||||
throw new Exception\InvalidArgumentException($exception->getMessage(), 0, $exception);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-param non-empty-string $adapter
|
||||
* @psalm-param list<mixed> $plugins
|
||||
*
|
||||
* @psalm-assert list<PluginArrayConfigurationWithPriorityType> $plugins
|
||||
*/
|
||||
private function assertValidPluginConfigurationStructure(string $adapter, array $plugins): void
|
||||
{
|
||||
Assert::allIsArray($plugins, 'All plugin configurations are expected to be an array.');
|
||||
foreach ($plugins as $pluginConfiguration) {
|
||||
try {
|
||||
$this->pluginFactory->assertValidConfigurationStructure($pluginConfiguration);
|
||||
if (isset($pluginConfiguration['priority'])) {
|
||||
Assert::integer($pluginConfiguration['priority'], 'Plugin priority has to be integer.');
|
||||
}
|
||||
} catch (Exception\InvalidArgumentException|\InvalidArgumentException $exception) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Plugin configuration for adapter "%s" is invalid: %s', $adapter, $exception->getMessage()), 0, $exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\AdapterPluginManager;
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
final class StorageAdapterFactoryFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container): StorageAdapterFactory
|
||||
{
|
||||
return new StorageAdapterFactory($container->get(AdapterPluginManager::class), $container->get(StoragePluginFactoryInterface::class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\InvalidArgumentException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
|
||||
/**
|
||||
* @psalm-type InternalOptionalPriorityConfigurationType = array{priority?:int}
|
||||
* NOTE: have to re-declare this here until https://github.com/vimeo/psalm/issues/5148 is fixed.
|
||||
* @psalm-type InternalPluginArrayConfigurationType = array{name:non-empty-string,options?:array<string,mixed>}
|
||||
* @psalm-type PluginArrayConfigurationWithPriorityType =
|
||||
* InternalPluginArrayConfigurationType&InternalOptionalPriorityConfigurationType
|
||||
* @psalm-type StorageAdapterArrayConfigurationType = array{
|
||||
* name:non-empty-string,
|
||||
* options?:array<string,mixed>,
|
||||
* plugins?: list<PluginArrayConfigurationWithPriorityType>
|
||||
* }|array{
|
||||
* adapter:non-empty-string,
|
||||
* options?:array<string,mixed>,
|
||||
* plugins?: list<PluginArrayConfigurationWithPriorityType>
|
||||
* }
|
||||
*/
|
||||
interface StorageAdapterFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @psalm-param StorageAdapterArrayConfigurationType $configuration
|
||||
*/
|
||||
public function createFromArrayConfiguration(array $configuration): StorageInterface;
|
||||
|
||||
/**
|
||||
* @psalm-param non-empty-string $storage
|
||||
*
|
||||
* @param array<string,mixed> $options
|
||||
*
|
||||
* @psalm-param list<PluginArrayConfigurationWithPriorityType> $plugins
|
||||
*/
|
||||
public function create(string $storage, array $options = [], array $plugins = []): StorageInterface;
|
||||
|
||||
/**
|
||||
* @param array<mixed> $configuration
|
||||
*
|
||||
* @psalm-assert StorageAdapterArrayConfigurationType $configuration
|
||||
*
|
||||
* @throws InvalidArgumentException if the provided configuration is invalid
|
||||
*/
|
||||
public function assertValidConfigurationStructure(array $configuration): void;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\AdapterPluginManager;
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
final class StorageAdapterPluginManagerFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container): AdapterPluginManager
|
||||
{
|
||||
return new AdapterPluginManager($container);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Interop\Container\ContainerInterface;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\Factory\AbstractFactoryInterface;
|
||||
use _JchOptimizeVendor\Webmozart\Assert\Assert;
|
||||
|
||||
/**
|
||||
* Storage cache factory for multiple caches.
|
||||
*/
|
||||
class StorageCacheAbstractServiceFactory implements AbstractFactoryInterface
|
||||
{
|
||||
public const CACHES_CONFIGURATION_KEY = 'caches';
|
||||
|
||||
/** @var null|array<string,mixed> */
|
||||
protected $config;
|
||||
|
||||
/**
|
||||
* Configuration key for cache objects.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $configKey = self::CACHES_CONFIGURATION_KEY;
|
||||
|
||||
/**
|
||||
* Create an object.
|
||||
*
|
||||
* @param string $requestedName
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
|
||||
{
|
||||
$config = $this->getConfig($container);
|
||||
$factory = $container->get(StorageAdapterFactoryInterface::class);
|
||||
\assert($factory instanceof StorageAdapterFactoryInterface);
|
||||
$configForRequestedName = $config[$requestedName] ?? [];
|
||||
Assert::isMap($configForRequestedName);
|
||||
$factory->assertValidConfigurationStructure($configForRequestedName);
|
||||
|
||||
return $factory->createFromArrayConfiguration($configForRequestedName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $requestedName
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function canCreate(ContainerInterface $container, $requestedName)
|
||||
{
|
||||
$config = $this->getConfig($container);
|
||||
if (empty($config)) {
|
||||
return \false;
|
||||
}
|
||||
|
||||
return isset($config[$requestedName]) && \is_array($config[$requestedName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve cache configuration, if any.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function getConfig(ContainerInterface $container)
|
||||
{
|
||||
if (null !== $this->config) {
|
||||
return $this->config;
|
||||
}
|
||||
if (!$container->has('config')) {
|
||||
$this->config = [];
|
||||
|
||||
return $this->config;
|
||||
}
|
||||
$config = $container->get('config');
|
||||
Assert::isArrayAccessible($config);
|
||||
if (!isset($config[$this->configKey])) {
|
||||
$this->config = [];
|
||||
|
||||
return $this->config;
|
||||
}
|
||||
$cacheConfigurations = $config[$this->configKey];
|
||||
Assert::isMap($cacheConfigurations);
|
||||
|
||||
return $this->config = $cacheConfigurations;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
use _JchOptimizeVendor\Webmozart\Assert\Assert;
|
||||
|
||||
final class StorageCacheFactory
|
||||
{
|
||||
public const CACHE_CONFIGURATION_KEY = 'cache';
|
||||
|
||||
public function __invoke(ContainerInterface $container): StorageInterface
|
||||
{
|
||||
$config = $container->get('config');
|
||||
Assert::isArrayAccessible($config);
|
||||
$cacheConfig = $config['cache'] ?? [];
|
||||
Assert::isMap($cacheConfig);
|
||||
$factory = $container->get(StorageAdapterFactoryInterface::class);
|
||||
\assert($factory instanceof StorageAdapterFactoryInterface);
|
||||
$factory->assertValidConfigurationStructure($cacheConfig);
|
||||
|
||||
return $factory->createFromArrayConfiguration($cacheConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\InvalidArgumentException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Plugin\PluginInterface;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\PluginManagerInterface;
|
||||
use _JchOptimizeVendor\Webmozart\Assert\Assert;
|
||||
use InvalidArgumentException as PhpInvalidArgumentException;
|
||||
|
||||
final class StoragePluginFactory implements StoragePluginFactoryInterface
|
||||
{
|
||||
/** @var PluginManagerInterface */
|
||||
private $plugins;
|
||||
|
||||
public function __construct(PluginManagerInterface $plugins)
|
||||
{
|
||||
$this->plugins = $plugins;
|
||||
}
|
||||
|
||||
public function createFromArrayConfiguration(array $configuration): PluginInterface
|
||||
{
|
||||
$name = $configuration['name'];
|
||||
$options = $configuration['options'] ?? [];
|
||||
|
||||
return $this->create($name, $options);
|
||||
}
|
||||
|
||||
public function create(string $plugin, array $options = []): PluginInterface
|
||||
{
|
||||
$instance = $this->plugins->build($plugin, $options);
|
||||
\assert($instance instanceof PluginInterface);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
public function assertValidConfigurationStructure(array $configuration): void
|
||||
{
|
||||
try {
|
||||
Assert::isNonEmptyMap($configuration, 'Configuration must be a non-empty array.');
|
||||
Assert::keyExists($configuration, 'name', 'Configuration must contain a "name" key.');
|
||||
Assert::stringNotEmpty($configuration['name'], 'Plugin "name" has to be a non-empty string.');
|
||||
Assert::nullOrIsMap($configuration['options'] ?? null, 'Plugin "options" must be an array with string keys.');
|
||||
} catch (PhpInvalidArgumentException $exception) {
|
||||
throw new InvalidArgumentException($exception->getMessage(), 0, $exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PluginManager;
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
final class StoragePluginFactoryFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container): StoragePluginFactory
|
||||
{
|
||||
return new StoragePluginFactory($container->get(PluginManager::class));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\InvalidArgumentException;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Plugin\PluginInterface;
|
||||
|
||||
/**
|
||||
* @psalm-type PluginArrayConfigurationType = array{name:non-empty-string,options?:array<string,mixed>}
|
||||
*/
|
||||
interface StoragePluginFactoryInterface
|
||||
{
|
||||
/**
|
||||
* @psalm-param PluginArrayConfigurationType $configuration
|
||||
*/
|
||||
public function createFromArrayConfiguration(array $configuration): PluginInterface;
|
||||
|
||||
/**
|
||||
* @psalm-param non-empty-string $plugin
|
||||
*
|
||||
* @param array<string,mixed> $options
|
||||
*
|
||||
* @psalm-param array<string,mixed> $options
|
||||
*/
|
||||
public function create(string $plugin, array $options = []): PluginInterface;
|
||||
|
||||
/**
|
||||
* @param array<mixed> $configuration
|
||||
*
|
||||
* @psalm-assert PluginArrayConfigurationType $configuration
|
||||
*
|
||||
* @throws InvalidArgumentException if the provided configuration is invalid
|
||||
*/
|
||||
public function assertValidConfigurationStructure(array $configuration): void;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Service;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PluginManager;
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
final class StoragePluginManagerFactory
|
||||
{
|
||||
public function __invoke(ContainerInterface $container): PluginManager
|
||||
{
|
||||
return new PluginManager($container);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,327 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Event;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventsCapableInterface;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\AbstractOptions;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\ErrorHandler;
|
||||
|
||||
/**
|
||||
* Unless otherwise marked, all options in this class affect all adapters.
|
||||
*/
|
||||
class AdapterOptions extends AbstractOptions
|
||||
{
|
||||
// @codingStandardsIgnoreStart
|
||||
/**
|
||||
* Prioritized properties ordered by prio to be set first
|
||||
* in case a bulk of options sets set at once.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $__prioritizedProperties__ = [];
|
||||
// @codingStandardsIgnoreEnd
|
||||
/**
|
||||
* The adapter using these options.
|
||||
*
|
||||
* @var null|StorageInterface
|
||||
*/
|
||||
protected $adapter;
|
||||
|
||||
/**
|
||||
* Validate key against pattern.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $keyPattern = '';
|
||||
|
||||
/**
|
||||
* Namespace option.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'laminascache';
|
||||
|
||||
/**
|
||||
* Readable option.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $readable = \true;
|
||||
|
||||
/**
|
||||
* TTL option.
|
||||
*
|
||||
* @var float|int 0 means infinite or maximum of adapter
|
||||
*/
|
||||
protected $ttl = 0;
|
||||
|
||||
/**
|
||||
* Writable option.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $writable = \true;
|
||||
|
||||
/**
|
||||
* Adapter using this instance.
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*/
|
||||
public function setAdapter(?StorageInterface $adapter = null)
|
||||
{
|
||||
$this->adapter = $adapter;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set key pattern.
|
||||
*
|
||||
* @param string $keyPattern
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setKeyPattern($keyPattern)
|
||||
{
|
||||
$keyPattern = (string) $keyPattern;
|
||||
if ($this->keyPattern !== $keyPattern) {
|
||||
// validate pattern
|
||||
if ('' !== $keyPattern) {
|
||||
ErrorHandler::start(\E_WARNING);
|
||||
$result = \preg_match($keyPattern, '');
|
||||
$error = ErrorHandler::stop();
|
||||
if (\false === $result) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Invalid pattern "%s"%s', $keyPattern, $error ? ': '.$error->getMessage() : ''), 0, $error);
|
||||
}
|
||||
}
|
||||
$this->triggerOptionEvent('key_pattern', $keyPattern);
|
||||
$this->keyPattern = $keyPattern;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get key pattern.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getKeyPattern()
|
||||
{
|
||||
return $this->keyPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set namespace.
|
||||
*
|
||||
* @param string $namespace
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*/
|
||||
public function setNamespace($namespace)
|
||||
{
|
||||
$namespace = (string) $namespace;
|
||||
if ($this->namespace !== $namespace) {
|
||||
$this->triggerOptionEvent('namespace', $namespace);
|
||||
$this->namespace = $namespace;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get namespace.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable reading data from cache.
|
||||
*
|
||||
* @param bool $readable
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*/
|
||||
public function setReadable($readable)
|
||||
{
|
||||
$readable = (bool) $readable;
|
||||
if ($this->readable !== $readable) {
|
||||
$this->triggerOptionEvent('readable', $readable);
|
||||
$this->readable = $readable;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If reading data from cache enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getReadable()
|
||||
{
|
||||
return $this->readable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time to live.
|
||||
*
|
||||
* @param float|int $ttl
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*/
|
||||
public function setTtl($ttl)
|
||||
{
|
||||
$this->normalizeTtl($ttl);
|
||||
if ($this->ttl !== $ttl) {
|
||||
$this->triggerOptionEvent('ttl', $ttl);
|
||||
$this->ttl = $ttl;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time to live.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getTtl()
|
||||
{
|
||||
return $this->ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable writing data to cache.
|
||||
*
|
||||
* @param bool $writable
|
||||
*
|
||||
* @return AdapterOptions Provides a fluent interface
|
||||
*/
|
||||
public function setWritable($writable)
|
||||
{
|
||||
$writable = (bool) $writable;
|
||||
if ($this->writable !== $writable) {
|
||||
$this->triggerOptionEvent('writable', $writable);
|
||||
$this->writable = $writable;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* If writing data to cache enabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getWritable()
|
||||
{
|
||||
return $this->writable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cast to array.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function toArray()
|
||||
{
|
||||
$array = [];
|
||||
$transform = function ($letters) {
|
||||
$letter = \array_shift($letters);
|
||||
|
||||
return '_'.\strtolower($letter);
|
||||
};
|
||||
foreach ($this as $key => $value) {
|
||||
if ('__strictMode__' === $key || '__prioritizedProperties__' === $key) {
|
||||
continue;
|
||||
}
|
||||
$normalizedKey = \preg_replace_callback('/([A-Z])/', $transform, $key);
|
||||
$array[$normalizedKey] = $value;
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* NOTE: This method was overwritten just to support prioritized properties
|
||||
* {@link https://github.com/zendframework/zf2/issues/6381}
|
||||
*
|
||||
* @param AbstractOptions|array|\Traversable $options
|
||||
*
|
||||
* @return AbstractOptions Provides fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setFromArray($options)
|
||||
{
|
||||
if ($this->__prioritizedProperties__) {
|
||||
if ($options instanceof AbstractOptions) {
|
||||
$options = $options->toArray();
|
||||
}
|
||||
if ($options instanceof \Traversable) {
|
||||
$options = \iterator_to_array($options);
|
||||
} elseif (!\is_array($options)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Parameter provided to %s must be an %s, %s or %s', __METHOD__, 'array', 'Traversable', AbstractOptions::class));
|
||||
}
|
||||
// Sort prioritized options to top
|
||||
$options = \array_change_key_case($options, \CASE_LOWER);
|
||||
foreach (\array_reverse($this->__prioritizedProperties__) as $key) {
|
||||
if (isset($options[$key])) {
|
||||
$options = [$key => $options[$key]] + $options;
|
||||
} elseif (isset($options[$key = \str_replace('_', '', $key)])) {
|
||||
$options = [$key => $options[$key]] + $options;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parent::setFromArray($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Triggers an option event if this options instance has a connection to
|
||||
* an adapter implements EventsCapableInterface.
|
||||
*
|
||||
* @param string $optionName
|
||||
* @param mixed $optionValue
|
||||
*/
|
||||
protected function triggerOptionEvent($optionName, $optionValue)
|
||||
{
|
||||
if ($this->adapter instanceof EventsCapableInterface) {
|
||||
$event = new Event('option', $this->adapter, new \ArrayObject([$optionName => $optionValue]));
|
||||
$this->adapter->getEventManager()->triggerEvent($event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and normalize a TTL.
|
||||
*
|
||||
* @param float|int $ttl
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
protected function normalizeTtl(&$ttl)
|
||||
{
|
||||
if (!\is_int($ttl)) {
|
||||
$ttl = (float) $ttl;
|
||||
// convert to int if possible
|
||||
if ($ttl === (float) (int) $ttl) {
|
||||
$ttl = (int) $ttl;
|
||||
}
|
||||
}
|
||||
if ($ttl < 0) {
|
||||
throw new Exception\InvalidArgumentException("TTL can't be negative");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Adapter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\IteratorInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use ReturnTypeWillChange;
|
||||
|
||||
use function count;
|
||||
|
||||
/**
|
||||
* @see ReturnTypeWillChange
|
||||
*/
|
||||
class KeyListIterator implements IteratorInterface, \Countable
|
||||
{
|
||||
/**
|
||||
* The storage instance.
|
||||
*
|
||||
* @var StorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* The iterator mode.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $mode = IteratorInterface::CURRENT_AS_KEY;
|
||||
|
||||
/**
|
||||
* Keys to iterate over.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $keys;
|
||||
|
||||
/**
|
||||
* Number of keys.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $count;
|
||||
|
||||
/**
|
||||
* Current iterator position.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $position = 0;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(StorageInterface $storage, array $keys)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
$this->keys = $keys;
|
||||
$this->count = \count($keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage instance.
|
||||
*
|
||||
* @return StorageInterface
|
||||
*/
|
||||
public function getStorage()
|
||||
{
|
||||
return $this->storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get iterator mode.
|
||||
*
|
||||
* @return int Value of IteratorInterface::CURRENT_AS_*
|
||||
*/
|
||||
public function getMode()
|
||||
{
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set iterator mode.
|
||||
*
|
||||
* @param int $mode
|
||||
*
|
||||
* @return KeyListIterator Provides a fluent interface
|
||||
*/
|
||||
public function setMode($mode)
|
||||
{
|
||||
$this->mode = (int) $mode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current key, value or metadata.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function current()
|
||||
{
|
||||
if (IteratorInterface::CURRENT_AS_SELF === $this->mode) {
|
||||
return $this;
|
||||
}
|
||||
$key = $this->key();
|
||||
if (IteratorInterface::CURRENT_AS_METADATA === $this->mode) {
|
||||
return $this->storage->getMetadata($key);
|
||||
}
|
||||
if (IteratorInterface::CURRENT_AS_VALUE === $this->mode) {
|
||||
return $this->storage->getItem($key);
|
||||
}
|
||||
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current key.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function key()
|
||||
{
|
||||
return $this->keys[$this->position];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if current position is valid.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function valid()
|
||||
{
|
||||
return $this->position < $this->count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move forward to next element.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function next()
|
||||
{
|
||||
++$this->position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element.
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function rewind()
|
||||
{
|
||||
$this->position = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count number of items.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function count()
|
||||
{
|
||||
return $this->count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\AbstractPluginManager;
|
||||
|
||||
/**
|
||||
* Plugin manager implementation for cache storage adapters.
|
||||
*
|
||||
* Enforces that adapters retrieved are instances of
|
||||
* StorageInterface. Additionally, it registers a number of default
|
||||
* adapters available.
|
||||
*/
|
||||
final class AdapterPluginManager extends AbstractPluginManager
|
||||
{
|
||||
/**
|
||||
* Do not share by default.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $sharedByDefault = \false;
|
||||
|
||||
/** @var string */
|
||||
protected $instanceOf = StorageInterface::class;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface AvailableSpaceCapableInterface
|
||||
{
|
||||
/**
|
||||
* Get available space in bytes.
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
public function getAvailableSpace();
|
||||
}
|
||||
@@ -0,0 +1,520 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventsCapableInterface;
|
||||
|
||||
class Capabilities
|
||||
{
|
||||
public const UNKNOWN_KEY_LENGTH = -1;
|
||||
public const UNLIMITED_KEY_LENGTH = 0;
|
||||
|
||||
/**
|
||||
* The storage instance.
|
||||
*
|
||||
* @var StorageInterface
|
||||
*/
|
||||
protected $storage;
|
||||
|
||||
/**
|
||||
* A marker to set/change capabilities.
|
||||
*
|
||||
* @var \stdClass
|
||||
*/
|
||||
protected $marker;
|
||||
|
||||
/**
|
||||
* Base capabilities.
|
||||
*
|
||||
* @var null|Capabilities
|
||||
*/
|
||||
protected $baseCapabilities;
|
||||
|
||||
/**
|
||||
* "lock-on-expire" support in seconds.
|
||||
*
|
||||
* 0 = Expired items will never be retrieved
|
||||
* >0 = Time in seconds an expired item could be retrieved
|
||||
* -1 = Expired items could be retrieved forever
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
protected $lockOnExpire;
|
||||
|
||||
/**
|
||||
* Max. key length.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
protected $maxKeyLength;
|
||||
|
||||
/**
|
||||
* Min. TTL (0 means items never expire).
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
protected $minTtl;
|
||||
|
||||
/**
|
||||
* Max. TTL (0 means infinite).
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
protected $maxTtl;
|
||||
|
||||
/**
|
||||
* Namespace is prefix.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
protected $namespaceIsPrefix;
|
||||
|
||||
/**
|
||||
* Namespace separator.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|string
|
||||
*/
|
||||
protected $namespaceSeparator;
|
||||
|
||||
/**
|
||||
* Static ttl.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
protected $staticTtl;
|
||||
|
||||
/**
|
||||
* Supported datatypes.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
protected $supportedDatatypes;
|
||||
|
||||
/**
|
||||
* Supported metadata.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|array
|
||||
*/
|
||||
protected $supportedMetadata;
|
||||
|
||||
/**
|
||||
* TTL precision.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|int
|
||||
*/
|
||||
protected $ttlPrecision;
|
||||
|
||||
/**
|
||||
* Use request time.
|
||||
*
|
||||
* If it's NULL the capability isn't set and the getter
|
||||
* returns the base capability or the default value.
|
||||
*
|
||||
* @var null|bool
|
||||
*/
|
||||
protected $useRequestTime;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct(StorageInterface $storage, \stdClass $marker, array $capabilities = [], ?Capabilities $baseCapabilities = null)
|
||||
{
|
||||
$this->storage = $storage;
|
||||
$this->marker = $marker;
|
||||
$this->baseCapabilities = $baseCapabilities;
|
||||
foreach ($capabilities as $name => $value) {
|
||||
$this->setCapability($marker, $name, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the storage adapter.
|
||||
*
|
||||
* @return StorageInterface
|
||||
*/
|
||||
public function getAdapter()
|
||||
{
|
||||
return $this->storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported datatypes.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedDatatypes()
|
||||
{
|
||||
return $this->getCapability('supportedDatatypes', ['NULL' => \false, 'boolean' => \false, 'integer' => \false, 'double' => \false, 'string' => \true, 'array' => \false, 'object' => \false, 'resource' => \false]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set supported datatypes.
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setSupportedDatatypes(\stdClass $marker, array $datatypes)
|
||||
{
|
||||
$allTypes = ['array', 'boolean', 'double', 'integer', 'NULL', 'object', 'resource', 'string'];
|
||||
// check/normalize datatype values
|
||||
foreach ($datatypes as $type => &$toType) {
|
||||
if (!\in_array($type, $allTypes)) {
|
||||
throw new Exception\InvalidArgumentException("Unknown datatype '{$type}'");
|
||||
}
|
||||
if (\is_string($toType)) {
|
||||
$toType = \strtolower($toType);
|
||||
if (!\in_array($toType, $allTypes)) {
|
||||
throw new Exception\InvalidArgumentException("Unknown datatype '{$toType}'");
|
||||
}
|
||||
} else {
|
||||
$toType = (bool) $toType;
|
||||
}
|
||||
}
|
||||
// add missing datatypes as not supported
|
||||
$missingTypes = \array_diff($allTypes, \array_keys($datatypes));
|
||||
foreach ($missingTypes as $type) {
|
||||
$datatypes[$type] = \false;
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'supportedDatatypes', $datatypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get supported metadata.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSupportedMetadata()
|
||||
{
|
||||
return $this->getCapability('supportedMetadata', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set supported metadata.
|
||||
*
|
||||
* @param string[] $metadata
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setSupportedMetadata(\stdClass $marker, array $metadata)
|
||||
{
|
||||
foreach ($metadata as $name) {
|
||||
if (!\is_string($name)) {
|
||||
throw new Exception\InvalidArgumentException('$metadata must be an array of strings');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'supportedMetadata', $metadata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get minimum supported time-to-live.
|
||||
*
|
||||
* @return int 0 means items never expire
|
||||
*/
|
||||
public function getMinTtl()
|
||||
{
|
||||
return $this->getCapability('minTtl', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set minimum supported time-to-live.
|
||||
*
|
||||
* @param int $minTtl
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setMinTtl(\stdClass $marker, $minTtl)
|
||||
{
|
||||
$minTtl = (int) $minTtl;
|
||||
if ($minTtl < 0) {
|
||||
throw new Exception\InvalidArgumentException('$minTtl must be greater or equal 0');
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'minTtl', $minTtl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum supported time-to-live.
|
||||
*
|
||||
* @return int 0 means infinite
|
||||
*/
|
||||
public function getMaxTtl()
|
||||
{
|
||||
return $this->getCapability('maxTtl', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum supported time-to-live.
|
||||
*
|
||||
* @param int $maxTtl
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setMaxTtl(\stdClass $marker, $maxTtl)
|
||||
{
|
||||
$maxTtl = (int) $maxTtl;
|
||||
if ($maxTtl < 0) {
|
||||
throw new Exception\InvalidArgumentException('$maxTtl must be greater or equal 0');
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'maxTtl', $maxTtl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the time-to-live handled static (on write)
|
||||
* or dynamic (on read).
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getStaticTtl()
|
||||
{
|
||||
return $this->getCapability('staticTtl', \false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if the time-to-live handled static (on write) or dynamic (on read).
|
||||
*
|
||||
* @param bool $flag
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*/
|
||||
public function setStaticTtl(\stdClass $marker, $flag)
|
||||
{
|
||||
return $this->setCapability($marker, 'staticTtl', (bool) $flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get time-to-live precision.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getTtlPrecision()
|
||||
{
|
||||
return $this->getCapability('ttlPrecision', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set time-to-live precision.
|
||||
*
|
||||
* @param float $ttlPrecision
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setTtlPrecision(\stdClass $marker, $ttlPrecision)
|
||||
{
|
||||
$ttlPrecision = (float) $ttlPrecision;
|
||||
if ($ttlPrecision <= 0) {
|
||||
throw new Exception\InvalidArgumentException('$ttlPrecision must be greater than 0');
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'ttlPrecision', $ttlPrecision);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get use request time.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getUseRequestTime()
|
||||
{
|
||||
return $this->getCapability('useRequestTime', \false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set use request time.
|
||||
*
|
||||
* @param bool $flag
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*/
|
||||
public function setUseRequestTime(\stdClass $marker, $flag)
|
||||
{
|
||||
return $this->setCapability($marker, 'useRequestTime', (bool) $flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "lock-on-expire" support in seconds.
|
||||
*
|
||||
* @return int 0 = Expired items will never be retrieved
|
||||
* >0 = Time in seconds an expired item could be retrieved
|
||||
* -1 = Expired items could be retrieved forever
|
||||
*/
|
||||
public function getLockOnExpire()
|
||||
{
|
||||
return $this->getCapability('lockOnExpire', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set "lock-on-expire" support in seconds.
|
||||
*
|
||||
* @param int $timeout
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*/
|
||||
public function setLockOnExpire(\stdClass $marker, $timeout)
|
||||
{
|
||||
return $this->setCapability($marker, 'lockOnExpire', (int) $timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get maximum key length.
|
||||
*
|
||||
* @return int -1 means unknown, 0 means infinite
|
||||
*/
|
||||
public function getMaxKeyLength()
|
||||
{
|
||||
return $this->getCapability('maxKeyLength', self::UNKNOWN_KEY_LENGTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set maximum key length.
|
||||
*
|
||||
* @param int $maxKeyLength
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setMaxKeyLength(\stdClass $marker, $maxKeyLength)
|
||||
{
|
||||
$maxKeyLength = (int) $maxKeyLength;
|
||||
if ($maxKeyLength < -1) {
|
||||
throw new Exception\InvalidArgumentException('$maxKeyLength must be greater or equal than -1');
|
||||
}
|
||||
|
||||
return $this->setCapability($marker, 'maxKeyLength', $maxKeyLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if namespace support is implemented as prefix.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getNamespaceIsPrefix()
|
||||
{
|
||||
return $this->getCapability('namespaceIsPrefix', \true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set if namespace support is implemented as prefix.
|
||||
*
|
||||
* @param bool $flag
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*/
|
||||
public function setNamespaceIsPrefix(\stdClass $marker, $flag)
|
||||
{
|
||||
return $this->setCapability($marker, 'namespaceIsPrefix', (bool) $flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get namespace separator if namespace is implemented as prefix.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNamespaceSeparator()
|
||||
{
|
||||
return $this->getCapability('namespaceSeparator', '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the namespace separator if namespace is implemented as prefix.
|
||||
*
|
||||
* @param string $separator
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*/
|
||||
public function setNamespaceSeparator(\stdClass $marker, $separator)
|
||||
{
|
||||
return $this->setCapability($marker, 'namespaceSeparator', (string) $separator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a capability.
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getCapability($property, $default = null)
|
||||
{
|
||||
if (null !== $this->{$property}) {
|
||||
return $this->{$property};
|
||||
}
|
||||
if ($this->baseCapabilities) {
|
||||
$getMethod = 'get'.$property;
|
||||
|
||||
return $this->baseCapabilities->{$getMethod}();
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change a capability.
|
||||
*
|
||||
* @param string $property
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return Capabilities Fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
protected function setCapability(\stdClass $marker, $property, $value)
|
||||
{
|
||||
if ($this->marker !== $marker) {
|
||||
throw new Exception\InvalidArgumentException('Invalid marker');
|
||||
}
|
||||
if ($this->{$property} !== $value) {
|
||||
$this->{$property} = $value;
|
||||
// trigger event
|
||||
if ($this->storage instanceof EventsCapableInterface) {
|
||||
$this->storage->getEventManager()->trigger('capability', $this->storage, new \ArrayObject([$property => $value]));
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface ClearByNamespaceInterface
|
||||
{
|
||||
/**
|
||||
* Remove items of given namespace.
|
||||
*
|
||||
* @param string $namespace
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clearByNamespace($namespace);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface ClearByPrefixInterface
|
||||
{
|
||||
/**
|
||||
* Remove items matching given prefix.
|
||||
*
|
||||
* @param string $prefix
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clearByPrefix($prefix);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface ClearExpiredInterface
|
||||
{
|
||||
/**
|
||||
* Remove expired items.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clearExpired();
|
||||
}
|
||||
58
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/Storage/Event.php
vendored
Normal file
58
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-cache/src/Storage/Event.php
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\Event as BaseEvent;
|
||||
|
||||
class Event extends BaseEvent
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Accept a storage adapter and its parameters.
|
||||
*
|
||||
* @param string $name Event name
|
||||
*/
|
||||
public function __construct($name, StorageInterface $storage, \ArrayObject $params)
|
||||
{
|
||||
parent::__construct($name, $storage, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event target/context.
|
||||
*
|
||||
* @see Laminas\EventManager\Event::setTarget()
|
||||
*
|
||||
* @param StorageInterface $target
|
||||
*
|
||||
* @return Event
|
||||
*/
|
||||
public function setTarget($target)
|
||||
{
|
||||
return $this->setStorage($target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of setTarget.
|
||||
*
|
||||
* @see Laminas\EventManager\Event::setTarget()
|
||||
*
|
||||
* @return Event
|
||||
*/
|
||||
public function setStorage(StorageInterface $storage)
|
||||
{
|
||||
$this->target = $storage;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias of getTarget.
|
||||
*
|
||||
* @return StorageInterface
|
||||
*/
|
||||
public function getStorage()
|
||||
{
|
||||
return $this->getTarget();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use Exception;
|
||||
|
||||
class ExceptionEvent extends PostEvent
|
||||
{
|
||||
/**
|
||||
* The exception to be thrown.
|
||||
*
|
||||
* @var \Exception
|
||||
*/
|
||||
protected $exception;
|
||||
|
||||
/**
|
||||
* Throw the exception or use the result.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $throwException = \true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Accept a target and its parameters.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $result
|
||||
*/
|
||||
public function __construct($name, StorageInterface $storage, \ArrayObject $params, &$result, \Exception $exception)
|
||||
{
|
||||
parent::__construct($name, $storage, $params, $result);
|
||||
$this->setException($exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the exception to be thrown.
|
||||
*
|
||||
* @return ExceptionEvent
|
||||
*/
|
||||
public function setException(\Exception $exception)
|
||||
{
|
||||
$this->exception = $exception;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the exception to be thrown.
|
||||
*
|
||||
* @return \Exception
|
||||
*/
|
||||
public function getException()
|
||||
{
|
||||
return $this->exception;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the exception or use the result.
|
||||
*
|
||||
* @param bool $flag
|
||||
*
|
||||
* @return ExceptionEvent
|
||||
*/
|
||||
public function setThrowException($flag)
|
||||
{
|
||||
$this->throwException = (bool) $flag;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw the exception or use the result.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getThrowException()
|
||||
{
|
||||
return $this->throwException;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface FlushableInterface
|
||||
{
|
||||
/**
|
||||
* Flush the whole storage.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function flush();
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
/**
|
||||
* @method IteratorInterface getIterator() Get the storage iterator
|
||||
*/
|
||||
interface IterableInterface extends \IteratorAggregate
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use Iterator;
|
||||
|
||||
interface IteratorInterface extends \Iterator
|
||||
{
|
||||
public const CURRENT_AS_SELF = 0;
|
||||
public const CURRENT_AS_KEY = 1;
|
||||
public const CURRENT_AS_VALUE = 2;
|
||||
public const CURRENT_AS_METADATA = 3;
|
||||
|
||||
/**
|
||||
* Get storage instance.
|
||||
*
|
||||
* @return StorageInterface
|
||||
*/
|
||||
public function getStorage();
|
||||
|
||||
/**
|
||||
* Get iterator mode.
|
||||
*
|
||||
* @return int Value of IteratorInterface::CURRENT_AS_*
|
||||
*/
|
||||
public function getMode();
|
||||
|
||||
/**
|
||||
* Set iterator mode.
|
||||
*
|
||||
* @param int $mode Value of IteratorInterface::CURRENT_AS_*
|
||||
*
|
||||
* @return IteratorInterface Fluent interface
|
||||
*/
|
||||
public function setMode($mode);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface OptimizableInterface
|
||||
{
|
||||
/**
|
||||
* Optimize the storage.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function optimize();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\AbstractListenerAggregate;
|
||||
|
||||
abstract class AbstractPlugin extends AbstractListenerAggregate implements PluginInterface
|
||||
{
|
||||
/** @var PluginOptions */
|
||||
protected $options;
|
||||
|
||||
/**
|
||||
* Set pattern options.
|
||||
*
|
||||
* @return AbstractPlugin Provides a fluent interface
|
||||
*/
|
||||
public function setOptions(PluginOptions $options)
|
||||
{
|
||||
$this->options = $options;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all pattern options.
|
||||
*
|
||||
* @return PluginOptions
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
if (null === $this->options) {
|
||||
$this->setOptions(new PluginOptions());
|
||||
}
|
||||
|
||||
return $this->options;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\ClearExpiredInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PostEvent;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventManagerInterface;
|
||||
|
||||
class ClearExpiredByFactor extends AbstractPlugin
|
||||
{
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
$callback = [$this, 'clearExpiredByFactor'];
|
||||
$this->listeners[] = $events->attach('setItem.post', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('setItems.post', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('addItem.post', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('addItems.post', $callback, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear expired items by factor after writing new item(s).
|
||||
*
|
||||
* @phpcs:disable Generic.NamingConventions.ConstructorName.OldStyle
|
||||
*/
|
||||
public function clearExpiredByFactor(PostEvent $event)
|
||||
{
|
||||
$storage = $event->getStorage();
|
||||
if (!$storage instanceof ClearExpiredInterface) {
|
||||
return;
|
||||
}
|
||||
$factor = $this->getOptions()->getClearingFactor();
|
||||
if ($factor && 1 === \random_int(1, $factor)) {
|
||||
$storage->clearExpired();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\ExceptionEvent;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventManagerInterface;
|
||||
|
||||
class ExceptionHandler extends AbstractPlugin
|
||||
{
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
$callback = [$this, 'onException'];
|
||||
// read
|
||||
$this->listeners[] = $events->attach('getItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('getItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('hasItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('hasItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('getMetadata.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('getMetadatas.exception', $callback, $priority);
|
||||
// write
|
||||
$this->listeners[] = $events->attach('setItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('setItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('addItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('addItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('touchItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('touchItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('removeItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('removeItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('checkAndSetItem.exception', $callback, $priority);
|
||||
// increment / decrement item(s)
|
||||
$this->listeners[] = $events->attach('incrementItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItems.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItem.exception', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItems.exception', $callback, $priority);
|
||||
// utility
|
||||
$this->listeners[] = $events->attach('clearExpired.exception', $callback, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* On exception.
|
||||
*/
|
||||
public function onException(ExceptionEvent $event)
|
||||
{
|
||||
$options = $this->getOptions();
|
||||
$callback = $options->getExceptionCallback();
|
||||
if ($callback) {
|
||||
\call_user_func($callback, $event->getException());
|
||||
}
|
||||
$event->setThrowException($options->getThrowExceptions());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Event;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventManagerInterface;
|
||||
|
||||
use function ignore_user_abort;
|
||||
|
||||
class IgnoreUserAbort extends AbstractPlugin
|
||||
{
|
||||
/**
|
||||
* The storage who activated ignore_user_abort.
|
||||
*
|
||||
* @var null|StorageInterface
|
||||
*/
|
||||
protected $activatedTarget;
|
||||
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
$cbOnBefore = [$this, 'onBefore'];
|
||||
$cbOnAfter = [$this, 'onAfter'];
|
||||
$this->listeners[] = $events->attach('setItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('setItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('setItem.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('setItems.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('setItems.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('setItems.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('addItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('addItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('addItem.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('addItems.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('addItems.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('addItems.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItem.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItems.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItems.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('replaceItems.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('checkAndSetItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('checkAndSetItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('checkAndSetItem.exception', $cbOnAfter, $priority);
|
||||
// increment / decrement item(s)
|
||||
$this->listeners[] = $events->attach('incrementItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItem.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItems.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItems.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('incrementItems.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItem.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItem.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItem.exception', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItems.pre', $cbOnBefore, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItems.post', $cbOnAfter, $priority);
|
||||
$this->listeners[] = $events->attach('decrementItems.exception', $cbOnAfter, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate ignore_user_abort if not already done
|
||||
* and save the target who activated it.
|
||||
*/
|
||||
public function onBefore(Event $event)
|
||||
{
|
||||
if (null === $this->activatedTarget && !\ignore_user_abort(\true)) {
|
||||
$this->activatedTarget = $event->getStorage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset ignore_user_abort if it's activated and if it's the same target
|
||||
* who activated it.
|
||||
*
|
||||
* If exit_on_abort is enabled and the connection has been aborted
|
||||
* exit the script.
|
||||
*/
|
||||
public function onAfter(Event $event)
|
||||
{
|
||||
if ($this->activatedTarget === $event->getStorage()) {
|
||||
// exit if connection aborted
|
||||
if ($this->getOptions()->getExitOnAbort() && \connection_aborted()) {
|
||||
exit;
|
||||
}
|
||||
// reset ignore_user_abort
|
||||
\ignore_user_abort(\false);
|
||||
// remove activated target
|
||||
$this->activatedTarget = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\OptimizableInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PostEvent;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventManagerInterface;
|
||||
|
||||
class OptimizeByFactor extends AbstractPlugin
|
||||
{
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
$callback = [$this, 'optimizeByFactor'];
|
||||
$this->listeners[] = $events->attach('removeItem.post', $callback, $priority);
|
||||
$this->listeners[] = $events->attach('removeItems.post', $callback, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Optimize by factor on a success _RESULT_.
|
||||
*
|
||||
* @phpcs:disable Generic.NamingConventions.ConstructorName.OldStyle
|
||||
*/
|
||||
public function optimizeByFactor(PostEvent $event)
|
||||
{
|
||||
$storage = $event->getStorage();
|
||||
if (!$storage instanceof OptimizableInterface) {
|
||||
return;
|
||||
}
|
||||
$factor = $this->getOptions()->getOptimizingFactor();
|
||||
if ($factor && 1 === \random_int(1, $factor)) {
|
||||
$storage->optimize();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\ListenerAggregateInterface;
|
||||
|
||||
interface PluginInterface extends ListenerAggregateInterface
|
||||
{
|
||||
/**
|
||||
* Set options.
|
||||
*
|
||||
* @return PluginInterface
|
||||
*/
|
||||
public function setOptions(PluginOptions $options);
|
||||
|
||||
/**
|
||||
* Get options.
|
||||
*
|
||||
* @return PluginOptions
|
||||
*/
|
||||
public function getOptions();
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Serializer\Adapter\AdapterInterface as SerializerAdapter;
|
||||
use _JchOptimizeVendor\Laminas\Serializer\Serializer as SerializerFactory;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\AbstractOptions;
|
||||
|
||||
class PluginOptions extends AbstractOptions
|
||||
{
|
||||
/**
|
||||
* Used by:
|
||||
* - ClearByFactor.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $clearingFactor = 0;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ExceptionHandler.
|
||||
*
|
||||
* @var null|callable
|
||||
*/
|
||||
protected $exceptionCallback;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - IgnoreUserAbort.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $exitOnAbort = \true;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - OptimizeByFactor.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $optimizingFactor = 0;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - Serializer.
|
||||
*
|
||||
* @var SerializerAdapter|string
|
||||
*/
|
||||
protected $serializer;
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - Serializer.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $serializerOptions = [];
|
||||
|
||||
/**
|
||||
* Used by:
|
||||
* - ExceptionHandler.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $throwExceptions = \true;
|
||||
|
||||
/**
|
||||
* Set automatic clearing factor.
|
||||
*
|
||||
* Used by:
|
||||
* - ClearExpiredByFactor
|
||||
*
|
||||
* @param int $clearingFactor
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*/
|
||||
public function setClearingFactor($clearingFactor)
|
||||
{
|
||||
$this->clearingFactor = $this->normalizeFactor($clearingFactor);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get automatic clearing factor.
|
||||
*
|
||||
* Used by:
|
||||
* - ClearExpiredByFactor
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getClearingFactor()
|
||||
{
|
||||
return $this->clearingFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set callback to call on intercepted exception.
|
||||
*
|
||||
* Used by:
|
||||
* - ExceptionHandler
|
||||
*
|
||||
* @param null|callable $exceptionCallback
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setExceptionCallback($exceptionCallback)
|
||||
{
|
||||
if (null !== $exceptionCallback && !\is_callable($exceptionCallback, \true)) {
|
||||
throw new Exception\InvalidArgumentException('Not a valid callback');
|
||||
}
|
||||
$this->exceptionCallback = $exceptionCallback;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get callback to call on intercepted exception.
|
||||
*
|
||||
* Used by:
|
||||
* - ExceptionHandler
|
||||
*
|
||||
* @return null|callable
|
||||
*/
|
||||
public function getExceptionCallback()
|
||||
{
|
||||
return $this->exceptionCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit if connection aborted and ignore_user_abort is disabled.
|
||||
*
|
||||
* @param bool $exitOnAbort
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*/
|
||||
public function setExitOnAbort($exitOnAbort)
|
||||
{
|
||||
$this->exitOnAbort = (bool) $exitOnAbort;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Exit if connection aborted and ignore_user_abort is disabled.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getExitOnAbort()
|
||||
{
|
||||
return $this->exitOnAbort;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set automatic optimizing factor.
|
||||
*
|
||||
* Used by:
|
||||
* - OptimizeByFactor
|
||||
*
|
||||
* @param int $optimizingFactor
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*/
|
||||
public function setOptimizingFactor($optimizingFactor)
|
||||
{
|
||||
$this->optimizingFactor = $this->normalizeFactor($optimizingFactor);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set automatic optimizing factor.
|
||||
*
|
||||
* Used by:
|
||||
* - OptimizeByFactor
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getOptimizingFactor()
|
||||
{
|
||||
return $this->optimizingFactor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set serializer.
|
||||
*
|
||||
* Used by:
|
||||
* - Serializer
|
||||
*
|
||||
* @param SerializerAdapter|string $serializer
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setSerializer($serializer)
|
||||
{
|
||||
if (!\is_string($serializer) && !$serializer instanceof SerializerAdapter) {
|
||||
/*
|
||||
* @psalm-suppress RedundantConditionGivenDocblockType, DocblockTypeContradiction
|
||||
* Until we do lack native type-hint we should check the `$serializer` twice.
|
||||
*/
|
||||
throw new Exception\InvalidArgumentException(\sprintf('%s expects either a string serializer name or Laminas\\Serializer\\Adapter\\AdapterInterface instance; received "%s"', __METHOD__, \is_object($serializer) ? \get_class($serializer) : \gettype($serializer)));
|
||||
}
|
||||
$this->serializer = $serializer;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get serializer.
|
||||
*
|
||||
* Used by:
|
||||
* - Serializer
|
||||
*
|
||||
* @return SerializerAdapter
|
||||
*/
|
||||
public function getSerializer()
|
||||
{
|
||||
if (!$this->serializer instanceof SerializerAdapter) {
|
||||
// use default serializer
|
||||
if (!$this->serializer) {
|
||||
$this->setSerializer(SerializerFactory::getDefaultAdapter());
|
||||
// instantiate by class name + serializer_options
|
||||
} else {
|
||||
$options = $this->getSerializerOptions();
|
||||
$this->setSerializer(SerializerFactory::factory($this->serializer, $options));
|
||||
}
|
||||
}
|
||||
|
||||
return $this->serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set configuration options for instantiating a serializer adapter.
|
||||
*
|
||||
* Used by:
|
||||
* - Serializer
|
||||
*
|
||||
* @param mixed $serializerOptions
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*/
|
||||
public function setSerializerOptions($serializerOptions)
|
||||
{
|
||||
$this->serializerOptions = $serializerOptions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get configuration options for instantiating a serializer adapter.
|
||||
*
|
||||
* Used by:
|
||||
* - Serializer
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getSerializerOptions()
|
||||
{
|
||||
return $this->serializerOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set flag indicating we should re-throw exceptions.
|
||||
*
|
||||
* Used by:
|
||||
* - ExceptionHandler
|
||||
*
|
||||
* @param bool $throwExceptions
|
||||
*
|
||||
* @return PluginOptions Provides a fluent interface
|
||||
*/
|
||||
public function setThrowExceptions($throwExceptions)
|
||||
{
|
||||
$this->throwExceptions = (bool) $throwExceptions;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Should we re-throw exceptions?
|
||||
*
|
||||
* Used by:
|
||||
* - ExceptionHandler
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function getThrowExceptions()
|
||||
{
|
||||
return $this->throwExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize a factor.
|
||||
*
|
||||
* Cast to int and ensure we have a value greater than zero.
|
||||
*
|
||||
* @param int $factor
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
protected function normalizeFactor($factor)
|
||||
{
|
||||
$factor = (int) $factor;
|
||||
if ($factor < 0) {
|
||||
throw new Exception\InvalidArgumentException("Invalid factor '{$factor}': must be greater or equal 0");
|
||||
}
|
||||
|
||||
return $factor;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage\Plugin;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Capabilities;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Event;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\PostEvent;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\StorageInterface;
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventManagerInterface;
|
||||
|
||||
class Serializer extends AbstractPlugin
|
||||
{
|
||||
/** @var array */
|
||||
protected $capabilities = [];
|
||||
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
// The higher the priority the sooner the plugin will be called on pre events
|
||||
// but the later it will be called on post events.
|
||||
$prePriority = $priority;
|
||||
$postPriority = -$priority;
|
||||
// read
|
||||
$this->listeners[] = $events->attach('getItem.post', [$this, 'onReadItemPost'], $postPriority);
|
||||
$this->listeners[] = $events->attach('getItems.post', [$this, 'onReadItemsPost'], $postPriority);
|
||||
// write
|
||||
$this->listeners[] = $events->attach('setItem.pre', [$this, 'onWriteItemPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('setItems.pre', [$this, 'onWriteItemsPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('addItem.pre', [$this, 'onWriteItemPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('addItems.pre', [$this, 'onWriteItemsPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('replaceItem.pre', [$this, 'onWriteItemPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('replaceItems.pre', [$this, 'onWriteItemsPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('checkAndSetItem.pre', [$this, 'onWriteItemPre'], $prePriority);
|
||||
// increment / decrement item(s)
|
||||
$this->listeners[] = $events->attach('incrementItem.pre', [$this, 'onIncrementItemPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('incrementItems.pre', [$this, 'onIncrementItemsPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('decrementItem.pre', [$this, 'onDecrementItemPre'], $prePriority);
|
||||
$this->listeners[] = $events->attach('decrementItems.pre', [$this, 'onDecrementItemsPre'], $prePriority);
|
||||
// overwrite capabilities
|
||||
$this->listeners[] = $events->attach('getCapabilities.post', [$this, 'onGetCapabilitiesPost'], $postPriority);
|
||||
}
|
||||
|
||||
/**
|
||||
* On read item post.
|
||||
*/
|
||||
public function onReadItemPost(PostEvent $event)
|
||||
{
|
||||
$result = $event->getResult();
|
||||
if (null !== $result) {
|
||||
$serializer = $this->getOptions()->getSerializer();
|
||||
$result = $serializer->unserialize($result);
|
||||
$event->setResult($result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On read items post.
|
||||
*/
|
||||
public function onReadItemsPost(PostEvent $event)
|
||||
{
|
||||
$serializer = $this->getOptions()->getSerializer();
|
||||
$result = $event->getResult();
|
||||
foreach ($result as &$value) {
|
||||
$value = $serializer->unserialize($value);
|
||||
}
|
||||
$event->setResult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* On write item pre.
|
||||
*/
|
||||
public function onWriteItemPre(Event $event)
|
||||
{
|
||||
$serializer = $this->getOptions()->getSerializer();
|
||||
$params = $event->getParams();
|
||||
$params['value'] = $serializer->serialize($params['value']);
|
||||
}
|
||||
|
||||
/**
|
||||
* On write items pre.
|
||||
*/
|
||||
public function onWriteItemsPre(Event $event)
|
||||
{
|
||||
$serializer = $this->getOptions()->getSerializer();
|
||||
$params = $event->getParams();
|
||||
foreach ($params['keyValuePairs'] as &$value) {
|
||||
$value = $serializer->serialize($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* On increment item pre.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function onIncrementItemPre(Event $event)
|
||||
{
|
||||
/** @var StorageInterface $storage */
|
||||
$storage = $event->getTarget();
|
||||
$params = $event->getParams();
|
||||
$casToken = null;
|
||||
$success = null;
|
||||
$oldValue = $storage->getItem($params['key'], $success, $casToken) ?? null;
|
||||
$newValue = $oldValue + $params['value'];
|
||||
$event->stopPropagation(\true);
|
||||
if ($storage->checkAndSetItem($casToken, $params['key'], $oldValue + $params['value'])) {
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
return \false;
|
||||
}
|
||||
|
||||
/**
|
||||
* On increment items pre.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function onIncrementItemsPre(Event $event)
|
||||
{
|
||||
$storage = $event->getTarget();
|
||||
$params = $event->getParams();
|
||||
$keyValuePairs = $storage->getItems(\array_keys($params['keyValuePairs']));
|
||||
foreach ($params['keyValuePairs'] as $key => &$value) {
|
||||
if (isset($keyValuePairs[$key])) {
|
||||
$keyValuePairs[$key] += $value;
|
||||
} else {
|
||||
$keyValuePairs[$key] = $value;
|
||||
}
|
||||
}
|
||||
$failedKeys = $storage->setItems($keyValuePairs);
|
||||
foreach ($failedKeys as $failedKey) {
|
||||
unset($keyValuePairs[$failedKey]);
|
||||
}
|
||||
$event->stopPropagation(\true);
|
||||
|
||||
return $keyValuePairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* On decrement item pre.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function onDecrementItemPre(Event $event)
|
||||
{
|
||||
/** @var StorageInterface $storage */
|
||||
$storage = $event->getTarget();
|
||||
$params = $event->getParams();
|
||||
$success = null;
|
||||
$casToken = null;
|
||||
$oldValue = $storage->getItem($params['key'], $success, $casToken) ?? 0;
|
||||
$newValue = $oldValue - $params['value'];
|
||||
$event->stopPropagation(\true);
|
||||
if ($storage->checkAndSetItem($casToken, $params['key'], $newValue)) {
|
||||
return $newValue;
|
||||
}
|
||||
|
||||
return \false;
|
||||
}
|
||||
|
||||
/**
|
||||
* On decrement items pre.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function onDecrementItemsPre(Event $event)
|
||||
{
|
||||
$storage = $event->getTarget();
|
||||
$params = $event->getParams();
|
||||
$keyValuePairs = $storage->getItems(\array_keys($params['keyValuePairs']));
|
||||
foreach ($params['keyValuePairs'] as $key => &$value) {
|
||||
if (isset($keyValuePairs[$key])) {
|
||||
$keyValuePairs[$key] -= $value;
|
||||
} else {
|
||||
$keyValuePairs[$key] = -$value;
|
||||
}
|
||||
}
|
||||
$failedKeys = $storage->setItems($keyValuePairs);
|
||||
foreach ($failedKeys as $failedKey) {
|
||||
unset($keyValuePairs[$failedKey]);
|
||||
}
|
||||
$event->stopPropagation(\true);
|
||||
|
||||
return $keyValuePairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* On get capabilities.
|
||||
*/
|
||||
public function onGetCapabilitiesPost(PostEvent $event)
|
||||
{
|
||||
$baseCapabilities = $event->getResult();
|
||||
$index = \spl_object_hash($baseCapabilities);
|
||||
if (!isset($this->capabilities[$index])) {
|
||||
$this->capabilities[$index] = new Capabilities(
|
||||
$baseCapabilities->getAdapter(),
|
||||
new \stdClass(),
|
||||
// marker
|
||||
['supportedDatatypes' => ['NULL' => \true, 'boolean' => \true, 'integer' => \true, 'double' => \true, 'string' => \true, 'array' => \true, 'object' => 'object', 'resource' => \false]],
|
||||
$baseCapabilities
|
||||
);
|
||||
}
|
||||
$event->setResult($this->capabilities[$index]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception;
|
||||
|
||||
interface PluginAwareInterface extends PluginCapableInterface
|
||||
{
|
||||
/**
|
||||
* Register a plugin.
|
||||
*
|
||||
* @param int $priority
|
||||
*
|
||||
* @return StorageInterface
|
||||
*
|
||||
* @throws Exception\LogicException
|
||||
*/
|
||||
public function addPlugin(Plugin\PluginInterface $plugin, $priority = 1);
|
||||
|
||||
/**
|
||||
* Unregister an already registered plugin.
|
||||
*
|
||||
* @return StorageInterface
|
||||
*
|
||||
* @throws Exception\LogicException
|
||||
*/
|
||||
public function removePlugin(Plugin\PluginInterface $plugin);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\EventsCapableInterface;
|
||||
|
||||
interface PluginCapableInterface extends EventsCapableInterface
|
||||
{
|
||||
/**
|
||||
* Check if a plugin is registered.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function hasPlugin(Plugin\PluginInterface $plugin);
|
||||
|
||||
/**
|
||||
* Return registry of plugins.
|
||||
*
|
||||
* @return \SplObjectStorage
|
||||
*/
|
||||
public function getPluginRegistry();
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Plugin\PluginInterface;
|
||||
use _JchOptimizeVendor\Laminas\Cache\Storage\Plugin\PluginOptions;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\AbstractPluginManager;
|
||||
use _JchOptimizeVendor\Laminas\ServiceManager\Factory\InvokableFactory;
|
||||
|
||||
/**
|
||||
* Plugin manager implementation for cache plugins.
|
||||
*
|
||||
* Enforces that plugins retrieved are instances of
|
||||
* Plugin\PluginInterface. Additionally, it registers a number of default
|
||||
* plugins available.
|
||||
*/
|
||||
final class PluginManager extends AbstractPluginManager
|
||||
{
|
||||
/** @var array<string,string> */
|
||||
protected $aliases = ['clear_expired_by_factor' => Plugin\ClearExpiredByFactor::class, 'clearexpiredbyfactor' => Plugin\ClearExpiredByFactor::class, 'clearExpiredByFactor' => Plugin\ClearExpiredByFactor::class, 'ClearExpiredByFactor' => Plugin\ClearExpiredByFactor::class, 'exception_handler' => Plugin\ExceptionHandler::class, 'exceptionhandler' => Plugin\ExceptionHandler::class, 'exceptionHandler' => Plugin\ExceptionHandler::class, 'ExceptionHandler' => Plugin\ExceptionHandler::class, 'ignore_user_abort' => Plugin\IgnoreUserAbort::class, 'ignoreuserabort' => Plugin\IgnoreUserAbort::class, 'ignoreUserAbort' => Plugin\IgnoreUserAbort::class, 'IgnoreUserAbort' => Plugin\IgnoreUserAbort::class, 'optimize_by_factor' => Plugin\OptimizeByFactor::class, 'optimizebyfactor' => Plugin\OptimizeByFactor::class, 'optimizeByFactor' => Plugin\OptimizeByFactor::class, 'OptimizeByFactor' => Plugin\OptimizeByFactor::class, 'serializer' => Plugin\Serializer::class, 'Serializer' => Plugin\Serializer::class];
|
||||
|
||||
/** @var array<string,string> */
|
||||
protected $factories = [Plugin\ClearExpiredByFactor::class => InvokableFactory::class, Plugin\ExceptionHandler::class => InvokableFactory::class, Plugin\IgnoreUserAbort::class => InvokableFactory::class, Plugin\OptimizeByFactor::class => InvokableFactory::class, Plugin\Serializer::class => InvokableFactory::class];
|
||||
|
||||
/**
|
||||
* Do not share by default.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected $sharedByDefault = \false;
|
||||
|
||||
/** @var string */
|
||||
protected $instanceOf = PluginInterface::class;
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function build($name, ?array $options = null)
|
||||
{
|
||||
$options = $options ?? [];
|
||||
|
||||
/** @psalm-suppress MixedAssignment */
|
||||
$plugin = parent::build($name);
|
||||
if ([] !== $options && $plugin instanceof PluginInterface) {
|
||||
$plugin->setOptions(new PluginOptions($options));
|
||||
}
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
class PostEvent extends Event
|
||||
{
|
||||
/**
|
||||
* The result/return value.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
protected $result;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Accept a target and its parameters.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $result
|
||||
*/
|
||||
public function __construct($name, StorageInterface $storage, \ArrayObject $params, &$result)
|
||||
{
|
||||
parent::__construct($name, $storage, $params);
|
||||
$this->setResult($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result/return value.
|
||||
*
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return PostEvent
|
||||
*/
|
||||
public function setResult(&$value)
|
||||
{
|
||||
$this->result = &$value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result/return value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function &getResult()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\Cache\Exception\ExceptionInterface;
|
||||
|
||||
interface StorageInterface
|
||||
{
|
||||
/**
|
||||
* Set options.
|
||||
*
|
||||
* @param Adapter\AdapterOptions|array|\Traversable $options
|
||||
*
|
||||
* @return StorageInterface Fluent interface
|
||||
*/
|
||||
public function setOptions($options);
|
||||
|
||||
/**
|
||||
* Get options.
|
||||
*
|
||||
* @return Adapter\AdapterOptions
|
||||
*/
|
||||
public function getOptions();
|
||||
|
||||
// reading
|
||||
/**
|
||||
* Get an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param bool $success
|
||||
* @param mixed $casToken
|
||||
*
|
||||
* @return mixed Data on success, null on failure
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function getItem($key, &$success = null, &$casToken = null);
|
||||
|
||||
/**
|
||||
* Get multiple items.
|
||||
*
|
||||
* @return array Associative array of keys and values
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function getItems(array $keys);
|
||||
|
||||
/**
|
||||
* Test if an item exists.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function hasItem($key);
|
||||
|
||||
/**
|
||||
* Test multiple items.
|
||||
*
|
||||
* @return array Array of found keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function hasItems(array $keys);
|
||||
|
||||
/**
|
||||
* Get metadata of an item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return array|bool Metadata on success, false on failure
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function getMetadata($key);
|
||||
|
||||
/**
|
||||
* Get multiple metadata.
|
||||
*
|
||||
* @return array Associative array of keys and metadata
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function getMetadatas(array $keys);
|
||||
|
||||
// writing
|
||||
/**
|
||||
* Store an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function setItem($key, $value);
|
||||
|
||||
/**
|
||||
* Store multiple items.
|
||||
*
|
||||
* @return array Array of not stored keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function setItems(array $keyValuePairs);
|
||||
|
||||
/**
|
||||
* Add an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function addItem($key, $value);
|
||||
|
||||
/**
|
||||
* Add multiple items.
|
||||
*
|
||||
* @return array Array of not stored keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function addItems(array $keyValuePairs);
|
||||
|
||||
/**
|
||||
* Replace an existing item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function replaceItem($key, $value);
|
||||
|
||||
/**
|
||||
* Replace multiple existing items.
|
||||
*
|
||||
* @return array Array of not stored keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function replaceItems(array $keyValuePairs);
|
||||
|
||||
/**
|
||||
* Set an item only if token matches.
|
||||
*
|
||||
* It uses the token received from getItem() to check if the item has
|
||||
* changed before overwriting it.
|
||||
*
|
||||
* @see getItem()
|
||||
* @see setItem()
|
||||
*
|
||||
* @param mixed $token
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function checkAndSetItem($token, $key, $value);
|
||||
|
||||
/**
|
||||
* Reset lifetime of an item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function touchItem($key);
|
||||
|
||||
/**
|
||||
* Reset lifetime of multiple items.
|
||||
*
|
||||
* @return array Array of not updated keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function touchItems(array $keys);
|
||||
|
||||
/**
|
||||
* Remove an item.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return bool
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function removeItem($key);
|
||||
|
||||
/**
|
||||
* Remove multiple items.
|
||||
*
|
||||
* @return array Array of not removed keys
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function removeItems(array $keys);
|
||||
|
||||
/**
|
||||
* Increment an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param int $value
|
||||
*
|
||||
* @return bool|int The new value on success, false on failure
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function incrementItem($key, $value);
|
||||
|
||||
/**
|
||||
* Increment multiple items.
|
||||
*
|
||||
* @return array Associative array of keys and new values
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function incrementItems(array $keyValuePairs);
|
||||
|
||||
/**
|
||||
* Decrement an item.
|
||||
*
|
||||
* @param string $key
|
||||
* @param int $value
|
||||
*
|
||||
* @return bool|int The new value on success, false on failure
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function decrementItem($key, $value);
|
||||
|
||||
/**
|
||||
* Decrement multiple items.
|
||||
*
|
||||
* @return array Associative array of keys and new values
|
||||
*
|
||||
* @throws ExceptionInterface
|
||||
*/
|
||||
public function decrementItems(array $keyValuePairs);
|
||||
|
||||
// status
|
||||
/**
|
||||
* Capabilities of this storage.
|
||||
*
|
||||
* @return Capabilities
|
||||
*/
|
||||
public function getCapabilities();
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface TaggableInterface
|
||||
{
|
||||
/**
|
||||
* Set tags to an item by given key.
|
||||
* An empty array will remove all tags.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string[] $tags
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function setTags($key, array $tags);
|
||||
|
||||
/**
|
||||
* Get tags of an item by given key.
|
||||
*
|
||||
* @param string $key
|
||||
*
|
||||
* @return false|string[]
|
||||
*/
|
||||
public function getTags($key);
|
||||
|
||||
/**
|
||||
* Remove items matching given tags.
|
||||
*
|
||||
* If $disjunction only one of the given tags must match
|
||||
* else all given tags must match.
|
||||
*
|
||||
* @param string[] $tags
|
||||
* @param bool $disjunction
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clearByTags(array $tags, $disjunction = \false);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\Cache\Storage;
|
||||
|
||||
interface TotalSpaceCapableInterface
|
||||
{
|
||||
/**
|
||||
* Get total space in bytes.
|
||||
*
|
||||
* @return float|int
|
||||
*/
|
||||
public function getTotalSpace();
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Abstract aggregate listener.
|
||||
*/
|
||||
abstract class AbstractListenerAggregate implements ListenerAggregateInterface
|
||||
{
|
||||
/** @var callable[] */
|
||||
protected $listeners = [];
|
||||
|
||||
public function detach(EventManagerInterface $events)
|
||||
{
|
||||
foreach ($this->listeners as $index => $callback) {
|
||||
$events->detach($callback);
|
||||
unset($this->listeners[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
181
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-eventmanager/src/Event.php
vendored
Normal file
181
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-eventmanager/src/Event.php
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Representation of an event.
|
||||
*
|
||||
* Encapsulates the target context and parameters passed, and provides some
|
||||
* behavior for interacting with the event manager.
|
||||
*/
|
||||
class Event implements EventInterface
|
||||
{
|
||||
/** @var string Event name */
|
||||
protected $name;
|
||||
|
||||
/** @var object|string The event target */
|
||||
protected $target;
|
||||
|
||||
/** @var array|\ArrayAccess|object The event parameters */
|
||||
protected $params = [];
|
||||
|
||||
/** @var bool Whether or not to stop propagation */
|
||||
protected $stopPropagation = \false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Accept a target and its parameters.
|
||||
*
|
||||
* @param string $name Event name
|
||||
* @param object|string $target
|
||||
* @param array|\ArrayAccess $params
|
||||
*/
|
||||
public function __construct($name = null, $target = null, $params = null)
|
||||
{
|
||||
if (null !== $name) {
|
||||
$this->setName($name);
|
||||
}
|
||||
if (null !== $target) {
|
||||
$this->setTarget($target);
|
||||
}
|
||||
if (null !== $params) {
|
||||
$this->setParams($params);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the event target.
|
||||
*
|
||||
* This may be either an object, or the name of a static method.
|
||||
*
|
||||
* @return object|string
|
||||
*/
|
||||
public function getTarget()
|
||||
{
|
||||
return $this->target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set parameters.
|
||||
*
|
||||
* Overwrites parameters
|
||||
*
|
||||
* @param array|\ArrayAccess|object $params
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function setParams($params)
|
||||
{
|
||||
if (!\is_array($params) && !\is_object($params)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Event parameters must be an array or object; received "%s"', \gettype($params)));
|
||||
}
|
||||
$this->params = $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all parameters.
|
||||
*
|
||||
* @return array|\ArrayAccess|object
|
||||
*/
|
||||
public function getParams()
|
||||
{
|
||||
return $this->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an individual parameter.
|
||||
*
|
||||
* If the parameter does not exist, the $default value will be returned.
|
||||
*
|
||||
* @param int|string $name
|
||||
* @param mixed $default
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParam($name, $default = null)
|
||||
{
|
||||
// Check in params that are arrays or implement array access
|
||||
if (\is_array($this->params) || $this->params instanceof \ArrayAccess) {
|
||||
if (!isset($this->params[$name])) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->params[$name];
|
||||
}
|
||||
// Check in normal objects
|
||||
if (!isset($this->params->{$name})) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
return $this->params->{$name};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = (string) $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the event target/context.
|
||||
*
|
||||
* @param null|object|string $target
|
||||
*/
|
||||
public function setTarget($target)
|
||||
{
|
||||
$this->target = $target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an individual parameter to a value.
|
||||
*
|
||||
* @param int|string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setParam($name, $value)
|
||||
{
|
||||
if (\is_array($this->params) || $this->params instanceof \ArrayAccess) {
|
||||
// Arrays or objects implementing array access
|
||||
$this->params[$name] = $value;
|
||||
|
||||
return;
|
||||
}
|
||||
// Objects
|
||||
$this->params->{$name} = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop further event propagation.
|
||||
*
|
||||
* @param bool $flag
|
||||
*/
|
||||
public function stopPropagation($flag = \true)
|
||||
{
|
||||
$this->stopPropagation = (bool) $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is propagation stopped?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function propagationIsStopped()
|
||||
{
|
||||
return $this->stopPropagation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Representation of an event.
|
||||
*/
|
||||
interface EventInterface
|
||||
{
|
||||
/**
|
||||
* Get event name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
/**
|
||||
* Get target/context from which event was triggered.
|
||||
*
|
||||
* @return null|object|string
|
||||
*/
|
||||
public function getTarget();
|
||||
|
||||
/**
|
||||
* Get parameters passed to the event.
|
||||
*
|
||||
* @return array|\ArrayAccess
|
||||
*/
|
||||
public function getParams();
|
||||
|
||||
/**
|
||||
* Get a single parameter by name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default Default value to return if parameter does not exist
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getParam($name, $default = null);
|
||||
|
||||
/**
|
||||
* Set the event name.
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function setName($name);
|
||||
|
||||
/**
|
||||
* Set the event target/context.
|
||||
*
|
||||
* @param null|object|string $target
|
||||
*/
|
||||
public function setTarget($target);
|
||||
|
||||
/**
|
||||
* Set event parameters.
|
||||
*
|
||||
* @param array|\ArrayAccess $params
|
||||
*/
|
||||
public function setParams($params);
|
||||
|
||||
/**
|
||||
* Set a single parameter by key.
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setParam($name, $value);
|
||||
|
||||
/**
|
||||
* Indicate whether or not the parent EventManagerInterface should stop propagating events.
|
||||
*
|
||||
* @param bool $flag
|
||||
*/
|
||||
public function stopPropagation($flag = \true);
|
||||
|
||||
/**
|
||||
* Has this event indicated event propagation should stop?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function propagationIsStopped();
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
use ArrayObject;
|
||||
|
||||
/**
|
||||
* Event manager: notification system.
|
||||
*
|
||||
* Use the EventManager when you want to create a per-instance notification
|
||||
* system for your objects.
|
||||
*/
|
||||
class EventManager implements EventManagerInterface
|
||||
{
|
||||
/**
|
||||
* Subscribed events and their listeners.
|
||||
*
|
||||
* STRUCTURE:
|
||||
* [
|
||||
* <string name> => [
|
||||
* <int priority> => [
|
||||
* 0 => [<callable listener>, ...]
|
||||
* ],
|
||||
* ...
|
||||
* ],
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* NOTE:
|
||||
* This structure helps us to reuse the list of listeners
|
||||
* instead of first iterating over it and generating a new one
|
||||
* -> In result it improves performance by up to 25% even if it looks a bit strange
|
||||
*
|
||||
* @var array[]
|
||||
*/
|
||||
protected $events = [];
|
||||
|
||||
/** @var EventInterface Prototype to use when creating an event at trigger(). */
|
||||
protected $eventPrototype;
|
||||
|
||||
/**
|
||||
* Identifiers, used to pull shared signals from SharedEventManagerInterface instance.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $identifiers = [];
|
||||
|
||||
/**
|
||||
* Shared event manager.
|
||||
*
|
||||
* @var null|SharedEventManagerInterface
|
||||
*/
|
||||
protected $sharedManager;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Allows optionally specifying identifier(s) to use to pull signals from a
|
||||
* SharedEventManagerInterface.
|
||||
*/
|
||||
public function __construct(?SharedEventManagerInterface $sharedEventManager = null, array $identifiers = [])
|
||||
{
|
||||
if ($sharedEventManager) {
|
||||
$this->sharedManager = $sharedEventManager;
|
||||
$this->setIdentifiers($identifiers);
|
||||
}
|
||||
$this->eventPrototype = new Event();
|
||||
}
|
||||
|
||||
public function setEventPrototype(EventInterface $prototype)
|
||||
{
|
||||
$this->eventPrototype = $prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the shared event manager, if composed.
|
||||
*
|
||||
* @return null|SharedEventManagerInterface $sharedEventManager
|
||||
*/
|
||||
public function getSharedManager()
|
||||
{
|
||||
return $this->sharedManager;
|
||||
}
|
||||
|
||||
public function getIdentifiers()
|
||||
{
|
||||
return $this->identifiers;
|
||||
}
|
||||
|
||||
public function setIdentifiers(array $identifiers)
|
||||
{
|
||||
$this->identifiers = \array_unique($identifiers);
|
||||
}
|
||||
|
||||
public function addIdentifiers(array $identifiers)
|
||||
{
|
||||
$this->identifiers = \array_unique(\array_merge($this->identifiers, $identifiers));
|
||||
}
|
||||
|
||||
public function trigger($eventName, $target = null, $argv = [])
|
||||
{
|
||||
$event = clone $this->eventPrototype;
|
||||
$event->setName($eventName);
|
||||
if (null !== $target) {
|
||||
$event->setTarget($target);
|
||||
}
|
||||
if ($argv) {
|
||||
$event->setParams($argv);
|
||||
}
|
||||
|
||||
return $this->triggerListeners($event);
|
||||
}
|
||||
|
||||
public function triggerUntil(callable $callback, $eventName, $target = null, $argv = [])
|
||||
{
|
||||
$event = clone $this->eventPrototype;
|
||||
$event->setName($eventName);
|
||||
if (null !== $target) {
|
||||
$event->setTarget($target);
|
||||
}
|
||||
if ($argv) {
|
||||
$event->setParams($argv);
|
||||
}
|
||||
|
||||
return $this->triggerListeners($event, $callback);
|
||||
}
|
||||
|
||||
public function triggerEvent(EventInterface $event)
|
||||
{
|
||||
return $this->triggerListeners($event);
|
||||
}
|
||||
|
||||
public function triggerEventUntil(callable $callback, EventInterface $event)
|
||||
{
|
||||
return $this->triggerListeners($event, $callback);
|
||||
}
|
||||
|
||||
public function attach($eventName, callable $listener, $priority = 1)
|
||||
{
|
||||
if (!\is_string($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('%s expects a string for the event; received %s', __METHOD__, \is_object($eventName) ? \get_class($eventName) : \gettype($eventName)));
|
||||
}
|
||||
$this->events[$eventName][(int) $priority][0][] = $listener;
|
||||
|
||||
return $listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception\InvalidArgumentException for invalid event types
|
||||
*/
|
||||
public function detach(callable $listener, $eventName = null, $force = \false)
|
||||
{
|
||||
// If event is wildcard, we need to iterate through each listeners
|
||||
if (null === $eventName || '*' === $eventName && !$force) {
|
||||
foreach (\array_keys($this->events) as $eventName) {
|
||||
$this->detach($listener, $eventName, \true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (!\is_string($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('%s expects a string for the event; received %s', __METHOD__, \is_object($eventName) ? \get_class($eventName) : \gettype($eventName)));
|
||||
}
|
||||
if (!isset($this->events[$eventName])) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->events[$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners[0] as $index => $evaluatedListener) {
|
||||
if ($evaluatedListener !== $listener) {
|
||||
continue;
|
||||
}
|
||||
// Found the listener; remove it.
|
||||
unset($this->events[$eventName][$priority][0][$index]);
|
||||
// If the queue for the given priority is empty, remove it.
|
||||
if (empty($this->events[$eventName][$priority][0])) {
|
||||
unset($this->events[$eventName][$priority]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the queue for the given event is empty, remove it.
|
||||
if (empty($this->events[$eventName])) {
|
||||
unset($this->events[$eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
public function clearListeners($eventName)
|
||||
{
|
||||
if (isset($this->events[$eventName])) {
|
||||
unset($this->events[$eventName]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare arguments.
|
||||
*
|
||||
* Use this method if you want to be able to modify arguments from within a
|
||||
* listener. It returns an ArrayObject of the arguments, which may then be
|
||||
* passed to trigger().
|
||||
*
|
||||
* @return \ArrayObject
|
||||
*/
|
||||
public function prepareArgs(array $args)
|
||||
{
|
||||
return new \ArrayObject($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger listeners.
|
||||
*
|
||||
* Actual functionality for triggering listeners, to which trigger() delegate.
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
protected function triggerListeners(EventInterface $event, ?callable $callback = null)
|
||||
{
|
||||
$name = $event->getName();
|
||||
if (empty($name)) {
|
||||
throw new Exception\RuntimeException('Event is missing a name; cannot trigger!');
|
||||
}
|
||||
if (isset($this->events[$name])) {
|
||||
$listOfListenersByPriority = $this->events[$name];
|
||||
if (isset($this->events['*'])) {
|
||||
foreach ($this->events['*'] as $priority => $listOfListeners) {
|
||||
$listOfListenersByPriority[$priority][] = $listOfListeners[0];
|
||||
}
|
||||
}
|
||||
} elseif (isset($this->events['*'])) {
|
||||
$listOfListenersByPriority = $this->events['*'];
|
||||
} else {
|
||||
$listOfListenersByPriority = [];
|
||||
}
|
||||
if ($this->sharedManager) {
|
||||
foreach ($this->sharedManager->getListeners($this->identifiers, $name) as $priority => $listeners) {
|
||||
$listOfListenersByPriority[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
// Sort by priority in reverse order
|
||||
\krsort($listOfListenersByPriority);
|
||||
// Initial value of stop propagation flag should be false
|
||||
$event->stopPropagation(\false);
|
||||
// Execute listeners
|
||||
$responses = new ResponseCollection();
|
||||
foreach ($listOfListenersByPriority as $listOfListeners) {
|
||||
foreach ($listOfListeners as $listeners) {
|
||||
foreach ($listeners as $listener) {
|
||||
$response = $listener($event);
|
||||
$responses->push($response);
|
||||
// If the event was asked to stop propagating, do so
|
||||
if ($event->propagationIsStopped()) {
|
||||
$responses->setStopped(\true);
|
||||
|
||||
return $responses;
|
||||
}
|
||||
// If the result causes our validation callback to return true,
|
||||
// stop propagation
|
||||
if ($callback && $callback($response)) {
|
||||
$responses->setStopped(\true);
|
||||
|
||||
return $responses;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $responses;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Interface to automate setter injection for an EventManager instance.
|
||||
*/
|
||||
interface EventManagerAwareInterface extends EventsCapableInterface
|
||||
{
|
||||
/**
|
||||
* Inject an EventManager instance.
|
||||
*/
|
||||
public function setEventManager(EventManagerInterface $eventManager);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* A trait for objects that provide events.
|
||||
*
|
||||
* If you use this trait in an object, you will probably want to also implement
|
||||
* EventManagerAwareInterface, which will make it so the default initializer in
|
||||
* a Laminas MVC application will automatically inject an instance of the
|
||||
* EventManager into your object when it is pulled from the ServiceManager.
|
||||
*
|
||||
* @see Laminas\Mvc\Service\ServiceManagerConfig
|
||||
*/
|
||||
trait EventManagerAwareTrait
|
||||
{
|
||||
/** @var EventManagerInterface */
|
||||
protected $events;
|
||||
|
||||
/**
|
||||
* Set the event manager instance used by this context.
|
||||
*
|
||||
* For convenience, this method will also set the class name / LSB name as
|
||||
* identifiers, in addition to any string or array of strings set to the
|
||||
* $this->eventIdentifier property.
|
||||
*/
|
||||
public function setEventManager(EventManagerInterface $events)
|
||||
{
|
||||
$identifiers = [self::class, static::class];
|
||||
if (isset($this->eventIdentifier)) {
|
||||
if (\is_string($this->eventIdentifier) || \is_array($this->eventIdentifier) || $this->eventIdentifier instanceof \Traversable) {
|
||||
$identifiers = \array_unique(\array_merge($identifiers, (array) $this->eventIdentifier));
|
||||
} elseif (\is_object($this->eventIdentifier)) {
|
||||
$identifiers[] = $this->eventIdentifier;
|
||||
}
|
||||
// silently ignore invalid eventIdentifier types
|
||||
}
|
||||
$events->setIdentifiers($identifiers);
|
||||
$this->events = $events;
|
||||
if (\method_exists($this, 'attachDefaultListeners')) {
|
||||
$this->attachDefaultListeners();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the event manager.
|
||||
*
|
||||
* Lazy-loads an EventManager instance if none registered.
|
||||
*
|
||||
* @return EventManagerInterface
|
||||
*/
|
||||
public function getEventManager()
|
||||
{
|
||||
if (!$this->events instanceof EventManagerInterface) {
|
||||
$this->setEventManager(new EventManager());
|
||||
}
|
||||
|
||||
return $this->events;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Interface for messengers.
|
||||
*/
|
||||
interface EventManagerInterface extends SharedEventsCapableInterface
|
||||
{
|
||||
/**
|
||||
* Create and trigger an event.
|
||||
*
|
||||
* Use this method when you do not want to create an EventInterface
|
||||
* instance prior to triggering. You will be required to pass:
|
||||
*
|
||||
* - the event name
|
||||
* - the event target (can be null)
|
||||
* - any event parameters you want to provide (empty array by default)
|
||||
*
|
||||
* It will create the Event instance for you and then trigger all listeners
|
||||
* related to the event.
|
||||
*
|
||||
* @param string $eventName
|
||||
* @param null|object|string $target
|
||||
* @param array|object $argv
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
public function trigger($eventName, $target = null, $argv = []);
|
||||
|
||||
/**
|
||||
* Create and trigger an event, applying a callback to each listener result.
|
||||
*
|
||||
* Use this method when you do not want to create an EventInterface
|
||||
* instance prior to triggering. You will be required to pass:
|
||||
*
|
||||
* - the event name
|
||||
* - the event target (can be null)
|
||||
* - any event parameters you want to provide (empty array by default)
|
||||
*
|
||||
* It will create the Event instance for you, and trigger all listeners
|
||||
* related to the event.
|
||||
*
|
||||
* The result of each listener is passed to $callback; if $callback returns
|
||||
* a boolean true value, the manager must short-circuit listener execution.
|
||||
*
|
||||
* @param string $eventName
|
||||
* @param null|object|string $target
|
||||
* @param array|object $argv
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
public function triggerUntil(callable $callback, $eventName, $target = null, $argv = []);
|
||||
|
||||
/**
|
||||
* Trigger an event.
|
||||
*
|
||||
* Provided an EventInterface instance, this method will trigger listeners
|
||||
* based on the event name, raising an exception if the event name is missing.
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
public function triggerEvent(EventInterface $event);
|
||||
|
||||
/**
|
||||
* Trigger an event, applying a callback to each listener result.
|
||||
*
|
||||
* Provided an EventInterface instance, this method will trigger listeners
|
||||
* based on the event name, raising an exception if the event name is missing.
|
||||
*
|
||||
* The result of each listener is passed to $callback; if $callback returns
|
||||
* a boolean true value, the manager must short-circuit listener execution.
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
public function triggerEventUntil(callable $callback, EventInterface $event);
|
||||
|
||||
/**
|
||||
* Attach a listener to an event.
|
||||
*
|
||||
* The first argument is the event, and the next argument is a
|
||||
* callable that will respond to that event.
|
||||
*
|
||||
* The last argument indicates a priority at which the event should be
|
||||
* executed; by default, this value is 1; however, you may set it for any
|
||||
* integer value. Higher values have higher priority (i.e., execute first).
|
||||
*
|
||||
* You can specify "*" for the event name. In such cases, the listener will
|
||||
* be triggered for every event *that has registered listeners at the time
|
||||
* it is attached*. As such, register wildcard events last whenever possible!
|
||||
*
|
||||
* @param string $eventName event to which to listen
|
||||
* @param int $priority priority at which to register listener
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function attach($eventName, callable $listener, $priority = 1);
|
||||
|
||||
/**
|
||||
* Detach a listener.
|
||||
*
|
||||
* If no $event or '*' is provided, detaches listener from all events;
|
||||
* otherwise, detaches only from the named event.
|
||||
*
|
||||
* @param null|string $eventName event from which to detach; null and '*'
|
||||
* indicate all events
|
||||
*/
|
||||
public function detach(callable $listener, $eventName = null);
|
||||
|
||||
/**
|
||||
* Clear all listeners for a given event.
|
||||
*
|
||||
* @param string $eventName
|
||||
*/
|
||||
public function clearListeners($eventName);
|
||||
|
||||
/**
|
||||
* Provide an event prototype to use with trigger().
|
||||
*
|
||||
* When `trigger()` needs to create an event instance, it should clone the
|
||||
* prototype provided to this method.
|
||||
*/
|
||||
public function setEventPrototype(EventInterface $prototype);
|
||||
|
||||
/**
|
||||
* Get the identifier(s) for this EventManager.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getIdentifiers();
|
||||
|
||||
/**
|
||||
* Set the identifiers (overrides any currently set identifiers).
|
||||
*
|
||||
* @param string[] $identifiers
|
||||
*/
|
||||
public function setIdentifiers(array $identifiers);
|
||||
|
||||
/**
|
||||
* Add identifier(s) (appends to any currently set identifiers).
|
||||
*
|
||||
* @param string[] $identifiers
|
||||
*/
|
||||
public function addIdentifiers(array $identifiers);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Interface indicating that an object composes an EventManagerInterface instance.
|
||||
*/
|
||||
interface EventsCapableInterface
|
||||
{
|
||||
/**
|
||||
* Retrieve the event manager.
|
||||
*
|
||||
* Lazy-loads an EventManager instance if none registered.
|
||||
*
|
||||
* @return EventManagerInterface
|
||||
*/
|
||||
public function getEventManager();
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
|
||||
class DomainException extends \DomainException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
|
||||
/**
|
||||
* Base exception interface.
|
||||
*/
|
||||
interface ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
|
||||
/**
|
||||
* Invalid argument exception.
|
||||
*/
|
||||
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
|
||||
/**
|
||||
* Invalid callback exception.
|
||||
*/
|
||||
class InvalidCallbackException extends DomainException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
|
||||
use RuntimeException as SplRuntimeException;
|
||||
|
||||
class RuntimeException extends SplRuntimeException implements ExceptionInterface
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Filter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\ResponseCollection;
|
||||
|
||||
/**
|
||||
* Interface for intercepting filter chains.
|
||||
*/
|
||||
interface FilterInterface
|
||||
{
|
||||
/**
|
||||
* Execute the filter chain.
|
||||
*
|
||||
* @param object|string $context
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function run($context, array $params = []);
|
||||
|
||||
/**
|
||||
* Attach an intercepting filter.
|
||||
*/
|
||||
public function attach(callable $callback);
|
||||
|
||||
/**
|
||||
* Detach an intercepting filter.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function detach(callable $filter);
|
||||
|
||||
/**
|
||||
* Get all intercepting filters.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getFilters();
|
||||
|
||||
/**
|
||||
* Clear all filters.
|
||||
*/
|
||||
public function clearFilters();
|
||||
|
||||
/**
|
||||
* Get all filter responses.
|
||||
*
|
||||
* @return ResponseCollection
|
||||
*/
|
||||
public function getResponses();
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager\Filter;
|
||||
|
||||
use _JchOptimizeVendor\Laminas\EventManager\Exception;
|
||||
use _JchOptimizeVendor\Laminas\Stdlib\FastPriorityQueue;
|
||||
|
||||
/**
|
||||
* Specialized priority queue implementation for use with an intercepting
|
||||
* filter chain.
|
||||
*
|
||||
* Allows removal
|
||||
*/
|
||||
class FilterIterator extends FastPriorityQueue
|
||||
{
|
||||
/**
|
||||
* Does the queue contain a given value?
|
||||
*
|
||||
* @param mixed $datum
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($datum)
|
||||
{
|
||||
foreach ($this as $item) {
|
||||
if ($item === $datum) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
return \false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a value into the queue.
|
||||
*
|
||||
* Requires a callable.
|
||||
*
|
||||
* @param callable $value
|
||||
* @param mixed $priority
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException for non-callable $value
|
||||
*/
|
||||
public function insert($value, $priority)
|
||||
{
|
||||
if (!\is_callable($value)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('%s can only aggregate callables; received %s', self::class, \is_object($value) ? \get_class($value) : \gettype($value)));
|
||||
}
|
||||
parent::insert($value, $priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a value from the queue.
|
||||
*
|
||||
* This is an expensive operation. It must first iterate through all values,
|
||||
* and then re-populate itself. Use only if absolutely necessary.
|
||||
*
|
||||
* @param mixed $datum
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove($datum)
|
||||
{
|
||||
$this->setExtractFlags(self::EXTR_BOTH);
|
||||
// Iterate and remove any matches
|
||||
$removed = \false;
|
||||
$items = [];
|
||||
$this->rewind();
|
||||
while (!$this->isEmpty()) {
|
||||
$item = $this->extract();
|
||||
if ($item['data'] === $datum) {
|
||||
$removed = \true;
|
||||
|
||||
continue;
|
||||
}
|
||||
$items[] = $item;
|
||||
}
|
||||
// Repopulate
|
||||
foreach ($items as $item) {
|
||||
$this->insert($item['data'], $item['priority']);
|
||||
}
|
||||
$this->setExtractFlags(self::EXTR_DATA);
|
||||
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterate the next filter in the chain.
|
||||
*
|
||||
* Iterates and calls the next filter in the chain.
|
||||
*
|
||||
* @param mixed $context
|
||||
* @param FilterIterator $chain
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function next($context = null, array $params = [], $chain = null)
|
||||
{
|
||||
if (empty($context) || $chain instanceof FilterIterator && $chain->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
// We can't extract from an empty heap
|
||||
if ($this->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
$next = $this->extract();
|
||||
|
||||
return $next($context, $params, $chain);
|
||||
}
|
||||
}
|
||||
102
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-eventmanager/src/FilterChain.php
vendored
Normal file
102
administrator/components/com_jchoptimize/lib/vendor/laminas/laminas-eventmanager/src/FilterChain.php
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* FilterChain: intercepting filter manager.
|
||||
*/
|
||||
class FilterChain implements Filter\FilterInterface
|
||||
{
|
||||
/** @var Filter\FilterIterator All filters */
|
||||
protected $filters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Initializes Filter\FilterIterator in which filters will be aggregated
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->filters = new Filter\FilterIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the filters.
|
||||
*
|
||||
* Begins iteration of the filters.
|
||||
*
|
||||
* @param mixed $context Object under observation
|
||||
* @param mixed $argv Associative array of arguments
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function run($context, array $argv = [])
|
||||
{
|
||||
$chain = clone $this->getFilters();
|
||||
if ($chain->isEmpty()) {
|
||||
return;
|
||||
}
|
||||
$next = $chain->extract();
|
||||
|
||||
return $next($context, $argv, $chain);
|
||||
}
|
||||
|
||||
/**
|
||||
* Connect a filter to the chain.
|
||||
*
|
||||
* @param callable $callback PHP Callback
|
||||
* @param int $priority Priority in the queue at which to execute;
|
||||
* defaults to 1 (higher numbers == higher priority)
|
||||
*
|
||||
* @return CallbackHandler (to allow later unsubscribe)
|
||||
*
|
||||
* @throws Exception\InvalidCallbackException
|
||||
*/
|
||||
public function attach(callable $callback, $priority = 1)
|
||||
{
|
||||
$this->filters->insert($callback, $priority);
|
||||
|
||||
return $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detach a filter from the chain.
|
||||
*
|
||||
* @return bool Returns true if filter found and unsubscribed; returns false otherwise
|
||||
*/
|
||||
public function detach(callable $filter)
|
||||
{
|
||||
return $this->filters->remove($filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all filters.
|
||||
*
|
||||
* @return Filter\FilterIterator
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
return $this->filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all filters.
|
||||
*/
|
||||
public function clearFilters()
|
||||
{
|
||||
$this->filters = new Filter\FilterIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current responses.
|
||||
*
|
||||
* Only available while the chain is still being iterated. Returns the
|
||||
* current ResponseCollection.
|
||||
*
|
||||
* @return null|ResponseCollection
|
||||
*/
|
||||
public function getResponses()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Lazy listener instance for use with LazyListenerAggregate.
|
||||
*
|
||||
* Used as an internal class for the LazyAggregate to allow lazy creation of
|
||||
* listeners via a dependency injection container.
|
||||
*
|
||||
* Lazy event listener definitions add the following members to what the
|
||||
* LazyListener accepts:
|
||||
*
|
||||
* - event: the event name to attach to.
|
||||
* - priority: the priority at which to attach the listener, if not the default.
|
||||
*/
|
||||
class LazyEventListener extends LazyListener
|
||||
{
|
||||
/** @var string Event name to which to attach. */
|
||||
private $event;
|
||||
|
||||
/** @var null|int Priority at which to attach. */
|
||||
private $priority;
|
||||
|
||||
public function __construct(array $definition, ContainerInterface $container, array $env = [])
|
||||
{
|
||||
parent::__construct($definition, $container, $env);
|
||||
if (!isset($definition['event']) || !\is_string($definition['event']) || empty($definition['event'])) {
|
||||
throw new Exception\InvalidArgumentException('Lazy listener definition is missing a valid "event" member; cannot create LazyListener');
|
||||
}
|
||||
$this->event = $definition['event'];
|
||||
$this->priority = isset($definition['priority']) ? (int) $definition['priority'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getEvent()
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $default
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getPriority($default = 1)
|
||||
{
|
||||
return null !== $this->priority ? $this->priority : $default;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Lazy listener instance.
|
||||
*
|
||||
* Used to allow lazy creation of listeners via a dependency injection
|
||||
* container.
|
||||
*
|
||||
* Lazy listener definitions have the following members:
|
||||
*
|
||||
* - listener: the service name of the listener to use.
|
||||
* - method: the method name of the listener to invoke for the specified event.
|
||||
*
|
||||
* If desired, you can pass $env at instantiation; this will be passed to the
|
||||
* container's `build()` method, if it has one, when creating the listener
|
||||
* instance.
|
||||
*
|
||||
* Pass instances directly to the event manager's `attach()` method as the
|
||||
* listener argument.
|
||||
*/
|
||||
class LazyListener
|
||||
{
|
||||
/** @var ContainerInterface Container from which to pull listener. */
|
||||
private $container;
|
||||
|
||||
/** @var array Variables/options to use during service creation, if any. */
|
||||
private $env;
|
||||
|
||||
/** @var callable Marshaled listener callback. */
|
||||
private $listener;
|
||||
|
||||
/** @var string Method name to invoke on listener. */
|
||||
private $method;
|
||||
|
||||
/** @var string Service name of listener. */
|
||||
private $service;
|
||||
|
||||
public function __construct(array $definition, ContainerInterface $container, array $env = [])
|
||||
{
|
||||
if (!isset($definition['listener']) || !\is_string($definition['listener']) || empty($definition['listener'])) {
|
||||
throw new Exception\InvalidArgumentException('Lazy listener definition is missing a valid "listener" member; cannot create LazyListener');
|
||||
}
|
||||
if (!isset($definition['method']) || !\is_string($definition['method']) || empty($definition['method'])) {
|
||||
throw new Exception\InvalidArgumentException('Lazy listener definition is missing a valid "method" member; cannot create LazyListener');
|
||||
}
|
||||
$this->service = $definition['listener'];
|
||||
$this->method = $definition['method'];
|
||||
$this->container = $container;
|
||||
$this->env = $env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the listener as an invokable, allowing direct attachment to an event manager.
|
||||
*
|
||||
* @return callable
|
||||
*/
|
||||
public function __invoke(EventInterface $event)
|
||||
{
|
||||
$listener = $this->fetchListener();
|
||||
$method = $this->method;
|
||||
|
||||
return $listener->{$method}($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return callable
|
||||
*/
|
||||
private function fetchListener()
|
||||
{
|
||||
if ($this->listener) {
|
||||
return $this->listener;
|
||||
}
|
||||
// In the future, typehint against Laminas\ServiceManager\ServiceLocatorInterface,
|
||||
// which defines this message starting in v3.
|
||||
if (\method_exists($this->container, 'build') && !empty($this->env)) {
|
||||
$this->listener = $this->container->build($this->service, $this->env);
|
||||
|
||||
return $this->listener;
|
||||
}
|
||||
$this->listener = $this->container->get($this->service);
|
||||
|
||||
return $this->listener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
use _JchOptimizeVendor\Psr\Container\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Aggregate listener for attaching lazy listeners.
|
||||
*
|
||||
* Lazy listeners are listeners where creation is deferred until they are
|
||||
* triggered; this removes the most costly mechanism of pulling a listener
|
||||
* from a container unless the listener is actually invoked.
|
||||
*
|
||||
* Usage is:
|
||||
*
|
||||
* <code>
|
||||
* $aggregate = new LazyListenerAggregate(
|
||||
* $lazyEventListenersOrDefinitions,
|
||||
* $container
|
||||
* );
|
||||
* $aggregate->attach($events);
|
||||
* </code>
|
||||
*/
|
||||
class LazyListenerAggregate implements ListenerAggregateInterface
|
||||
{
|
||||
use ListenerAggregateTrait;
|
||||
// phpcs:disable SlevomatCodingStandard.Classes.UnusedPrivateElements.WriteOnlyProperty
|
||||
/** @var ContainerInterface Container from which to pull lazy listeners. */
|
||||
private $container;
|
||||
|
||||
/** @var array Additional environment/option variables to use when creating listener. */
|
||||
private $env;
|
||||
// phpcs:enable
|
||||
/**
|
||||
* Generated LazyEventListener instances.
|
||||
*
|
||||
* @var LazyEventListener[]
|
||||
*/
|
||||
private $lazyListeners = [];
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* Accepts the composed $listeners, as well as the $container and $env in
|
||||
* order to create a listener aggregate that defers listener creation until
|
||||
* the listener is triggered.
|
||||
*
|
||||
* Listeners may be either LazyEventListener instances, or lazy event
|
||||
* listener definitions that can be provided to a LazyEventListener
|
||||
* constructor in order to create a new instance; in the latter case, the
|
||||
* $container and $env will be passed at instantiation as well.
|
||||
*
|
||||
* @param array $listeners lazyEventListener instances or array definitions
|
||||
* to pass to the LazyEventListener constructor
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException for invalid listener items
|
||||
*/
|
||||
public function __construct(array $listeners, ContainerInterface $container, array $env = [])
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->env = $env;
|
||||
// This would raise an exception for invalid structs
|
||||
foreach ($listeners as $listener) {
|
||||
if (\is_array($listener)) {
|
||||
$listener = new LazyEventListener($listener, $container, $env);
|
||||
}
|
||||
if (!$listener instanceof LazyEventListener) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('All listeners must be LazyEventListener instances or definitions; received %s', \is_object($listener) ? \get_class($listener) : \gettype($listener)));
|
||||
}
|
||||
$this->lazyListeners[] = $listener;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach the aggregate to the event manager.
|
||||
*
|
||||
* Loops through all composed lazy listeners, and attaches them to the
|
||||
* event manager.
|
||||
*
|
||||
* @param int $priority
|
||||
*/
|
||||
public function attach(EventManagerInterface $events, $priority = 1)
|
||||
{
|
||||
foreach ($this->lazyListeners as $lazyListener) {
|
||||
$this->listeners[] = $events->attach($lazyListener->getEvent(), $lazyListener, $lazyListener->getPriority($priority));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Interface for self-registering event listeners.
|
||||
*
|
||||
* Classes implementing this interface may be registered by name or instance
|
||||
* with an EventManager, without an event name. The {@link attach()} method will
|
||||
* then be called with the current EventManager instance, allowing the class to
|
||||
* wire up one or more listeners.
|
||||
*/
|
||||
interface ListenerAggregateInterface
|
||||
{
|
||||
/**
|
||||
* Attach one or more listeners.
|
||||
*
|
||||
* Implementors may add an optional $priority argument; the EventManager
|
||||
* implementation will pass this to the aggregate.
|
||||
*
|
||||
* @param int $priority
|
||||
*/
|
||||
public function attach(EventManagerInterface $events, $priority = 1);
|
||||
|
||||
/**
|
||||
* Detach all previously attached listeners.
|
||||
*/
|
||||
public function detach(EventManagerInterface $events);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Provides logic to easily create aggregate listeners, without worrying about
|
||||
* manually detaching events.
|
||||
*/
|
||||
trait ListenerAggregateTrait
|
||||
{
|
||||
/** @var callable[] */
|
||||
protected $listeners = [];
|
||||
|
||||
public function detach(EventManagerInterface $events)
|
||||
{
|
||||
foreach ($this->listeners as $index => $callback) {
|
||||
$events->detach($callback);
|
||||
unset($this->listeners[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Collection of signal handler return values.
|
||||
*/
|
||||
class ResponseCollection extends \SplStack
|
||||
{
|
||||
/** @var bool */
|
||||
protected $stopped = \false;
|
||||
|
||||
/**
|
||||
* Did the last response provided trigger a short circuit of the stack?
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function stopped()
|
||||
{
|
||||
return $this->stopped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the collection as stopped (or its opposite).
|
||||
*
|
||||
* @param bool $flag
|
||||
*/
|
||||
public function setStopped($flag)
|
||||
{
|
||||
$this->stopped = (bool) $flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient access to the first handler return value.
|
||||
*
|
||||
* @return mixed The first handler return value
|
||||
*/
|
||||
public function first()
|
||||
{
|
||||
return parent::bottom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenient access to the last handler return value.
|
||||
*
|
||||
* If the collection is empty, returns null. Otherwise, returns value
|
||||
* returned by last handler.
|
||||
*
|
||||
* @return mixed The last handler return value
|
||||
*/
|
||||
public function last()
|
||||
{
|
||||
if (0 === \count($this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return parent::top();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if any of the responses match the given value.
|
||||
*
|
||||
* @param mixed $value The value to look for among responses
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains($value)
|
||||
{
|
||||
foreach ($this as $response) {
|
||||
if ($response === $value) {
|
||||
return \true;
|
||||
}
|
||||
}
|
||||
|
||||
return \false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
use function get_class;
|
||||
|
||||
/**
|
||||
* Shared/contextual EventManager.
|
||||
*
|
||||
* Allows attaching to EMs composed by other classes without having an instance first.
|
||||
* The assumption is that the SharedEventManager will be injected into EventManager
|
||||
* instances, and then queried for additional listeners when triggering an event.
|
||||
*/
|
||||
class SharedEventManager implements SharedEventManagerInterface
|
||||
{
|
||||
/**
|
||||
* Identifiers with event connections.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $identifiers = [];
|
||||
|
||||
/**
|
||||
* Attach a listener to an event emitted by components with specific identifiers.
|
||||
*
|
||||
* As an example, the following connects to the "getAll" event of both an
|
||||
* AbstractResource and EntityResource:
|
||||
*
|
||||
* <code>
|
||||
* $sharedEventManager = new SharedEventManager();
|
||||
* foreach (['My\Resource\AbstractResource', 'My\Resource\EntityResource'] as $identifier) {
|
||||
* $sharedEventManager->attach(
|
||||
* $identifier,
|
||||
* 'getAll',
|
||||
* function ($e) use ($cache) {
|
||||
* if (!$id = $e->getParam('id', false)) {
|
||||
* return;
|
||||
* }
|
||||
* if (!$data = $cache->load(get_class($resource) . '::getOne::' . $id )) {
|
||||
* return;
|
||||
* }
|
||||
* return $data;
|
||||
* }
|
||||
* );
|
||||
* }
|
||||
* </code>
|
||||
*
|
||||
* @param string $identifier identifier for event emitting component
|
||||
* @param string $event
|
||||
* @param callable $listener listener that will handle the event
|
||||
* @param int $priority Priority at which listener should execute
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException for invalid identifier arguments
|
||||
* @throws Exception\InvalidArgumentException for invalid event arguments
|
||||
*/
|
||||
public function attach($identifier, $event, callable $listener, $priority = 1)
|
||||
{
|
||||
if (!\is_string($identifier) || empty($identifier)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Invalid identifier provided; must be a string; received "%s"', \is_object($identifier) ? \get_class($identifier) : \gettype($identifier)));
|
||||
}
|
||||
if (!\is_string($event) || empty($event)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Invalid event provided; must be a non-empty string; received "%s"', \is_object($event) ? \get_class($event) : \gettype($event)));
|
||||
}
|
||||
$this->identifiers[$identifier][$event][(int) $priority][] = $listener;
|
||||
}
|
||||
|
||||
public function detach(callable $listener, $identifier = null, $eventName = null, $force = \false)
|
||||
{
|
||||
// No identifier or wildcard identifier: loop through all identifiers and detach
|
||||
if (null === $identifier || '*' === $identifier && !$force) {
|
||||
foreach (\array_keys($this->identifiers) as $identifier) {
|
||||
$this->detach($listener, $identifier, $eventName, \true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (!\is_string($identifier) || empty($identifier)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Invalid identifier provided; must be a string, received %s', \is_object($identifier) ? \get_class($identifier) : \gettype($identifier)));
|
||||
}
|
||||
// Do we have any listeners on the provided identifier?
|
||||
if (!isset($this->identifiers[$identifier])) {
|
||||
return;
|
||||
}
|
||||
if (null === $eventName || '*' === $eventName && !$force) {
|
||||
foreach (\array_keys($this->identifiers[$identifier]) as $eventName) {
|
||||
$this->detach($listener, $identifier, $eventName, \true);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
if (!\is_string($eventName) || empty($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Invalid event name provided; must be a string, received %s', \is_object($eventName) ? \get_class($eventName) : \gettype($eventName)));
|
||||
}
|
||||
if (!isset($this->identifiers[$identifier][$eventName])) {
|
||||
return;
|
||||
}
|
||||
foreach ($this->identifiers[$identifier][$eventName] as $priority => $listeners) {
|
||||
foreach ($listeners as $index => $evaluatedListener) {
|
||||
if ($evaluatedListener !== $listener) {
|
||||
continue;
|
||||
}
|
||||
// Found the listener; remove it.
|
||||
unset($this->identifiers[$identifier][$eventName][$priority][$index]);
|
||||
// Is the priority queue empty?
|
||||
if (empty($this->identifiers[$identifier][$eventName][$priority])) {
|
||||
unset($this->identifiers[$identifier][$eventName][$priority]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Is the event queue empty?
|
||||
if (empty($this->identifiers[$identifier][$eventName])) {
|
||||
unset($this->identifiers[$identifier][$eventName]);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Is the identifier queue now empty? Remove it.
|
||||
if (empty($this->identifiers[$identifier])) {
|
||||
unset($this->identifiers[$identifier]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve all listeners for a given identifier and event.
|
||||
*
|
||||
* @param string[] $identifiers
|
||||
* @param string $eventName
|
||||
*
|
||||
* @return array[]
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException
|
||||
*/
|
||||
public function getListeners(array $identifiers, $eventName)
|
||||
{
|
||||
if ('*' === $eventName || !\is_string($eventName) || empty($eventName)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Event name passed to %s must be a non-empty, non-wildcard string', __METHOD__));
|
||||
}
|
||||
$returnListeners = [];
|
||||
foreach ($identifiers as $identifier) {
|
||||
if ('*' === $identifier || !\is_string($identifier) || empty($identifier)) {
|
||||
throw new Exception\InvalidArgumentException(\sprintf('Identifier names passed to %s must be non-empty, non-wildcard strings', __METHOD__));
|
||||
}
|
||||
if (isset($this->identifiers[$identifier])) {
|
||||
$listenersByIdentifier = $this->identifiers[$identifier];
|
||||
if (isset($listenersByIdentifier[$eventName])) {
|
||||
foreach ($listenersByIdentifier[$eventName] as $priority => $listeners) {
|
||||
$returnListeners[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
if (isset($listenersByIdentifier['*'])) {
|
||||
foreach ($listenersByIdentifier['*'] as $priority => $listeners) {
|
||||
$returnListeners[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isset($this->identifiers['*'])) {
|
||||
$wildcardIdentifier = $this->identifiers['*'];
|
||||
if (isset($wildcardIdentifier[$eventName])) {
|
||||
foreach ($wildcardIdentifier[$eventName] as $priority => $listeners) {
|
||||
$returnListeners[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
if (isset($wildcardIdentifier['*'])) {
|
||||
foreach ($wildcardIdentifier['*'] as $priority => $listeners) {
|
||||
$returnListeners[$priority][] = $listeners;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($returnListeners as $priority => $listOfListeners) {
|
||||
$returnListeners[$priority] = \array_merge(...$listOfListeners);
|
||||
}
|
||||
|
||||
return $returnListeners;
|
||||
}
|
||||
|
||||
public function clearListeners($identifier, $eventName = null)
|
||||
{
|
||||
if (!isset($this->identifiers[$identifier])) {
|
||||
return \false;
|
||||
}
|
||||
if (null === $eventName) {
|
||||
unset($this->identifiers[$identifier]);
|
||||
|
||||
return;
|
||||
}
|
||||
if (!isset($this->identifiers[$identifier][$eventName])) {
|
||||
return;
|
||||
}
|
||||
unset($this->identifiers[$identifier][$eventName]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
namespace _JchOptimizeVendor\Laminas\EventManager;
|
||||
|
||||
/**
|
||||
* Interface for shared event listener collections.
|
||||
*/
|
||||
interface SharedEventManagerInterface
|
||||
{
|
||||
/**
|
||||
* Attach a listener to an event emitted by components with specific identifiers.
|
||||
*
|
||||
* @param string $identifier Identifier for event emitting component
|
||||
* @param string $eventName
|
||||
* @param callable $listener listener that will handle the event
|
||||
* @param int $priority Priority at which listener should execute
|
||||
*/
|
||||
public function attach($identifier, $eventName, callable $listener, $priority = 1);
|
||||
|
||||
/**
|
||||
* Detach a shared listener.
|
||||
*
|
||||
* Allows detaching a listener from one or more events to which it may be
|
||||
* attached.
|
||||
*
|
||||
* @param callable $listener listener to detach
|
||||
* @param null|string $identifier identifier from which to detach; null indicates
|
||||
* all registered identifiers
|
||||
* @param null|string $eventName event from which to detach; null indicates
|
||||
* all registered events
|
||||
*
|
||||
* @throws Exception\InvalidArgumentException for invalid identifier arguments
|
||||
* @throws Exception\InvalidArgumentException for invalid event arguments
|
||||
*/
|
||||
public function detach(callable $listener, $identifier = null, $eventName = null);
|
||||
|
||||
/**
|
||||
* Retrieve all listeners for given identifiers.
|
||||
*
|
||||
* @param string $eventName
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getListeners(array $identifiers, $eventName);
|
||||
|
||||
/**
|
||||
* Clear all listeners for a given identifier, optionally for a specific event.
|
||||
*
|
||||
* @param string $identifier
|
||||
* @param null|string $eventName
|
||||
*/
|
||||
public function clearListeners($identifier, $eventName = null);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user