+ *
+ * @author Kolja Zuelsdorf
+ */
+class ProcessHandler extends AbstractProcessingHandler
+{
+ /**
+ * Holds the process to receive data on its STDIN.
+ *
+ * @var resource|bool|null
+ */
+ private $process;
+
+ /**
+ * @var string
+ */
+ private $command;
+
+ /**
+ * @var string|null
+ */
+ private $cwd;
+
+ /**
+ * @var resource[]
+ */
+ private $pipes = [];
+
+ /**
+ * @var array
+ */
+ protected const DESCRIPTOR_SPEC = [
+ 0 => ['pipe', 'r'], // STDIN is a pipe that the child will read from
+ 1 => ['pipe', 'w'], // STDOUT is a pipe that the child will write to
+ 2 => ['pipe', 'w'], // STDERR is a pipe to catch the any errors
+ ];
+
+ /**
+ * @param string $command Command for the process to start. Absolute paths are recommended,
+ * especially if you do not use the $cwd parameter.
+ * @param string|null $cwd "Current working directory" (CWD) for the process to be executed in.
+ * @throws \InvalidArgumentException
+ */
+ public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null)
+ {
+ if ($command === '') {
+ throw new \InvalidArgumentException('The command argument must be a non-empty string.');
+ }
+ if ($cwd === '') {
+ throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
+ }
+
+ parent::__construct($level, $bubble);
+
+ $this->command = $command;
+ $this->cwd = $cwd;
+ }
+
+ /**
+ * Writes the record down to the log of the implementing handler
+ *
+ * @throws \UnexpectedValueException
+ */
+ protected function write(array $record): void
+ {
+ $this->ensureProcessIsStarted();
+
+ $this->writeProcessInput($record['formatted']);
+
+ $errors = $this->readProcessErrors();
+ if (empty($errors) === false) {
+ throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
+ }
+ }
+
+ /**
+ * Makes sure that the process is actually started, and if not, starts it,
+ * assigns the stream pipes, and handles startup errors, if any.
+ */
+ private function ensureProcessIsStarted(): void
+ {
+ if (is_resource($this->process) === false) {
+ $this->startProcess();
+
+ $this->handleStartupErrors();
+ }
+ }
+
+ /**
+ * Starts the actual process and sets all streams to non-blocking.
+ */
+ private function startProcess(): void
+ {
+ $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
+
+ foreach ($this->pipes as $pipe) {
+ stream_set_blocking($pipe, false);
+ }
+ }
+
+ /**
+ * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
+ *
+ * @throws \UnexpectedValueException
+ */
+ private function handleStartupErrors(): void
+ {
+ $selected = $this->selectErrorStream();
+ if (false === $selected) {
+ throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
+ }
+
+ $errors = $this->readProcessErrors();
+
+ if (is_resource($this->process) === false || empty($errors) === false) {
+ throw new \UnexpectedValueException(
+ sprintf('The process "%s" could not be opened: ' . $errors, $this->command)
+ );
+ }
+ }
+
+ /**
+ * Selects the STDERR stream.
+ *
+ * @return int|bool
+ */
+ protected function selectErrorStream()
+ {
+ $empty = [];
+ $errorPipes = [$this->pipes[2]];
+
+ return stream_select($errorPipes, $empty, $empty, 1);
+ }
+
+ /**
+ * Reads the errors of the process, if there are any.
+ *
+ * @codeCoverageIgnore
+ * @return string Empty string if there are no errors.
+ */
+ protected function readProcessErrors(): string
+ {
+ return (string) stream_get_contents($this->pipes[2]);
+ }
+
+ /**
+ * Writes to the input stream of the opened process.
+ *
+ * @codeCoverageIgnore
+ */
+ protected function writeProcessInput(string $string): void
+ {
+ fwrite($this->pipes[0], $string);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function close(): void
+ {
+ if (is_resource($this->process)) {
+ foreach ($this->pipes as $pipe) {
+ fclose($pipe);
+ }
+ proc_close($this->process);
+ $this->process = null;
+ }
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php b/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
index 66a3d83a..3adec7a4 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php
@@ -16,25 +16,29 @@
/**
* Interface to describe loggers that have processors
*
- * This interface is present in monolog 1.x to ease forward compatibility.
- *
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
interface ProcessableHandlerInterface
{
/**
* Adds a processor in the stack.
*
+ * @psalm-param ProcessorInterface|callable(Record): Record $callback
+ *
* @param ProcessorInterface|callable $callback
* @return HandlerInterface self
*/
- public function pushProcessor($callback): HandlerInterface;
+ public function pushProcessor(callable $callback): HandlerInterface;
/**
* Removes the processor on top of the stack and returns it.
*
- * @throws \LogicException In case the processor stack is empty
- * @return callable
+ * @psalm-return ProcessorInterface|callable(Record): Record $callback
+ *
+ * @throws \LogicException In case the processor stack is empty
+ * @return callable|ProcessorInterface
*/
public function popProcessor(): callable;
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php b/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
index 09f32a12..9ef6e301 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php
@@ -12,26 +12,27 @@
namespace Monolog\Handler;
use Monolog\ResettableInterface;
+use Monolog\Processor\ProcessorInterface;
/**
* Helper trait for implementing ProcessableInterface
*
- * This trait is present in monolog 1.x to ease forward compatibility.
- *
* @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
trait ProcessableHandlerTrait
{
/**
* @var callable[]
+ * @phpstan-var array
*/
protected $processors = [];
/**
- * {@inheritdoc}
- * @suppress PhanTypeMismatchReturn
+ * {@inheritDoc}
*/
- public function pushProcessor($callback): HandlerInterface
+ public function pushProcessor(callable $callback): HandlerInterface
{
array_unshift($this->processors, $callback);
@@ -39,7 +40,7 @@ public function pushProcessor($callback): HandlerInterface
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
public function popProcessor(): callable
{
@@ -52,6 +53,9 @@ public function popProcessor(): callable
/**
* Processes a record.
+ *
+ * @phpstan-param Record $record
+ * @phpstan-return Record
*/
protected function processRecord(array $record): array
{
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php
index a99e6ab7..36e19ccc 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php
@@ -1,4 +1,4 @@
-
*/
-class PsrHandler extends AbstractHandler
+class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
{
/**
* PSR-3 compliant logger
@@ -28,12 +33,15 @@ class PsrHandler extends AbstractHandler
*/
protected $logger;
+ /**
+ * @var FormatterInterface|null
+ */
+ protected $formatter;
+
/**
* @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/
- public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bubble = true)
+ public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true)
{
parent::__construct($level, $bubble);
@@ -43,14 +51,45 @@ public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, $bu
/**
* {@inheritDoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if (!$this->isHandling($record)) {
return false;
}
- $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']);
+ if ($this->formatter) {
+ $formatted = $this->formatter->format($record);
+ $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']);
+ } else {
+ $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']);
+ }
return false === $this->bubble;
}
+
+ /**
+ * Sets the formatter.
+ *
+ * @param FormatterInterface $formatter
+ */
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
+ {
+ $this->formatter = $formatter;
+
+ return $this;
+ }
+
+ /**
+ * Gets the formatter.
+ *
+ * @return FormatterInterface
+ */
+ public function getFormatter(): FormatterInterface
+ {
+ if (!$this->formatter) {
+ throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
+ }
+
+ return $this->formatter;
+ }
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php
index f27bb3da..fed2303d 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php
@@ -1,4 +1,4 @@
-
* @see https://www.pushover.net/api
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class PushoverHandler extends SocketHandler
{
+ /** @var string */
private $token;
+ /** @var array */
private $users;
+ /** @var string */
private $title;
- private $user;
+ /** @var string|int|null */
+ private $user = null;
+ /** @var int */
private $retry;
+ /** @var int */
private $expire;
+ /** @var int */
private $highPriorityLevel;
+ /** @var int */
private $emergencyLevel;
+ /** @var bool */
private $useFormattedMessage = false;
/**
* All parameters that can be sent to Pushover
* @see https://pushover.net/api
- * @var array
+ * @var array
*/
- private $parameterNames = array(
+ private $parameterNames = [
'token' => true,
'user' => true,
'message' => true,
@@ -51,72 +66,103 @@ class PushoverHandler extends SocketHandler
'retry' => true,
'expire' => true,
'callback' => true,
- );
+ ];
/**
* Sounds the api supports by default
* @see https://pushover.net/api#sounds
- * @var array
+ * @var string[]
*/
- private $sounds = array(
+ private $sounds = [
'pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming',
'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb',
'persistent', 'echo', 'updown', 'none',
- );
+ ];
/**
* @param string $token Pushover api token
* @param string|array $users Pushover user id or array of ids the message will be sent to
- * @param string $title Title sent to the Pushover API
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param string|null $title Title sent to the Pushover API
* @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
* the pushover.net app owner. OpenSSL is required for this option.
- * @param int $highPriorityLevel The minimum logging level at which this handler will start
+ * @param string|int $highPriorityLevel The minimum logging level at which this handler will start
* sending "high priority" requests to the Pushover API
- * @param int $emergencyLevel The minimum logging level at which this handler will start
+ * @param string|int $emergencyLevel The minimum logging level at which this handler will start
* sending "emergency" requests to the Pushover API
- * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will send the same notification to the user.
- * @param int $expire The expire parameter specifies how many seconds your notification will continue to be retried for (every retry seconds).
+ * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will
+ * send the same notification to the user.
+ * @param int $expire The expire parameter specifies how many seconds your notification will continue
+ * to be retried for (every retry seconds).
+ *
+ * @phpstan-param string|array $users
+ * @phpstan-param Level|LevelName|LogLevel::* $highPriorityLevel
+ * @phpstan-param Level|LevelName|LogLevel::* $emergencyLevel
*/
- public function __construct($token, $users, $title = null, $level = Logger::CRITICAL, $bubble = true, $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, $retry = 30, $expire = 25200)
- {
+ public function __construct(
+ string $token,
+ $users,
+ ?string $title = null,
+ $level = Logger::CRITICAL,
+ bool $bubble = true,
+ bool $useSSL = true,
+ $highPriorityLevel = Logger::CRITICAL,
+ $emergencyLevel = Logger::EMERGENCY,
+ int $retry = 30,
+ int $expire = 25200,
+ bool $persistent = false,
+ float $timeout = 0.0,
+ float $writingTimeout = 10.0,
+ ?float $connectionTimeout = null,
+ ?int $chunkSize = null
+ ) {
$connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
- parent::__construct($connectionString, $level, $bubble);
+ parent::__construct(
+ $connectionString,
+ $level,
+ $bubble,
+ $persistent,
+ $timeout,
+ $writingTimeout,
+ $connectionTimeout,
+ $chunkSize
+ );
$this->token = $token;
$this->users = (array) $users;
- $this->title = $title ?: gethostname();
+ $this->title = $title ?: (string) gethostname();
$this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
$this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
$this->retry = $retry;
$this->expire = $expire;
}
- protected function generateDataStream($record)
+ protected function generateDataStream(array $record): string
{
$content = $this->buildContent($record);
return $this->buildHeader($content) . $content;
}
- private function buildContent($record)
+ /**
+ * @phpstan-param FormattedRecord $record
+ */
+ private function buildContent(array $record): string
{
// Pushover has a limit of 512 characters on title and message combined.
$maxMessageLength = 512 - strlen($this->title);
$message = ($this->useFormattedMessage) ? $record['formatted'] : $record['message'];
- $message = substr($message, 0, $maxMessageLength);
+ $message = Utils::substr($message, 0, $maxMessageLength);
$timestamp = $record['datetime']->getTimestamp();
- $dataArray = array(
+ $dataArray = [
'token' => $this->token,
'user' => $this->user,
'message' => $message,
'title' => $this->title,
'timestamp' => $timestamp,
- );
+ ];
if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
$dataArray['priority'] = 2;
@@ -141,7 +187,7 @@ private function buildContent($record)
return http_build_query($dataArray);
}
- private function buildHeader($content)
+ private function buildHeader(string $content): string
{
$header = "POST /1/messages.json HTTP/1.1\r\n";
$header .= "Host: api.pushover.net\r\n";
@@ -152,7 +198,7 @@ private function buildHeader($content)
return $header;
}
- protected function write(array $record)
+ protected function write(array $record): void
{
foreach ($this->users as $user) {
$this->user = $user;
@@ -164,22 +210,37 @@ protected function write(array $record)
$this->user = null;
}
- public function setHighPriorityLevel($value)
+ /**
+ * @param int|string $value
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $value
+ */
+ public function setHighPriorityLevel($value): self
{
- $this->highPriorityLevel = $value;
+ $this->highPriorityLevel = Logger::toMonologLevel($value);
+
+ return $this;
}
- public function setEmergencyLevel($value)
+ /**
+ * @param int|string $value
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $value
+ */
+ public function setEmergencyLevel($value): self
{
- $this->emergencyLevel = $value;
+ $this->emergencyLevel = Logger::toMonologLevel($value);
+
+ return $this;
}
/**
* Use the formatted message?
- * @param bool $value
*/
- public function useFormattedMessage($value)
+ public function useFormattedMessage(bool $value): self
{
- $this->useFormattedMessage = (bool) $value;
+ $this->useFormattedMessage = $value;
+
+ return $this;
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php
deleted file mode 100644
index b0298fa6..00000000
--- a/vendor/monolog/monolog/src/Monolog/Handler/RavenHandler.php
+++ /dev/null
@@ -1,234 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Monolog\Handler;
-
-use Monolog\Formatter\LineFormatter;
-use Monolog\Formatter\FormatterInterface;
-use Monolog\Logger;
-use Raven_Client;
-
-/**
- * Handler to send messages to a Sentry (https://github.com/getsentry/sentry) server
- * using sentry-php (https://github.com/getsentry/sentry-php)
- *
- * @author Marc Abramowitz
- */
-class RavenHandler extends AbstractProcessingHandler
-{
- /**
- * Translates Monolog log levels to Raven log levels.
- */
- protected $logLevels = array(
- Logger::DEBUG => Raven_Client::DEBUG,
- Logger::INFO => Raven_Client::INFO,
- Logger::NOTICE => Raven_Client::INFO,
- Logger::WARNING => Raven_Client::WARNING,
- Logger::ERROR => Raven_Client::ERROR,
- Logger::CRITICAL => Raven_Client::FATAL,
- Logger::ALERT => Raven_Client::FATAL,
- Logger::EMERGENCY => Raven_Client::FATAL,
- );
-
- /**
- * @var string should represent the current version of the calling
- * software. Can be any string (git commit, version number)
- */
- protected $release;
-
- /**
- * @var Raven_Client the client object that sends the message to the server
- */
- protected $ravenClient;
-
- /**
- * @var FormatterInterface The formatter to use for the logs generated via handleBatch()
- */
- protected $batchFormatter;
-
- /**
- * @param Raven_Client $ravenClient
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- */
- public function __construct(Raven_Client $ravenClient, $level = Logger::DEBUG, $bubble = true)
- {
- @trigger_error('The Monolog\Handler\RavenHandler class is deprecated. You should rather upgrade to the sentry/sentry 2.x and use Sentry\Monolog\Handler, see https://github.com/getsentry/sentry-php/blob/master/src/Monolog/Handler.php', E_USER_DEPRECATED);
-
- parent::__construct($level, $bubble);
-
- $this->ravenClient = $ravenClient;
- }
-
- /**
- * {@inheritdoc}
- */
- public function handleBatch(array $records)
- {
- $level = $this->level;
-
- // filter records based on their level
- $records = array_filter($records, function ($record) use ($level) {
- return $record['level'] >= $level;
- });
-
- if (!$records) {
- return;
- }
-
- // the record with the highest severity is the "main" one
- $record = array_reduce($records, function ($highest, $record) {
- if (null === $highest || $record['level'] > $highest['level']) {
- return $record;
- }
-
- return $highest;
- });
-
- // the other ones are added as a context item
- $logs = array();
- foreach ($records as $r) {
- $logs[] = $this->processRecord($r);
- }
-
- if ($logs) {
- $record['context']['logs'] = (string) $this->getBatchFormatter()->formatBatch($logs);
- }
-
- $this->handle($record);
- }
-
- /**
- * Sets the formatter for the logs generated by handleBatch().
- *
- * @param FormatterInterface $formatter
- */
- public function setBatchFormatter(FormatterInterface $formatter)
- {
- $this->batchFormatter = $formatter;
- }
-
- /**
- * Gets the formatter for the logs generated by handleBatch().
- *
- * @return FormatterInterface
- */
- public function getBatchFormatter()
- {
- if (!$this->batchFormatter) {
- $this->batchFormatter = $this->getDefaultBatchFormatter();
- }
-
- return $this->batchFormatter;
- }
-
- /**
- * {@inheritdoc}
- */
- protected function write(array $record)
- {
- $previousUserContext = false;
- $options = array();
- $options['level'] = $this->logLevels[$record['level']];
- $options['tags'] = array();
- if (!empty($record['extra']['tags'])) {
- $options['tags'] = array_merge($options['tags'], $record['extra']['tags']);
- unset($record['extra']['tags']);
- }
- if (!empty($record['context']['tags'])) {
- $options['tags'] = array_merge($options['tags'], $record['context']['tags']);
- unset($record['context']['tags']);
- }
- if (!empty($record['context']['fingerprint'])) {
- $options['fingerprint'] = $record['context']['fingerprint'];
- unset($record['context']['fingerprint']);
- }
- if (!empty($record['context']['logger'])) {
- $options['logger'] = $record['context']['logger'];
- unset($record['context']['logger']);
- } else {
- $options['logger'] = $record['channel'];
- }
- foreach ($this->getExtraParameters() as $key) {
- foreach (array('extra', 'context') as $source) {
- if (!empty($record[$source][$key])) {
- $options[$key] = $record[$source][$key];
- unset($record[$source][$key]);
- }
- }
- }
- if (!empty($record['context'])) {
- $options['extra']['context'] = $record['context'];
- if (!empty($record['context']['user'])) {
- $previousUserContext = $this->ravenClient->context->user;
- $this->ravenClient->user_context($record['context']['user']);
- unset($options['extra']['context']['user']);
- }
- }
- if (!empty($record['extra'])) {
- $options['extra']['extra'] = $record['extra'];
- }
-
- if (!empty($this->release) && !isset($options['release'])) {
- $options['release'] = $this->release;
- }
-
- if (isset($record['context']['exception']) && ($record['context']['exception'] instanceof \Exception || (PHP_VERSION_ID >= 70000 && $record['context']['exception'] instanceof \Throwable))) {
- $options['message'] = $record['formatted'];
- $this->ravenClient->captureException($record['context']['exception'], $options);
- } else {
- $this->ravenClient->captureMessage($record['formatted'], array(), $options);
- }
-
- if ($previousUserContext !== false) {
- $this->ravenClient->user_context($previousUserContext);
- }
- }
-
- /**
- * {@inheritDoc}
- */
- protected function getDefaultFormatter()
- {
- return new LineFormatter('[%channel%] %message%');
- }
-
- /**
- * Gets the default formatter for the logs generated by handleBatch().
- *
- * @return FormatterInterface
- */
- protected function getDefaultBatchFormatter()
- {
- return new LineFormatter();
- }
-
- /**
- * Gets extra parameters supported by Raven that can be found in "extra" and "context"
- *
- * @return array
- */
- protected function getExtraParameters()
- {
- return array('contexts', 'checksum', 'release', 'event_id');
- }
-
- /**
- * @param string $value
- * @return self
- */
- public function setRelease($value)
- {
- $this->release = $value;
-
- return $this;
- }
-}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
index 3725db24..91d16eaf 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.php
@@ -1,4 +1,4 @@
-pushHandler($redis);
*
* @author Thomas Tourlourat
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class RedisHandler extends AbstractProcessingHandler
{
+ /** @var \Predis\Client<\Predis\Client>|\Redis */
private $redisClient;
+ /** @var string */
private $redisKey;
+ /** @var int */
protected $capSize;
/**
- * @param \Predis\Client|\Redis $redis The redis instance
+ * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance
* @param string $key The key name to push records to
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param int|false $capSize Number of entries to limit list size to
+ * @param int $capSize Number of entries to limit list size to, 0 = unlimited
*/
- public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true, $capSize = false)
+ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0)
{
if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
throw new \InvalidArgumentException('Predis\Client or Redis instance required');
@@ -54,7 +58,7 @@ public function __construct($redis, $key, $level = Logger::DEBUG, $bubble = true
/**
* {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
if ($this->capSize) {
$this->writeCapped($record);
@@ -67,10 +71,9 @@ protected function write(array $record)
* Write and cap the collection
* Writes the record to the redis list and caps its
*
- * @param array $record associative record array
- * @return void
+ * @phpstan-param FormattedRecord $record
*/
- protected function writeCapped(array $record)
+ protected function writeCapped(array $record): void
{
if ($this->redisClient instanceof \Redis) {
$mode = defined('\Redis::MULTI') ? \Redis::MULTI : 1;
@@ -91,7 +94,7 @@ protected function writeCapped(array $record)
/**
* {@inheritDoc}
*/
- protected function getDefaultFormatter()
+ protected function getDefaultFormatter(): FormatterInterface
{
return new LineFormatter();
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php
new file mode 100644
index 00000000..7789309c
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Formatter\LineFormatter;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Logger;
+
+/**
+ * Sends the message to a Redis Pub/Sub channel using PUBLISH
+ *
+ * usage example:
+ *
+ * $log = new Logger('application');
+ * $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING);
+ * $log->pushHandler($redis);
+ *
+ * @author Gaëtan Faugère
+ */
+class RedisPubSubHandler extends AbstractProcessingHandler
+{
+ /** @var \Predis\Client<\Predis\Client>|\Redis */
+ private $redisClient;
+ /** @var string */
+ private $channelKey;
+
+ /**
+ * @param \Predis\Client<\Predis\Client>|\Redis $redis The redis instance
+ * @param string $key The channel key to publish records to
+ */
+ public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true)
+ {
+ if (!(($redis instanceof \Predis\Client) || ($redis instanceof \Redis))) {
+ throw new \InvalidArgumentException('Predis\Client or Redis instance required');
+ }
+
+ $this->redisClient = $redis;
+ $this->channelKey = $key;
+
+ parent::__construct($level, $bubble);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function write(array $record): void
+ {
+ $this->redisClient->publish($this->channelKey, $record["formatted"]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function getDefaultFormatter(): FormatterInterface
+ {
+ return new LineFormatter();
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php
index 65073ffe..adcc9395 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.php
@@ -1,4 +1,4 @@
- 'debug',
Logger::INFO => 'info',
Logger::NOTICE => 'info',
@@ -49,7 +48,7 @@ class RollbarHandler extends AbstractProcessingHandler
Logger::CRITICAL => 'critical',
Logger::ALERT => 'critical',
Logger::EMERGENCY => 'critical',
- );
+ ];
/**
* Records whether any log records have been added since the last flush of the rollbar notifier
@@ -58,24 +57,23 @@ class RollbarHandler extends AbstractProcessingHandler
*/
private $hasRecords = false;
+ /** @var bool */
protected $initialized = false;
/**
- * @param RollbarNotifier $rollbarNotifier RollbarNotifier object constructed with valid token
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
*/
- public function __construct(RollbarNotifier $rollbarNotifier, $level = Logger::ERROR, $bubble = true)
+ public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true)
{
- $this->rollbarNotifier = $rollbarNotifier;
+ $this->rollbarLogger = $rollbarLogger;
parent::__construct($level, $bubble);
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
if (!$this->initialized) {
// __destructor() doesn't get called on Fatal errors
@@ -84,54 +82,45 @@ protected function write(array $record)
}
$context = $record['context'];
- $payload = array();
- if (isset($context['payload'])) {
- $payload = $context['payload'];
- unset($context['payload']);
- }
- $context = array_merge($context, $record['extra'], array(
+ $context = array_merge($context, $record['extra'], [
'level' => $this->levelMap[$record['level']],
'monolog_level' => $record['level_name'],
'channel' => $record['channel'],
'datetime' => $record['datetime']->format('U'),
- ));
+ ]);
- if (isset($context['exception']) && $context['exception'] instanceof Exception) {
- $payload['level'] = $context['level'];
+ if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
$exception = $context['exception'];
unset($context['exception']);
-
- $this->rollbarNotifier->report_exception($exception, $context, $payload);
+ $toLog = $exception;
} else {
- $this->rollbarNotifier->report_message(
- $record['message'],
- $context['level'],
- $context,
- $payload
- );
+ $toLog = $record['message'];
}
+ // @phpstan-ignore-next-line
+ $this->rollbarLogger->log($context['level'], $toLog, $context);
+
$this->hasRecords = true;
}
- public function flush()
+ public function flush(): void
{
if ($this->hasRecords) {
- $this->rollbarNotifier->flush();
+ $this->rollbarLogger->flush();
$this->hasRecords = false;
}
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function close()
+ public function close(): void
{
$this->flush();
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
public function reset()
{
@@ -139,6 +128,4 @@ public function reset()
parent::reset();
}
-
-
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
index b8253ba0..17745d22 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php
@@ -1,4 +1,4 @@
-filename = Utils::canonicalizePath($filename);
- $this->maxFiles = (int) $maxFiles;
- $this->nextRotation = new \DateTime('tomorrow');
+ $this->maxFiles = $maxFiles;
+ $this->nextRotation = new \DateTimeImmutable('tomorrow');
$this->filenameFormat = '{filename}-{date}';
- $this->dateFormat = 'Y-m-d';
+ $this->dateFormat = static::FILE_PER_DAY;
parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function close()
+ public function close(): void
{
parent::close();
@@ -68,7 +73,7 @@ public function close()
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
public function reset()
{
@@ -79,40 +84,40 @@ public function reset()
}
}
- public function setFilenameFormat($filenameFormat, $dateFormat)
+ public function setFilenameFormat(string $filenameFormat, string $dateFormat): self
{
- if (!preg_match('{^Y(([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
- trigger_error(
+ if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
+ throw new InvalidArgumentException(
'Invalid date format - format must be one of '.
'RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") '.
'or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the '.
- 'date formats using slashes, underscores and/or dots instead of dashes.',
- E_USER_DEPRECATED
+ 'date formats using slashes, underscores and/or dots instead of dashes.'
);
}
if (substr_count($filenameFormat, '{date}') === 0) {
- trigger_error(
- 'Invalid filename format - format should contain at least `{date}`, because otherwise rotating is impossible.',
- E_USER_DEPRECATED
+ throw new InvalidArgumentException(
+ 'Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.'
);
}
$this->filenameFormat = $filenameFormat;
$this->dateFormat = $dateFormat;
$this->url = $this->getTimedFilename();
$this->close();
+
+ return $this;
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
// on the first record written, if the log is new, we should rotate (once per day)
if (null === $this->mustRotate) {
- $this->mustRotate = !file_exists($this->url);
+ $this->mustRotate = null === $this->url || !file_exists($this->url);
}
- if ($this->nextRotation < $record['datetime']) {
+ if ($this->nextRotation <= $record['datetime']) {
$this->mustRotate = true;
$this->close();
}
@@ -123,11 +128,11 @@ protected function write(array $record)
/**
* Rotates the files.
*/
- protected function rotate()
+ protected function rotate(): void
{
// update filename
$this->url = $this->getTimedFilename();
- $this->nextRotation = new \DateTime('tomorrow');
+ $this->nextRotation = new \DateTimeImmutable('tomorrow');
// skip GC of old logs if files are unlimited
if (0 === $this->maxFiles) {
@@ -135,6 +140,11 @@ protected function rotate()
}
$logFiles = glob($this->getGlobPattern());
+ if (false === $logFiles) {
+ // failed to glob
+ return;
+ }
+
if ($this->maxFiles >= count($logFiles)) {
// no files to remove
return;
@@ -149,7 +159,9 @@ protected function rotate()
if (is_writable($file)) {
// suppress errors here as unlink() might fail if two processes
// are cleaning up/rotating at the same time
- set_error_handler(function ($errno, $errstr, $errfile, $errline) {});
+ set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline): bool {
+ return false;
+ });
unlink($file);
restore_error_handler();
}
@@ -158,31 +170,35 @@ protected function rotate()
$this->mustRotate = false;
}
- protected function getTimedFilename()
+ protected function getTimedFilename(): string
{
$fileInfo = pathinfo($this->filename);
$timedFilename = str_replace(
- array('{filename}', '{date}'),
- array($fileInfo['filename'], date($this->dateFormat)),
+ ['{filename}', '{date}'],
+ [$fileInfo['filename'], date($this->dateFormat)],
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
- if (!empty($fileInfo['extension'])) {
+ if (isset($fileInfo['extension'])) {
$timedFilename .= '.'.$fileInfo['extension'];
}
return $timedFilename;
}
- protected function getGlobPattern()
+ protected function getGlobPattern(): string
{
$fileInfo = pathinfo($this->filename);
$glob = str_replace(
- array('{filename}', '{date}'),
- array($fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'),
+ ['{filename}', '{date}'],
+ [$fileInfo['filename'], str_replace(
+ ['Y', 'y', 'm', 'd'],
+ ['[0-9][0-9][0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]', '[0-9][0-9]'],
+ $this->dateFormat)
+ ],
$fileInfo['dirname'] . '/' . $this->filenameFormat
);
- if (!empty($fileInfo['extension'])) {
+ if (isset($fileInfo['extension'])) {
$glob .= '.'.$fileInfo['extension'];
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
index b547ed7d..c128a32d 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php
@@ -1,4 +1,4 @@
-
* @author Kunal Mehta
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
*/
-class SamplingHandler extends AbstractHandler
+class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
+ use ProcessableHandlerTrait;
+
/**
- * @var callable|HandlerInterface $handler
+ * @var HandlerInterface|callable
+ * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
*/
protected $handler;
@@ -40,10 +46,12 @@ class SamplingHandler extends AbstractHandler
protected $factor;
/**
+ * @psalm-param HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface $handler
+ *
* @param callable|HandlerInterface $handler Handler or factory callable($record|null, $samplingHandler).
- * @param int $factor Sample factor
+ * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
*/
- public function __construct($handler, $factor)
+ public function __construct($handler, int $factor)
{
parent::__construct();
$this->handler = $handler;
@@ -54,18 +62,17 @@ public function __construct($handler, $factor)
}
}
- public function isHandling(array $record)
+ public function isHandling(array $record): bool
{
return $this->getHandler($record)->isHandling($record);
}
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ /** @var Record $record */
+ $record = $this->processRecord($record);
}
$this->getHandler($record)->handle($record);
@@ -79,12 +86,14 @@ public function handle(array $record)
*
* If the handler was provided as a factory callable, this will trigger the handler's instantiation.
*
+ * @phpstan-param Record|array{level: Level}|null $record
+ *
* @return HandlerInterface
*/
public function getHandler(array $record = null)
{
if (!$this->handler instanceof HandlerInterface) {
- $this->handler = call_user_func($this->handler, $record, $this);
+ $this->handler = ($this->handler)($record, $this);
if (!$this->handler instanceof HandlerInterface) {
throw new \RuntimeException("The factory callable should return a HandlerInterface");
}
@@ -94,20 +103,30 @@ public function getHandler(array $record = null)
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
- $this->getHandler()->setFormatter($formatter);
+ $handler = $this->getHandler();
+ if ($handler instanceof FormattableHandlerInterface) {
+ $handler->setFormatter($formatter);
- return $this;
+ return $this;
+ }
+
+ throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function getFormatter()
+ public function getFormatter(): FormatterInterface
{
- return $this->getHandler()->getFormatter();
+ $handler = $this->getHandler();
+ if ($handler instanceof FormattableHandlerInterface) {
+ return $handler->getFormatter();
+ }
+
+ throw new \UnexpectedValueException('The nested handler of type '.get_class($handler).' does not support formatters.');
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php
new file mode 100644
index 00000000..1280ee70
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php
@@ -0,0 +1,102 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+
+/**
+ * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
+ *
+ * @author Ricardo Fontanelli
+ */
+class SendGridHandler extends MailHandler
+{
+ /**
+ * The SendGrid API User
+ * @var string
+ */
+ protected $apiUser;
+
+ /**
+ * The SendGrid API Key
+ * @var string
+ */
+ protected $apiKey;
+
+ /**
+ * The email addresses to which the message will be sent
+ * @var string
+ */
+ protected $from;
+
+ /**
+ * The email addresses to which the message will be sent
+ * @var string[]
+ */
+ protected $to;
+
+ /**
+ * The subject of the email
+ * @var string
+ */
+ protected $subject;
+
+ /**
+ * @param string $apiUser The SendGrid API User
+ * @param string $apiKey The SendGrid API Key
+ * @param string $from The sender of the email
+ * @param string|string[] $to The recipients of the email
+ * @param string $subject The subject of the mail
+ */
+ public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true)
+ {
+ if (!extension_loaded('curl')) {
+ throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler');
+ }
+
+ parent::__construct($level, $bubble);
+ $this->apiUser = $apiUser;
+ $this->apiKey = $apiKey;
+ $this->from = $from;
+ $this->to = (array) $to;
+ $this->subject = $subject;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function send(string $content, array $records): void
+ {
+ $message = [];
+ $message['api_user'] = $this->apiUser;
+ $message['api_key'] = $this->apiKey;
+ $message['from'] = $this->from;
+ foreach ($this->to as $recipient) {
+ $message['to[]'] = $recipient;
+ }
+ $message['subject'] = $this->subject;
+ $message['date'] = date('r');
+
+ if ($this->isHtmlBody($content)) {
+ $message['html'] = $content;
+ } else {
+ $message['text'] = $content;
+ }
+
+ $ch = curl_init();
+ curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
+ curl_setopt($ch, CURLOPT_POST, 1);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message));
+ Curl\Util::execute($ch, 2);
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php b/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
index 39455501..71a41094 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php
@@ -1,4 +1,4 @@
-
* @see https://api.slack.com/incoming-webhooks
* @see https://api.slack.com/docs/message-attachments
+ *
+ * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class SlackRecord
{
- const COLOR_DANGER = 'danger';
+ public const COLOR_DANGER = 'danger';
- const COLOR_WARNING = 'warning';
+ public const COLOR_WARNING = 'warning';
- const COLOR_GOOD = 'good';
+ public const COLOR_GOOD = 'good';
- const COLOR_DEFAULT = '#e3e4e6';
+ public const COLOR_DEFAULT = '#e3e4e6';
/**
* Slack channel (encoded ID or name)
@@ -48,7 +51,7 @@ class SlackRecord
/**
* User icon e.g. 'ghost', 'http://example.com/user.png'
- * @var string
+ * @var string|null
*/
private $userIcon;
@@ -72,12 +75,12 @@ class SlackRecord
/**
* Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
- * @var array
+ * @var string[]
*/
private $excludeFields;
/**
- * @var FormatterInterface
+ * @var ?FormatterInterface
*/
private $formatter;
@@ -86,26 +89,45 @@ class SlackRecord
*/
private $normalizerFormatter;
- public function __construct($channel = null, $username = null, $useAttachment = true, $userIcon = null, $useShortAttachment = false, $includeContextAndExtra = false, array $excludeFields = array(), FormatterInterface $formatter = null)
- {
- $this->channel = $channel;
- $this->username = $username;
- $this->userIcon = trim($userIcon, ':');
- $this->useAttachment = $useAttachment;
- $this->useShortAttachment = $useShortAttachment;
- $this->includeContextAndExtra = $includeContextAndExtra;
- $this->excludeFields = $excludeFields;
- $this->formatter = $formatter;
+ /**
+ * @param string[] $excludeFields
+ */
+ public function __construct(
+ ?string $channel = null,
+ ?string $username = null,
+ bool $useAttachment = true,
+ ?string $userIcon = null,
+ bool $useShortAttachment = false,
+ bool $includeContextAndExtra = false,
+ array $excludeFields = array(),
+ FormatterInterface $formatter = null
+ ) {
+ $this
+ ->setChannel($channel)
+ ->setUsername($username)
+ ->useAttachment($useAttachment)
+ ->setUserIcon($userIcon)
+ ->useShortAttachment($useShortAttachment)
+ ->includeContextAndExtra($includeContextAndExtra)
+ ->excludeFields($excludeFields)
+ ->setFormatter($formatter);
if ($this->includeContextAndExtra) {
$this->normalizerFormatter = new NormalizerFormatter();
}
}
- public function getSlackData(array $record)
+ /**
+ * Returns required data in format that Slack
+ * is expecting.
+ *
+ * @phpstan-param FormattedRecord $record
+ * @phpstan-return mixed[]
+ */
+ public function getSlackData(array $record): array
{
$dataArray = array();
- $record = $this->excludeFields($record);
+ $record = $this->removeExcludedFields($record);
if ($this->username) {
$dataArray['username'] = $this->username;
@@ -116,6 +138,7 @@ public function getSlackData(array $record)
}
if ($this->formatter && !$this->useAttachment) {
+ /** @phpstan-ignore-next-line */
$message = $this->formatter->format($record);
} else {
$message = $record['message'];
@@ -123,12 +146,14 @@ public function getSlackData(array $record)
if ($this->useAttachment) {
$attachment = array(
- 'fallback' => $message,
- 'text' => $message,
- 'color' => $this->getAttachmentColor($record['level']),
- 'fields' => array(),
- 'mrkdwn_in' => array('fields'),
- 'ts' => $record['datetime']->getTimestamp()
+ 'fallback' => $message,
+ 'text' => $message,
+ 'color' => $this->getAttachmentColor($record['level']),
+ 'fields' => array(),
+ 'mrkdwn_in' => array('fields'),
+ 'ts' => $record['datetime']->getTimestamp(),
+ 'footer' => $this->username,
+ 'footer_icon' => $this->userIcon,
);
if ($this->useShortAttachment) {
@@ -138,7 +163,6 @@ public function getSlackData(array $record)
$attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
}
-
if ($this->includeContextAndExtra) {
foreach (array('extra', 'context') as $key) {
if (empty($record[$key])) {
@@ -147,7 +171,7 @@ public function getSlackData(array $record)
if ($this->useShortAttachment) {
$attachment['fields'][] = $this->generateAttachmentField(
- $key,
+ (string) $key,
$record[$key]
);
} else {
@@ -177,93 +201,157 @@ public function getSlackData(array $record)
}
/**
- * Returned a Slack message attachment color associated with
+ * Returns a Slack message attachment color associated with
* provided level.
- *
- * @param int $level
- * @return string
*/
- public function getAttachmentColor($level)
+ public function getAttachmentColor(int $level): string
{
switch (true) {
case $level >= Logger::ERROR:
- return self::COLOR_DANGER;
+ return static::COLOR_DANGER;
case $level >= Logger::WARNING:
- return self::COLOR_WARNING;
+ return static::COLOR_WARNING;
case $level >= Logger::INFO:
- return self::COLOR_GOOD;
+ return static::COLOR_GOOD;
default:
- return self::COLOR_DEFAULT;
+ return static::COLOR_DEFAULT;
}
}
/**
* Stringifies an array of key/value pairs to be used in attachment fields
*
- * @param array $fields
- *
- * @return string
+ * @param mixed[] $fields
*/
- public function stringify($fields)
+ public function stringify(array $fields): string
{
+ /** @var Record $fields */
$normalized = $this->normalizerFormatter->format($fields);
- $prettyPrintFlag = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 128;
- $flags = 0;
- if (PHP_VERSION_ID >= 50400) {
- $flags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
- }
$hasSecondDimension = count(array_filter($normalized, 'is_array'));
$hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
return $hasSecondDimension || $hasNonNumericKeys
- ? Utils::jsonEncode($normalized, $prettyPrintFlag | $flags)
- : Utils::jsonEncode($normalized, $flags);
+ ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT|Utils::DEFAULT_JSON_FLAGS)
+ : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
}
/**
- * Sets the formatter
+ * Channel used by the bot when posting
+ *
+ * @param ?string $channel
*
- * @param FormatterInterface $formatter
+ * @return static
+ */
+ public function setChannel(?string $channel = null): self
+ {
+ $this->channel = $channel;
+
+ return $this;
+ }
+
+ /**
+ * Username used by the bot when posting
+ *
+ * @param ?string $username
+ *
+ * @return static
+ */
+ public function setUsername(?string $username = null): self
+ {
+ $this->username = $username;
+
+ return $this;
+ }
+
+ public function useAttachment(bool $useAttachment = true): self
+ {
+ $this->useAttachment = $useAttachment;
+
+ return $this;
+ }
+
+ public function setUserIcon(?string $userIcon = null): self
+ {
+ $this->userIcon = $userIcon;
+
+ if (\is_string($userIcon)) {
+ $this->userIcon = trim($userIcon, ':');
+ }
+
+ return $this;
+ }
+
+ public function useShortAttachment(bool $useShortAttachment = false): self
+ {
+ $this->useShortAttachment = $useShortAttachment;
+
+ return $this;
+ }
+
+ public function includeContextAndExtra(bool $includeContextAndExtra = false): self
+ {
+ $this->includeContextAndExtra = $includeContextAndExtra;
+
+ if ($this->includeContextAndExtra) {
+ $this->normalizerFormatter = new NormalizerFormatter();
+ }
+
+ return $this;
+ }
+
+ /**
+ * @param string[] $excludeFields
*/
- public function setFormatter(FormatterInterface $formatter)
+ public function excludeFields(array $excludeFields = []): self
+ {
+ $this->excludeFields = $excludeFields;
+
+ return $this;
+ }
+
+ public function setFormatter(?FormatterInterface $formatter = null): self
{
$this->formatter = $formatter;
+
+ return $this;
}
/**
* Generates attachment field
*
- * @param string $title
- * @param string|array $value
+ * @param string|mixed[] $value
*
- * @return array
+ * @return array{title: string, value: string, short: false}
*/
- private function generateAttachmentField($title, $value)
+ private function generateAttachmentField(string $title, $value): array
{
$value = is_array($value)
- ? sprintf('```%s```', $this->stringify($value))
+ ? sprintf('```%s```', substr($this->stringify($value), 0, 1990))
: $value;
return array(
'title' => ucfirst($title),
'value' => $value,
- 'short' => false
+ 'short' => false,
);
}
/**
* Generates a collection of attachment fields from array
*
- * @param array $data
+ * @param mixed[] $data
*
- * @return array
+ * @return array
*/
- private function generateAttachmentFields(array $data)
+ private function generateAttachmentFields(array $data): array
{
+ /** @var Record $data */
+ $normalized = $this->normalizerFormatter->format($data);
+
$fields = array();
- foreach ($this->normalizerFormatter->format($data) as $key => $value) {
- $fields[] = $this->generateAttachmentField($key, $value);
+ foreach ($normalized as $key => $value) {
+ $fields[] = $this->generateAttachmentField((string) $key, $value);
}
return $fields;
@@ -272,11 +360,11 @@ private function generateAttachmentFields(array $data)
/**
* Get a copy of record with fields excluded according to $this->excludeFields
*
- * @param array $record
+ * @phpstan-param FormattedRecord $record
*
- * @return array
+ * @return mixed[]
*/
- private function excludeFields(array $record)
+ private function removeExcludedFields(array $record): array
{
foreach ($this->excludeFields as $field) {
$keys = explode('.', $field);
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
index 88c4c4d0..a648513e 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php
@@ -1,4 +1,4 @@
-
* @see https://api.slack.com/
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class SlackHandler extends SocketHandler
{
@@ -42,20 +44,42 @@ class SlackHandler extends SocketHandler
* @param string|null $username Name of a bot
* @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
* @param string|null $iconEmoji The emoji name to use (or null)
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
+ * @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style
* @param bool $includeContextAndExtra Whether the attachment should include context and extra data
- * @param array $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
+ * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
* @throws MissingExtensionException If no OpenSSL PHP extension configured
*/
- public function __construct($token, $channel, $username = null, $useAttachment = true, $iconEmoji = null, $level = Logger::CRITICAL, $bubble = true, $useShortAttachment = false, $includeContextAndExtra = false, array $excludeFields = array())
- {
+ public function __construct(
+ string $token,
+ string $channel,
+ ?string $username = null,
+ bool $useAttachment = true,
+ ?string $iconEmoji = null,
+ $level = Logger::CRITICAL,
+ bool $bubble = true,
+ bool $useShortAttachment = false,
+ bool $includeContextAndExtra = false,
+ array $excludeFields = array(),
+ bool $persistent = false,
+ float $timeout = 0.0,
+ float $writingTimeout = 10.0,
+ ?float $connectionTimeout = null,
+ ?int $chunkSize = null
+ ) {
if (!extension_loaded('openssl')) {
throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
}
- parent::__construct('ssl://slack.com:443', $level, $bubble);
+ parent::__construct(
+ 'ssl://slack.com:443',
+ $level,
+ $bubble,
+ $persistent,
+ $timeout,
+ $writingTimeout,
+ $connectionTimeout,
+ $chunkSize
+ );
$this->slackRecord = new SlackRecord(
$channel,
@@ -64,30 +88,26 @@ public function __construct($token, $channel, $username = null, $useAttachment =
$iconEmoji,
$useShortAttachment,
$includeContextAndExtra,
- $excludeFields,
- $this->formatter
+ $excludeFields
);
$this->token = $token;
}
- public function getSlackRecord()
+ public function getSlackRecord(): SlackRecord
{
return $this->slackRecord;
}
- public function getToken()
+ public function getToken(): string
{
return $this->token;
}
/**
- * {@inheritdoc}
- *
- * @param array $record
- * @return string
+ * {@inheritDoc}
*/
- protected function generateDataStream($record)
+ protected function generateDataStream(array $record): string
{
$content = $this->buildContent($record);
@@ -97,10 +117,9 @@ protected function generateDataStream($record)
/**
* Builds the body of API call
*
- * @param array $record
- * @return string
+ * @phpstan-param FormattedRecord $record
*/
- private function buildContent($record)
+ private function buildContent(array $record): string
{
$dataArray = $this->prepareContentData($record);
@@ -108,12 +127,10 @@ private function buildContent($record)
}
/**
- * Prepares content data
- *
- * @param array $record
- * @return array
+ * @phpstan-param FormattedRecord $record
+ * @return string[]
*/
- protected function prepareContentData($record)
+ protected function prepareContentData(array $record): array
{
$dataArray = $this->slackRecord->getSlackData($record);
$dataArray['token'] = $this->token;
@@ -127,11 +144,8 @@ protected function prepareContentData($record)
/**
* Builds the header of the API Call
- *
- * @param string $content
- * @return string
*/
- private function buildHeader($content)
+ private function buildHeader(string $content): string
{
$header = "POST /api/chat.postMessage HTTP/1.1\r\n";
$header .= "Host: slack.com\r\n";
@@ -143,11 +157,9 @@ private function buildHeader($content)
}
/**
- * {@inheritdoc}
- *
- * @param array $record
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
parent::write($record);
$this->finalizeWrite();
@@ -159,7 +171,7 @@ protected function write(array $record)
* If we do not read some but close the socket too early, slack sometimes
* drops the request entirely.
*/
- protected function finalizeWrite()
+ protected function finalizeWrite(): void
{
$res = $this->getResource();
if (is_resource($res)) {
@@ -168,54 +180,77 @@ protected function finalizeWrite()
$this->closeSocket();
}
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
+ {
+ parent::setFormatter($formatter);
+ $this->slackRecord->setFormatter($formatter);
+
+ return $this;
+ }
+
+ public function getFormatter(): FormatterInterface
+ {
+ $formatter = parent::getFormatter();
+ $this->slackRecord->setFormatter($formatter);
+
+ return $formatter;
+ }
+
/**
- * Returned a Slack message attachment color associated with
- * provided level.
- *
- * @param int $level
- * @return string
- * @deprecated Use underlying SlackRecord instead
+ * Channel used by the bot when posting
*/
- protected function getAttachmentColor($level)
+ public function setChannel(string $channel): self
{
- trigger_error(
- 'SlackHandler::getAttachmentColor() is deprecated. Use underlying SlackRecord instead.',
- E_USER_DEPRECATED
- );
+ $this->slackRecord->setChannel($channel);
- return $this->slackRecord->getAttachmentColor($level);
+ return $this;
}
/**
- * Stringifies an array of key/value pairs to be used in attachment fields
- *
- * @param array $fields
- * @return string
- * @deprecated Use underlying SlackRecord instead
+ * Username used by the bot when posting
*/
- protected function stringify($fields)
+ public function setUsername(string $username): self
{
- trigger_error(
- 'SlackHandler::stringify() is deprecated. Use underlying SlackRecord instead.',
- E_USER_DEPRECATED
- );
+ $this->slackRecord->setUsername($username);
- return $this->slackRecord->stringify($fields);
+ return $this;
}
- public function setFormatter(FormatterInterface $formatter)
+ public function useAttachment(bool $useAttachment): self
{
- parent::setFormatter($formatter);
- $this->slackRecord->setFormatter($formatter);
+ $this->slackRecord->useAttachment($useAttachment);
return $this;
}
- public function getFormatter()
+ public function setIconEmoji(string $iconEmoji): self
{
- $formatter = parent::getFormatter();
- $this->slackRecord->setFormatter($formatter);
+ $this->slackRecord->setUserIcon($iconEmoji);
- return $formatter;
+ return $this;
+ }
+
+ public function useShortAttachment(bool $useShortAttachment): self
+ {
+ $this->slackRecord->useShortAttachment($useShortAttachment);
+
+ return $this;
+ }
+
+ public function includeContextAndExtra(bool $includeContextAndExtra): self
+ {
+ $this->slackRecord->includeContextAndExtra($includeContextAndExtra);
+
+ return $this;
+ }
+
+ /**
+ * @param string[] $excludeFields
+ */
+ public function excludeFields(array $excludeFields): self
+ {
+ $this->slackRecord->excludeFields($excludeFields);
+
+ return $this;
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
index b87be99a..8ae3c788 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php
@@ -1,4 +1,4 @@
-webhookUrl = $webhookUrl;
@@ -61,27 +73,24 @@ public function __construct($webhookUrl, $channel = null, $username = null, $use
$iconEmoji,
$useShortAttachment,
$includeContextAndExtra,
- $excludeFields,
- $this->formatter
+ $excludeFields
);
}
- public function getSlackRecord()
+ public function getSlackRecord(): SlackRecord
{
return $this->slackRecord;
}
- public function getWebhookUrl()
+ public function getWebhookUrl(): string
{
return $this->webhookUrl;
}
/**
- * {@inheritdoc}
- *
- * @param array $record
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
$postData = $this->slackRecord->getSlackData($record);
$postString = Utils::jsonEncode($postData);
@@ -92,7 +101,7 @@ protected function write(array $record)
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => array('Content-type: application/json'),
- CURLOPT_POSTFIELDS => $postString
+ CURLOPT_POSTFIELDS => $postString,
);
if (defined('CURLOPT_SAFE_UPLOAD')) {
$options[CURLOPT_SAFE_UPLOAD] = true;
@@ -103,7 +112,7 @@ protected function write(array $record)
Curl\Util::execute($ch);
}
- public function setFormatter(FormatterInterface $formatter)
+ public function setFormatter(FormatterInterface $formatter): HandlerInterface
{
parent::setFormatter($formatter);
$this->slackRecord->setFormatter($formatter);
@@ -111,7 +120,7 @@ public function setFormatter(FormatterInterface $formatter)
return $this;
}
- public function getFormatter()
+ public function getFormatter(): FormatterInterface
{
$formatter = parent::getFormatter();
$this->slackRecord->setFormatter($formatter);
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php
deleted file mode 100644
index d3352ea0..00000000
--- a/vendor/monolog/monolog/src/Monolog/Handler/SlackbotHandler.php
+++ /dev/null
@@ -1,84 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Monolog\Handler;
-
-use Monolog\Logger;
-
-/**
- * Sends notifications through Slack's Slackbot
- *
- * @author Haralan Dobrev
- * @see https://slack.com/apps/A0F81R8ET-slackbot
- * @deprecated According to Slack the API used on this handler it is deprecated.
- * Therefore this handler will be removed on 2.x
- * Slack suggests to use webhooks instead. Please contact slack for more information.
- */
-class SlackbotHandler extends AbstractProcessingHandler
-{
- /**
- * The slug of the Slack team
- * @var string
- */
- private $slackTeam;
-
- /**
- * Slackbot token
- * @var string
- */
- private $token;
-
- /**
- * Slack channel name
- * @var string
- */
- private $channel;
-
- /**
- * @param string $slackTeam Slack team slug
- * @param string $token Slackbot token
- * @param string $channel Slack channel (encoded ID or name)
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- */
- public function __construct($slackTeam, $token, $channel, $level = Logger::CRITICAL, $bubble = true)
- {
- @trigger_error('SlackbotHandler is deprecated and will be removed on 2.x', E_USER_DEPRECATED);
- parent::__construct($level, $bubble);
-
- $this->slackTeam = $slackTeam;
- $this->token = $token;
- $this->channel = $channel;
- }
-
- /**
- * {@inheritdoc}
- *
- * @param array $record
- */
- protected function write(array $record)
- {
- $slackbotUrl = sprintf(
- 'https://%s.slack.com/services/hooks/slackbot?token=%s&channel=%s',
- $this->slackTeam,
- $this->token,
- $this->channel
- );
-
- $ch = curl_init();
- curl_setopt($ch, CURLOPT_URL, $slackbotUrl);
- curl_setopt($ch, CURLOPT_POST, true);
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_POSTFIELDS, $record['message']);
-
- Curl\Util::execute($ch);
- }
-}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
index db50d97f..21701afa 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php
@@ -1,4 +1,4 @@
-
* @see http://php.net/manual/en/function.fsockopen.php
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class SocketHandler extends AbstractProcessingHandler
{
+ /** @var string */
private $connectionString;
+ /** @var float */
private $connectionTimeout;
+ /** @var resource|null */
private $resource;
- private $timeout = 0;
- private $writingTimeout = 10;
+ /** @var float */
+ private $timeout;
+ /** @var float */
+ private $writingTimeout;
+ /** @var ?int */
private $lastSentBytes = null;
- private $chunkSize = null;
- private $persistent = false;
- private $errno;
- private $errstr;
- private $lastWritingAt;
+ /** @var ?int */
+ private $chunkSize;
+ /** @var bool */
+ private $persistent;
+ /** @var ?int */
+ private $errno = null;
+ /** @var ?string */
+ private $errstr = null;
+ /** @var ?float */
+ private $lastWritingAt = null;
/**
- * @param string $connectionString Socket connection string
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param string $connectionString Socket connection string
+ * @param bool $persistent Flag to enable/disable persistent connections
+ * @param float $timeout Socket timeout to wait until the request is being aborted
+ * @param float $writingTimeout Socket timeout to wait until the request should've been sent/written
+ * @param float|null $connectionTimeout Socket connect timeout to wait until the connection should've been
+ * established
+ * @param int|null $chunkSize Sets the chunk size. Only has effect during connection in the writing cycle
+ *
+ * @throws \InvalidArgumentException If an invalid timeout value (less than 0) is passed.
*/
- public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true)
- {
+ public function __construct(
+ string $connectionString,
+ $level = Logger::DEBUG,
+ bool $bubble = true,
+ bool $persistent = false,
+ float $timeout = 0.0,
+ float $writingTimeout = 10.0,
+ ?float $connectionTimeout = null,
+ ?int $chunkSize = null
+ ) {
parent::__construct($level, $bubble);
$this->connectionString = $connectionString;
- $this->connectionTimeout = (float) ini_get('default_socket_timeout');
+
+ if ($connectionTimeout !== null) {
+ $this->validateTimeout($connectionTimeout);
+ }
+
+ $this->connectionTimeout = $connectionTimeout ?? (float) ini_get('default_socket_timeout');
+ $this->persistent = $persistent;
+ $this->validateTimeout($timeout);
+ $this->timeout = $timeout;
+ $this->validateTimeout($writingTimeout);
+ $this->writingTimeout = $writingTimeout;
+ $this->chunkSize = $chunkSize;
}
/**
* Connect (if necessary) and write to the socket
*
- * @param array $record
+ * {@inheritDoc}
*
* @throws \UnexpectedValueException
* @throws \RuntimeException
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
$this->connectIfNotConnected();
$data = $this->generateDataStream($record);
@@ -63,7 +102,7 @@ protected function write(array $record)
/**
* We will not close a PersistentSocket instance so it can be reused in other requests.
*/
- public function close()
+ public function close(): void
{
if (!$this->isPersistent()) {
$this->closeSocket();
@@ -73,7 +112,7 @@ public function close()
/**
* Close socket, if open
*/
- public function closeSocket()
+ public function closeSocket(): void
{
if (is_resource($this->resource)) {
fclose($this->resource);
@@ -82,39 +121,39 @@ public function closeSocket()
}
/**
- * Set socket connection to nbe persistent. It only has effect before the connection is initiated.
- *
- * @param bool $persistent
+ * Set socket connection to be persistent. It only has effect before the connection is initiated.
*/
- public function setPersistent($persistent)
+ public function setPersistent(bool $persistent): self
{
- $this->persistent = (bool) $persistent;
+ $this->persistent = $persistent;
+
+ return $this;
}
/**
* Set connection timeout. Only has effect before we connect.
*
- * @param float $seconds
- *
* @see http://php.net/manual/en/function.fsockopen.php
*/
- public function setConnectionTimeout($seconds)
+ public function setConnectionTimeout(float $seconds): self
{
$this->validateTimeout($seconds);
- $this->connectionTimeout = (float) $seconds;
+ $this->connectionTimeout = $seconds;
+
+ return $this;
}
/**
* Set write timeout. Only has effect before we connect.
*
- * @param float $seconds
- *
* @see http://php.net/manual/en/function.stream-set-timeout.php
*/
- public function setTimeout($seconds)
+ public function setTimeout(float $seconds): self
{
$this->validateTimeout($seconds);
- $this->timeout = (float) $seconds;
+ $this->timeout = $seconds;
+
+ return $this;
}
/**
@@ -122,58 +161,52 @@ public function setTimeout($seconds)
*
* @param float $seconds 0 for no timeout
*/
- public function setWritingTimeout($seconds)
+ public function setWritingTimeout(float $seconds): self
{
$this->validateTimeout($seconds);
- $this->writingTimeout = (float) $seconds;
+ $this->writingTimeout = $seconds;
+
+ return $this;
}
/**
* Set chunk size. Only has effect during connection in the writing cycle.
- *
- * @param float $bytes
*/
- public function setChunkSize($bytes)
+ public function setChunkSize(int $bytes): self
{
$this->chunkSize = $bytes;
+
+ return $this;
}
/**
* Get current connection string
- *
- * @return string
*/
- public function getConnectionString()
+ public function getConnectionString(): string
{
return $this->connectionString;
}
/**
* Get persistent setting
- *
- * @return bool
*/
- public function isPersistent()
+ public function isPersistent(): bool
{
return $this->persistent;
}
/**
* Get current connection timeout setting
- *
- * @return float
*/
- public function getConnectionTimeout()
+ public function getConnectionTimeout(): float
{
return $this->connectionTimeout;
}
/**
* Get current in-transfer timeout
- *
- * @return float
*/
- public function getTimeout()
+ public function getTimeout(): float
{
return $this->timeout;
}
@@ -183,17 +216,15 @@ public function getTimeout()
*
* @return float
*/
- public function getWritingTimeout()
+ public function getWritingTimeout(): float
{
return $this->writingTimeout;
}
/**
* Get current chunk size
- *
- * @return float
*/
- public function getChunkSize()
+ public function getChunkSize(): ?int
{
return $this->chunkSize;
}
@@ -202,10 +233,8 @@ public function getChunkSize()
* Check to see if the socket is currently available.
*
* UDP might appear to be connected but might fail when writing. See http://php.net/fsockopen for details.
- *
- * @return bool
*/
- public function isConnected()
+ public function isConnected(): bool
{
return is_resource($this->resource)
&& !feof($this->resource); // on TCP - other party can close connection.
@@ -213,6 +242,8 @@ public function isConnected()
/**
* Wrapper to allow mocking
+ *
+ * @return resource|false
*/
protected function pfsockopen()
{
@@ -221,6 +252,8 @@ protected function pfsockopen()
/**
* Wrapper to allow mocking
+ *
+ * @return resource|false
*/
protected function fsockopen()
{
@@ -231,50 +264,77 @@ protected function fsockopen()
* Wrapper to allow mocking
*
* @see http://php.net/manual/en/function.stream-set-timeout.php
+ *
+ * @return bool
*/
protected function streamSetTimeout()
{
$seconds = floor($this->timeout);
$microseconds = round(($this->timeout - $seconds) * 1e6);
- return stream_set_timeout($this->resource, $seconds, $microseconds);
+ if (!is_resource($this->resource)) {
+ throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
+ }
+
+ return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
}
/**
* Wrapper to allow mocking
*
* @see http://php.net/manual/en/function.stream-set-chunk-size.php
+ *
+ * @return int|bool
*/
protected function streamSetChunkSize()
{
+ if (!is_resource($this->resource)) {
+ throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
+ }
+
+ if (null === $this->chunkSize) {
+ throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
+ }
+
return stream_set_chunk_size($this->resource, $this->chunkSize);
}
/**
* Wrapper to allow mocking
+ *
+ * @return int|bool
*/
- protected function fwrite($data)
+ protected function fwrite(string $data)
{
+ if (!is_resource($this->resource)) {
+ throw new \LogicException('fwrite called but $this->resource is not a resource');
+ }
+
return @fwrite($this->resource, $data);
}
/**
* Wrapper to allow mocking
+ *
+ * @return mixed[]|bool
*/
protected function streamGetMetadata()
{
+ if (!is_resource($this->resource)) {
+ throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
+ }
+
return stream_get_meta_data($this->resource);
}
- private function validateTimeout($value)
+ private function validateTimeout(float $value): void
{
- $ok = filter_var($value, FILTER_VALIDATE_FLOAT);
- if ($ok === false || $value < 0) {
+ if ($value < 0) {
throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got $value)");
}
}
- private function connectIfNotConnected()
+ private function connectIfNotConnected(): void
{
if ($this->isConnected()) {
return;
@@ -282,7 +342,10 @@ private function connectIfNotConnected()
$this->connect();
}
- protected function generateDataStream($record)
+ /**
+ * @phpstan-param FormattedRecord $record
+ */
+ protected function generateDataStream(array $record): string
{
return (string) $record['formatted'];
}
@@ -295,41 +358,41 @@ protected function getResource()
return $this->resource;
}
- private function connect()
+ private function connect(): void
{
$this->createSocketResource();
$this->setSocketTimeout();
$this->setStreamChunkSize();
}
- private function createSocketResource()
+ private function createSocketResource(): void
{
if ($this->isPersistent()) {
$resource = $this->pfsockopen();
} else {
$resource = $this->fsockopen();
}
- if (!$resource) {
+ if (is_bool($resource)) {
throw new \UnexpectedValueException("Failed connecting to $this->connectionString ($this->errno: $this->errstr)");
}
$this->resource = $resource;
}
- private function setSocketTimeout()
+ private function setSocketTimeout(): void
{
if (!$this->streamSetTimeout()) {
throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
}
}
- private function setStreamChunkSize()
+ private function setStreamChunkSize(): void
{
if ($this->chunkSize && !$this->streamSetChunkSize()) {
throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
}
}
- private function writeToSocket($data)
+ private function writeToSocket(string $data): void
{
$length = strlen($data);
$sent = 0;
@@ -345,7 +408,7 @@ private function writeToSocket($data)
}
$sent += $chunk;
$socketInfo = $this->streamGetMetadata();
- if ($socketInfo['timed_out']) {
+ if (is_array($socketInfo) && $socketInfo['timed_out']) {
throw new \RuntimeException("Write timed-out");
}
@@ -358,15 +421,15 @@ private function writeToSocket($data)
}
}
- private function writingIsTimedOut($sent)
+ private function writingIsTimedOut(int $sent): bool
{
- $writingTimeout = (int) floor($this->writingTimeout);
- if (0 === $writingTimeout) {
+ // convert to ms
+ if (0.0 == $this->writingTimeout) {
return false;
}
if ($sent !== $this->lastSentBytes) {
- $this->lastWritingAt = time();
+ $this->lastWritingAt = microtime(true);
$this->lastSentBytes = $sent;
return false;
@@ -374,7 +437,7 @@ private function writingIsTimedOut($sent)
usleep(100);
}
- if ((time() - $this->lastWritingAt) >= $writingTimeout) {
+ if ((microtime(true) - $this->lastWritingAt) >= $this->writingTimeout) {
$this->closeSocket();
return true;
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php
new file mode 100644
index 00000000..dcf282b4
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php
@@ -0,0 +1,62 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Aws\Sqs\SqsClient;
+use Monolog\Logger;
+use Monolog\Utils;
+
+/**
+ * Writes to any sqs queue.
+ *
+ * @author Martijn van Calker
+ */
+class SqsHandler extends AbstractProcessingHandler
+{
+ /** 256 KB in bytes - maximum message size in SQS */
+ protected const MAX_MESSAGE_SIZE = 262144;
+ /** 100 KB in bytes - head message size for new error log */
+ protected const HEAD_MESSAGE_SIZE = 102400;
+
+ /** @var SqsClient */
+ private $client;
+ /** @var string */
+ private $queueUrl;
+
+ public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true)
+ {
+ parent::__construct($level, $bubble);
+
+ $this->client = $sqsClient;
+ $this->queueUrl = $queueUrl;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function write(array $record): void
+ {
+ if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
+ throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string' . Utils::getRecordMessageForException($record));
+ }
+
+ $messageBody = $record['formatted'];
+ if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
+ $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
+ }
+
+ $this->client->sendMessage([
+ 'QueueUrl' => $this->queueUrl,
+ 'MessageBody' => $messageBody,
+ ]);
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
index 74a613cb..65183512 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class StreamHandler extends AbstractProcessingHandler
{
- /** @private 512KB */
- const CHUNK_SIZE = 524288;
-
+ /** @const int */
+ protected const MAX_CHUNK_SIZE = 2147483647;
+ /** @const int 10MB */
+ protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
+ /** @var int */
+ protected $streamChunkSize;
/** @var resource|null */
protected $stream;
- protected $url;
- private $errorMessage;
+ /** @var ?string */
+ protected $url = null;
+ /** @var ?string */
+ private $errorMessage = null;
+ /** @var ?int */
protected $filePermission;
+ /** @var bool */
protected $useLocking;
- private $dirCreated;
+ /** @var true|null */
+ private $dirCreated = null;
/**
- * @param resource|string $stream
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param resource|string $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write
* @param int|null $filePermission Optional file permissions (default (0644) are only for owner read/write)
* @param bool $useLocking Try to lock log file before doing any writes
*
- * @throws \Exception If a missing directory is not buildable
* @throws \InvalidArgumentException If stream is not a resource or string
*/
- public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
+ public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
{
parent::__construct($level, $bubble);
+
+ if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) {
+ if ($phpMemoryLimit > 0) {
+ // use max 10% of allowed memory for the chunk size, and at least 100KB
+ $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024));
+ } else {
+ // memory is unlimited, set to the default 10MB
+ $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
+ }
+ } else {
+ // no memory limit information, set to the default 10MB
+ $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
+ }
+
if (is_resource($stream)) {
$this->stream = $stream;
- $this->streamSetChunkSize();
+
+ stream_set_chunk_size($this->stream, $this->streamChunkSize);
} elseif (is_string($stream)) {
$this->url = Utils::canonicalizePath($stream);
} else {
@@ -61,9 +83,9 @@ public function __construct($stream, $level = Logger::DEBUG, $bubble = true, $fi
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function close()
+ public function close(): void
{
if ($this->url && is_resource($this->stream)) {
fclose($this->stream);
@@ -87,78 +109,83 @@ public function getStream()
*
* @return string|null
*/
- public function getUrl()
+ public function getUrl(): ?string
{
return $this->url;
}
/**
- * {@inheritdoc}
+ * @return int
+ */
+ public function getStreamChunkSize(): int
+ {
+ return $this->streamChunkSize;
+ }
+
+ /**
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
if (!is_resource($this->stream)) {
- if (null === $this->url || '' === $this->url) {
- throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
+ $url = $this->url;
+ if (null === $url || '' === $url) {
+ throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().' . Utils::getRecordMessageForException($record));
}
- $this->createDir();
+ $this->createDir($url);
$this->errorMessage = null;
- set_error_handler(array($this, 'customErrorHandler'));
- $this->stream = fopen($this->url, 'a');
+ set_error_handler([$this, 'customErrorHandler']);
+ $stream = fopen($url, 'a');
if ($this->filePermission !== null) {
- @chmod($this->url, $this->filePermission);
+ @chmod($url, $this->filePermission);
}
restore_error_handler();
- if (!is_resource($this->stream)) {
+ if (!is_resource($stream)) {
$this->stream = null;
- throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $this->url));
+ throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: '.$this->errorMessage, $url) . Utils::getRecordMessageForException($record));
}
- $this->streamSetChunkSize();
+ stream_set_chunk_size($stream, $this->streamChunkSize);
+ $this->stream = $stream;
+ }
+
+ $stream = $this->stream;
+ if (!is_resource($stream)) {
+ throw new \LogicException('No stream was opened yet' . Utils::getRecordMessageForException($record));
}
if ($this->useLocking) {
// ignoring errors here, there's not much we can do about them
- flock($this->stream, LOCK_EX);
+ flock($stream, LOCK_EX);
}
- $this->streamWrite($this->stream, $record);
+ $this->streamWrite($stream, $record);
if ($this->useLocking) {
- flock($this->stream, LOCK_UN);
+ flock($stream, LOCK_UN);
}
}
/**
* Write to stream
* @param resource $stream
- * @param array $record
+ * @param array $record
+ *
+ * @phpstan-param FormattedRecord $record
*/
- protected function streamWrite($stream, array $record)
+ protected function streamWrite($stream, array $record): void
{
fwrite($stream, (string) $record['formatted']);
}
- protected function streamSetChunkSize()
- {
- if (version_compare(PHP_VERSION, '5.4.0', '>=')) {
- return stream_set_chunk_size($this->stream, self::CHUNK_SIZE);
- }
-
- return false;
- }
-
- private function customErrorHandler($code, $msg)
+ private function customErrorHandler(int $code, string $msg): bool
{
$this->errorMessage = preg_replace('{^(fopen|mkdir)\(.*?\): }', '', $msg);
+
+ return true;
}
- /**
- * @param string $stream
- *
- * @return null|string
- */
- private function getDirFromStream($stream)
+ private function getDirFromStream(string $stream): ?string
{
$pos = strpos($stream, '://');
if ($pos === false) {
@@ -172,21 +199,21 @@ private function getDirFromStream($stream)
return null;
}
- private function createDir()
+ private function createDir(string $url): void
{
// Do not try to create dir if it has already been tried.
if ($this->dirCreated) {
return;
}
- $dir = $this->getDirFromStream($this->url);
+ $dir = $this->getDirFromStream($url);
if (null !== $dir && !is_dir($dir)) {
$this->errorMessage = null;
- set_error_handler(array($this, 'customErrorHandler'));
+ set_error_handler([$this, 'customErrorHandler']);
$status = mkdir($dir, 0777, true);
restore_error_handler();
- if (false === $status && !is_dir($dir)) {
- throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage, $dir));
+ if (false === $status && !is_dir($dir) && strpos((string) $this->errorMessage, 'File exists') === false) {
+ throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: '.$this->errorMessage, $dir));
}
}
$this->dirCreated = true;
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php
index ac7b16ff..fae92514 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php
@@ -1,4 +1,4 @@
-mailer = $mailer;
$this->messageTemplate = $message;
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function send($content, array $records)
+ protected function send(string $content, array $records): void
{
$this->mailer->send($this->buildMessage($content, $records));
}
@@ -51,10 +60,9 @@ protected function send($content, array $records)
/**
* Gets the formatter for the Swift_Message subject.
*
- * @param string $format The format of the subject
- * @return FormatterInterface
+ * @param string|null $format The format of the subject
*/
- protected function getSubjectFormatter($format)
+ protected function getSubjectFormatter(?string $format): FormatterInterface
{
return new LineFormatter($format);
}
@@ -62,22 +70,25 @@ protected function getSubjectFormatter($format)
/**
* Creates instance of Swift_Message to be sent
*
- * @param string $content formatted email body to be sent
- * @param array $records Log records that formed the content
- * @return \Swift_Message
+ * @param string $content formatted email body to be sent
+ * @param array $records Log records that formed the content
+ * @return Swift_Message
+ *
+ * @phpstan-param Record[] $records
*/
- protected function buildMessage($content, array $records)
+ protected function buildMessage(string $content, array $records): Swift_Message
{
$message = null;
- if ($this->messageTemplate instanceof \Swift_Message) {
+ if ($this->messageTemplate instanceof Swift_Message) {
$message = clone $this->messageTemplate;
$message->generateId();
} elseif (is_callable($this->messageTemplate)) {
- $message = call_user_func($this->messageTemplate, $content, $records);
+ $message = ($this->messageTemplate)($content, $records);
}
- if (!$message instanceof \Swift_Message) {
- throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
+ if (!$message instanceof Swift_Message) {
+ $record = reset($records);
+ throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : ''));
}
if ($records) {
@@ -85,27 +96,20 @@ protected function buildMessage($content, array $records)
$message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
}
- $message->setBody($content);
+ $mime = 'text/plain';
+ if ($this->isHtmlBody($content)) {
+ $mime = 'text/html';
+ }
+
+ $message->setBody($content, $mime);
+ /** @phpstan-ignore-next-line */
if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
$message->setDate(new \DateTimeImmutable());
} else {
+ /** @phpstan-ignore-next-line */
$message->setDate(time());
}
return $message;
}
-
- /**
- * BC getter, to be removed in 2.0
- */
- public function __get($name)
- {
- if ($name === 'message') {
- trigger_error('SwiftMailerHandler->message is deprecated, use ->buildMessage() instead to retrieve the message', E_USER_DEPRECATED);
-
- return $this->buildMessage(null, array());
- }
-
- throw new \InvalidArgumentException('Invalid property '.$name);
- }
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php
new file mode 100644
index 00000000..130e6f1f
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SymfonyMailerHandler.php
@@ -0,0 +1,111 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use Monolog\Logger;
+use Monolog\Utils;
+use Monolog\Formatter\FormatterInterface;
+use Monolog\Formatter\LineFormatter;
+use Symfony\Component\Mailer\MailerInterface;
+use Symfony\Component\Mailer\Transport\TransportInterface;
+use Symfony\Component\Mime\Email;
+
+/**
+ * SymfonyMailerHandler uses Symfony's Mailer component to send the emails
+ *
+ * @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ */
+class SymfonyMailerHandler extends MailHandler
+{
+ /** @var MailerInterface|TransportInterface */
+ protected $mailer;
+ /** @var Email|callable(string, Record[]): Email */
+ private $emailTemplate;
+
+ /**
+ * @psalm-param Email|callable(string, Record[]): Email $email
+ *
+ * @param MailerInterface|TransportInterface $mailer The mailer to use
+ * @param callable|Email $email An email template, the subject/body will be replaced
+ */
+ public function __construct($mailer, $email, $level = Logger::ERROR, bool $bubble = true)
+ {
+ parent::__construct($level, $bubble);
+
+ $this->mailer = $mailer;
+ $this->emailTemplate = $email;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected function send(string $content, array $records): void
+ {
+ $this->mailer->send($this->buildMessage($content, $records));
+ }
+
+ /**
+ * Gets the formatter for the Swift_Message subject.
+ *
+ * @param string|null $format The format of the subject
+ */
+ protected function getSubjectFormatter(?string $format): FormatterInterface
+ {
+ return new LineFormatter($format);
+ }
+
+ /**
+ * Creates instance of Email to be sent
+ *
+ * @param string $content formatted email body to be sent
+ * @param array $records Log records that formed the content
+ *
+ * @phpstan-param Record[] $records
+ */
+ protected function buildMessage(string $content, array $records): Email
+ {
+ $message = null;
+ if ($this->emailTemplate instanceof Email) {
+ $message = clone $this->emailTemplate;
+ } elseif (is_callable($this->emailTemplate)) {
+ $message = ($this->emailTemplate)($content, $records);
+ }
+
+ if (!$message instanceof Email) {
+ $record = reset($records);
+ throw new \InvalidArgumentException('Could not resolve message as instance of Email or a callable returning it' . ($record ? Utils::getRecordMessageForException($record) : ''));
+ }
+
+ if ($records) {
+ $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
+ $message->subject($subjectFormatter->format($this->getHighestRecord($records)));
+ }
+
+ if ($this->isHtmlBody($content)) {
+ if (null !== ($charset = $message->getHtmlCharset())) {
+ $message->html($content, $charset);
+ } else {
+ $message->html($content);
+ }
+ } else {
+ if (null !== ($charset = $message->getTextCharset())) {
+ $message->text($content, $charset);
+ } else {
+ $message->text($content);
+ }
+ }
+
+ return $message->date(new \DateTimeImmutable());
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php
index f770c802..1d543b7e 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php
@@ -1,4 +1,4 @@
-facilities, or a LOG_* facility constant
+ * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
*/
- public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $logopts = LOG_PID)
+ public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID)
{
parent::__construct($facility, $level, $bubble);
@@ -47,20 +48,20 @@ public function __construct($ident, $facility = LOG_USER, $level = Logger::DEBUG
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function close()
+ public function close(): void
{
closelog();
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
if (!openlog($this->ident, $this->logopts, $this->facility)) {
- throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"');
+ throw new \LogicException('Can\'t open syslog for ident "'.$this->ident.'" and facility "'.$this->facility.'"' . Utils::getRecordMessageForException($record));
}
syslog($this->logLevels[$record['level']], (string) $record['formatted']);
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php
index 3bff085b..dbd8ef69 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php
@@ -1,4 +1,4 @@
-ip = $ip;
$this->port = $port;
- $this->socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
}
+ /**
+ * @param string $line
+ * @param string $header
+ * @return void
+ */
public function write($line, $header = "")
{
$this->send($this->assembleMessage($line, $header));
}
- public function close()
+ public function close(): void
{
- if (is_resource($this->socket)) {
+ if (is_resource($this->socket) || $this->socket instanceof Socket) {
socket_close($this->socket);
$this->socket = null;
}
}
- protected function send($chunk)
+ /**
+ * @return resource|Socket
+ */
+ protected function getSocket()
{
- if (!is_resource($this->socket)) {
- throw new \LogicException('The UdpSocket to '.$this->ip.':'.$this->port.' has been closed and can not be written to anymore');
+ if (null !== $this->socket) {
+ return $this->socket;
+ }
+
+ $domain = AF_INET;
+ $protocol = SOL_UDP;
+ // Check if we are using unix sockets.
+ if ($this->port === 0) {
+ $domain = AF_UNIX;
+ $protocol = IPPROTO_IP;
+ }
+
+ $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null;
+ if (null === $this->socket) {
+ throw new \RuntimeException('The UdpSocket to '.$this->ip.':'.$this->port.' could not be opened via socket_create');
}
- socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
+
+ return $this->socket;
+ }
+
+ protected function send(string $chunk): void
+ {
+ socket_sendto($this->getSocket(), $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
}
- protected function assembleMessage($line, $header)
+ protected function assembleMessage(string $line, string $header): string
{
- $chunkSize = self::DATAGRAM_MAX_LENGTH - strlen($header);
+ $chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header);
- return $header . substr($line, 0, $chunkSize);
+ return $header . Utils::substr($line, 0, $chunkSize);
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php
index 4dfd5f5e..deaa19f8 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php
@@ -1,4 +1,4 @@
- */
private $dateFormats = array(
self::RFC3164 => 'M d H:i:s',
self::RFC5424 => \DateTime::RFC3339,
+ self::RFC5424e => \DateTime::RFC3339_EXTENDED,
);
+ /** @var UdpSocket */
protected $socket;
+ /** @var string */
protected $ident;
+ /** @var self::RFC* */
protected $rfc;
/**
- * @param string $host
- * @param int $port
- * @param mixed $facility
- * @param int $level The minimum logging level at which this handler will be triggered
- * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
- * @param string $ident Program name or tag for each log message.
- * @param int $rfc RFC to format the message for.
+ * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
+ * @param int $port Port number, or 0 if $host is a unix socket
+ * @param string|int $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
+ * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
+ * @param string $ident Program name or tag for each log message.
+ * @param int $rfc RFC to format the message for.
+ * @throws MissingExtensionException
+ *
+ * @phpstan-param self::RFC* $rfc
*/
- public function __construct($host, $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, $bubble = true, $ident = 'php', $rfc = self::RFC5424)
+ public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424)
{
+ if (!extension_loaded('sockets')) {
+ throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
+ }
+
parent::__construct($facility, $level, $bubble);
$this->ident = $ident;
$this->rfc = $rfc;
- $this->socket = new UdpSocket($host, $port ?: 514);
+ $this->socket = new UdpSocket($host, $port);
}
- protected function write(array $record)
+ protected function write(array $record): void
{
$lines = $this->splitMessageIntoLines($record['formatted']);
- $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']]);
+ $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']);
foreach ($lines as $line) {
$this->socket->write($line, $header);
}
}
- public function close()
+ public function close(): void
{
$this->socket->close();
}
- private function splitMessageIntoLines($message)
+ /**
+ * @param string|string[] $message
+ * @return string[]
+ */
+ private function splitMessageIntoLines($message): array
{
if (is_array($message)) {
$message = implode("\n", $message);
}
- return preg_split('/$\R?^/m', $message, -1, PREG_SPLIT_NO_EMPTY);
+ $lines = preg_split('/$\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
+ if (false === $lines) {
+ $pcreErrorCode = preg_last_error();
+ throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
+ }
+
+ return $lines;
}
/**
* Make common syslog header (see rfc5424 or rfc3164)
*/
- protected function makeCommonSyslogHeader($severity)
+ protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime): string
{
$priority = $severity + $this->facility;
@@ -93,32 +117,34 @@ protected function makeCommonSyslogHeader($severity)
$hostname = '-';
}
- $date = $this->getDateTime();
-
if ($this->rfc === self::RFC3164) {
+ // see https://github.com/phpstan/phpstan/issues/5348
+ // @phpstan-ignore-next-line
+ $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
+ $date = $dateNew->format($this->dateFormats[$this->rfc]);
+
return "<$priority>" .
$date . " " .
$hostname . " " .
$this->ident . "[" . $pid . "]: ";
- } else {
- return "<$priority>1 " .
- $date . " " .
- $hostname . " " .
- $this->ident . " " .
- $pid . " - - ";
}
- }
- protected function getDateTime()
- {
- return date($this->dateFormats[$this->rfc]);
+ $date = $datetime->format($this->dateFormats[$this->rfc]);
+
+ return "<$priority>1 " .
+ $date . " " .
+ $hostname . " " .
+ $this->ident . " " .
+ $pid . " - - ";
}
/**
* Inject your own socket, mainly used for testing
*/
- public function setSocket($socket)
+ public function setSocket(UdpSocket $socket): self
{
$this->socket = $socket;
+
+ return $this;
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php
new file mode 100644
index 00000000..8912eba5
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php
@@ -0,0 +1,274 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+use RuntimeException;
+use Monolog\Logger;
+use Monolog\Utils;
+
+/**
+ * Handler send logs to Telegram using Telegram Bot API.
+ *
+ * How to use:
+ * 1) Create telegram bot with https://telegram.me/BotFather
+ * 2) Create a telegram channel where logs will be recorded.
+ * 3) Add created bot from step 1 to the created channel from step 2.
+ *
+ * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
+ *
+ * @link https://core.telegram.org/bots/api
+ *
+ * @author Mazur Alexandr
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ */
+class TelegramBotHandler extends AbstractProcessingHandler
+{
+ private const BOT_API = 'https://api.telegram.org/bot';
+
+ /**
+ * The available values of parseMode according to the Telegram api documentation
+ */
+ private const AVAILABLE_PARSE_MODES = [
+ 'HTML',
+ 'MarkdownV2',
+ 'Markdown', // legacy mode without underline and strikethrough, use MarkdownV2 instead
+ ];
+
+ /**
+ * The maximum number of characters allowed in a message according to the Telegram api documentation
+ */
+ private const MAX_MESSAGE_LENGTH = 4096;
+
+ /**
+ * Telegram bot access token provided by BotFather.
+ * Create telegram bot with https://telegram.me/BotFather and use access token from it.
+ * @var string
+ */
+ private $apiKey;
+
+ /**
+ * Telegram channel name.
+ * Since to start with '@' symbol as prefix.
+ * @var string
+ */
+ private $channel;
+
+ /**
+ * The kind of formatting that is used for the message.
+ * See available options at https://core.telegram.org/bots/api#formatting-options
+ * or in AVAILABLE_PARSE_MODES
+ * @var ?string
+ */
+ private $parseMode;
+
+ /**
+ * Disables link previews for links in the message.
+ * @var ?bool
+ */
+ private $disableWebPagePreview;
+
+ /**
+ * Sends the message silently. Users will receive a notification with no sound.
+ * @var ?bool
+ */
+ private $disableNotification;
+
+ /**
+ * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
+ * False - truncates a message that is too long.
+ * @var bool
+ */
+ private $splitLongMessages;
+
+ /**
+ * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
+ * @var bool
+ */
+ private $delayBetweenMessages;
+
+ /**
+ * @param string $apiKey Telegram bot access token provided by BotFather
+ * @param string $channel Telegram channel name
+ * @param bool $splitLongMessages Split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages
+ * @param bool $delayBetweenMessages Adds delay between sending a split message according to Telegram API
+ * @throws MissingExtensionException
+ */
+ public function __construct(
+ string $apiKey,
+ string $channel,
+ $level = Logger::DEBUG,
+ bool $bubble = true,
+ string $parseMode = null,
+ bool $disableWebPagePreview = null,
+ bool $disableNotification = null,
+ bool $splitLongMessages = false,
+ bool $delayBetweenMessages = false
+ )
+ {
+ if (!extension_loaded('curl')) {
+ throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
+ }
+
+ parent::__construct($level, $bubble);
+
+ $this->apiKey = $apiKey;
+ $this->channel = $channel;
+ $this->setParseMode($parseMode);
+ $this->disableWebPagePreview($disableWebPagePreview);
+ $this->disableNotification($disableNotification);
+ $this->splitLongMessages($splitLongMessages);
+ $this->delayBetweenMessages($delayBetweenMessages);
+ }
+
+ public function setParseMode(string $parseMode = null): self
+ {
+ if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
+ throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
+ }
+
+ $this->parseMode = $parseMode;
+
+ return $this;
+ }
+
+ public function disableWebPagePreview(bool $disableWebPagePreview = null): self
+ {
+ $this->disableWebPagePreview = $disableWebPagePreview;
+
+ return $this;
+ }
+
+ public function disableNotification(bool $disableNotification = null): self
+ {
+ $this->disableNotification = $disableNotification;
+
+ return $this;
+ }
+
+ /**
+ * True - split a message longer than MAX_MESSAGE_LENGTH into parts and send in multiple messages.
+ * False - truncates a message that is too long.
+ * @param bool $splitLongMessages
+ * @return $this
+ */
+ public function splitLongMessages(bool $splitLongMessages = false): self
+ {
+ $this->splitLongMessages = $splitLongMessages;
+
+ return $this;
+ }
+
+ /**
+ * Adds 1-second delay between sending a split message (according to Telegram API to avoid 429 Too Many Requests).
+ * @param bool $delayBetweenMessages
+ * @return $this
+ */
+ public function delayBetweenMessages(bool $delayBetweenMessages = false): self
+ {
+ $this->delayBetweenMessages = $delayBetweenMessages;
+
+ return $this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function handleBatch(array $records): void
+ {
+ /** @var Record[] $messages */
+ $messages = [];
+
+ foreach ($records as $record) {
+ if (!$this->isHandling($record)) {
+ continue;
+ }
+
+ if ($this->processors) {
+ /** @var Record $record */
+ $record = $this->processRecord($record);
+ }
+
+ $messages[] = $record;
+ }
+
+ if (!empty($messages)) {
+ $this->send((string)$this->getFormatter()->formatBatch($messages));
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ protected function write(array $record): void
+ {
+ $this->send($record['formatted']);
+ }
+
+ /**
+ * Send request to @link https://api.telegram.org/bot on SendMessage action.
+ * @param string $message
+ */
+ protected function send(string $message): void
+ {
+ $messages = $this->handleMessageLength($message);
+
+ foreach ($messages as $key => $msg) {
+ if ($this->delayBetweenMessages && $key > 0) {
+ sleep(1);
+ }
+
+ $this->sendCurl($msg);
+ }
+ }
+
+ protected function sendCurl(string $message): void
+ {
+ $ch = curl_init();
+ $url = self::BOT_API . $this->apiKey . '/SendMessage';
+ curl_setopt($ch, CURLOPT_URL, $url);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
+ 'text' => $message,
+ 'chat_id' => $this->channel,
+ 'parse_mode' => $this->parseMode,
+ 'disable_web_page_preview' => $this->disableWebPagePreview,
+ 'disable_notification' => $this->disableNotification,
+ ]));
+
+ $result = Curl\Util::execute($ch);
+ if (!is_string($result)) {
+ throw new RuntimeException('Telegram API error. Description: No response');
+ }
+ $result = json_decode($result, true);
+
+ if ($result['ok'] === false) {
+ throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
+ }
+ }
+
+ /**
+ * Handle a message that is too long: truncates or splits into several
+ * @param string $message
+ * @return string[]
+ */
+ private function handleMessageLength(string $message): array
+ {
+ $truncatedMarker = ' (...truncated)';
+ if (!$this->splitLongMessages && strlen($message) > self::MAX_MESSAGE_LENGTH) {
+ return [Utils::substr($message, 0, self::MAX_MESSAGE_LENGTH - strlen($truncatedMarker)) . $truncatedMarker];
+ }
+
+ return str_split($message, self::MAX_MESSAGE_LENGTH);
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php
index 478db0ac..0986da27 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/TestHandler.php
@@ -1,4 +1,4 @@
- */
+ protected $recordsByLevel = [];
+ /** @var bool */
private $skipReset = false;
+ /**
+ * @return array
+ *
+ * @phpstan-return Record[]
+ */
public function getRecords()
{
return $this->records;
}
+ /**
+ * @return void
+ */
public function clear()
{
- $this->records = array();
- $this->recordsByLevel = array();
+ $this->records = [];
+ $this->recordsByLevel = [];
}
+ /**
+ * @return void
+ */
public function reset()
{
if (!$this->skipReset) {
@@ -87,21 +108,32 @@ public function reset()
}
}
- public function setSkipReset($skipReset)
+ /**
+ * @return void
+ */
+ public function setSkipReset(bool $skipReset)
{
$this->skipReset = $skipReset;
}
- public function hasRecords($level)
+ /**
+ * @param string|int $level Logging level value or name
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function hasRecords($level): bool
{
- return isset($this->recordsByLevel[$level]);
+ return isset($this->recordsByLevel[Logger::toMonologLevel($level)]);
}
/**
* @param string|array $record Either a message string or an array containing message and optionally context keys that will be checked against all records
- * @param int $level Logger::LEVEL constant value
+ * @param string|int $level Logging level value or name
+ *
+ * @phpstan-param array{message: string, context?: mixed[]}|string $record
+ * @phpstan-param Level|LevelName|LogLevel::* $level
*/
- public function hasRecord($record, $level)
+ public function hasRecord($record, $level): bool
{
if (is_string($record)) {
$record = array('message' => $record);
@@ -114,36 +146,52 @@ public function hasRecord($record, $level)
if (isset($record['context']) && $rec['context'] !== $record['context']) {
return false;
}
+
return true;
}, $level);
}
- public function hasRecordThatContains($message, $level)
+ /**
+ * @param string|int $level Logging level value or name
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function hasRecordThatContains(string $message, $level): bool
{
return $this->hasRecordThatPasses(function ($rec) use ($message) {
return strpos($rec['message'], $message) !== false;
}, $level);
}
- public function hasRecordThatMatches($regex, $level)
+ /**
+ * @param string|int $level Logging level value or name
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function hasRecordThatMatches(string $regex, $level): bool
{
- return $this->hasRecordThatPasses(function ($rec) use ($regex) {
+ return $this->hasRecordThatPasses(function (array $rec) use ($regex): bool {
return preg_match($regex, $rec['message']) > 0;
}, $level);
}
- public function hasRecordThatPasses($predicate, $level)
+ /**
+ * @param string|int $level Logging level value or name
+ * @return bool
+ *
+ * @psalm-param callable(Record, int): mixed $predicate
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function hasRecordThatPasses(callable $predicate, $level)
{
- if (!is_callable($predicate)) {
- throw new \InvalidArgumentException("Expected a callable for hasRecordThatSucceeds");
- }
+ $level = Logger::toMonologLevel($level);
if (!isset($this->recordsByLevel[$level])) {
return false;
}
foreach ($this->recordsByLevel[$level] as $i => $rec) {
- if (call_user_func($predicate, $rec, $i)) {
+ if ($predicate($rec, $i)) {
return true;
}
}
@@ -152,23 +200,29 @@ public function hasRecordThatPasses($predicate, $level)
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
$this->recordsByLevel[$record['level']][] = $record;
$this->records[] = $record;
}
+ /**
+ * @param string $method
+ * @param mixed[] $args
+ * @return bool
+ */
public function __call($method, $args)
{
if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
$genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
$level = constant('Monolog\Logger::' . strtoupper($matches[2]));
- if (method_exists($this, $genericMethod)) {
+ $callback = [$this, $genericMethod];
+ if (is_callable($callback)) {
$args[] = $level;
- return call_user_func_array(array($this, $genericMethod), $args);
+ return call_user_func_array($callback, $args);
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php b/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php
new file mode 100644
index 00000000..c8183528
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php
@@ -0,0 +1,24 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Handler;
+
+trait WebRequestRecognizerTrait
+{
+ /**
+ * Checks if PHP's serving a web request
+ * @return bool
+ */
+ protected function isWebRequest(): bool
+ {
+ return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php
index 7d7622a3..b6d3d3b1 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
class WhatFailureGroupHandler extends GroupHandler
{
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function handle(array $record)
+ public function handle(array $record): bool
{
if ($this->processors) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
+ /** @var Record $record */
+ $record = $this->processRecord($record);
}
foreach ($this->handlers as $handler) {
try {
$handler->handle($record);
- } catch (\Exception $e) {
- // What failure?
} catch (\Throwable $e) {
// What failure?
}
@@ -44,26 +43,36 @@ public function handle(array $record)
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function handleBatch(array $records)
+ public function handleBatch(array $records): void
{
if ($this->processors) {
$processed = array();
foreach ($records as $record) {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
- }
- $processed[] = $record;
+ $processed[] = $this->processRecord($record);
}
+ /** @var Record[] $records */
$records = $processed;
}
foreach ($this->handlers as $handler) {
try {
$handler->handleBatch($records);
- } catch (\Exception $e) {
+ } catch (\Throwable $e) {
// What failure?
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function close(): void
+ {
+ foreach ($this->handlers as $handler) {
+ try {
+ $handler->close();
} catch (\Throwable $e) {
// What failure?
}
diff --git a/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php b/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php
index a20aeae0..ddd46d8c 100644
--- a/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php
+++ b/vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php
@@ -1,4 +1,5 @@
-
* @author Jason Davis
+ *
+ * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
*/
class ZendMonitorHandler extends AbstractProcessingHandler
{
/**
* Monolog level / ZendMonitor Custom Event priority map
*
- * @var array
+ * @var array
*/
- protected $levelMap = array();
+ protected $levelMap = [];
/**
- * Construct
- *
- * @param int $level
- * @param bool $bubble
* @throws MissingExtensionException
*/
- public function __construct($level = Logger::DEBUG, $bubble = true)
+ public function __construct($level = Logger::DEBUG, bool $bubble = true)
{
if (!function_exists('zend_monitor_custom_event')) {
throw new MissingExtensionException(
@@ -43,7 +43,7 @@ public function __construct($level = Logger::DEBUG, $bubble = true)
);
}
//zend monitor constants are not defined if zend monitor is not enabled.
- $this->levelMap = array(
+ $this->levelMap = [
Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO,
@@ -52,14 +52,14 @@ public function __construct($level = Logger::DEBUG, $bubble = true)
Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR,
- );
+ ];
parent::__construct($level, $bubble);
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- protected function write(array $record)
+ protected function write(array $record): void
{
$this->writeZendMonitorCustomEvent(
Logger::getLevelName($record['level']),
@@ -71,30 +71,30 @@ protected function write(array $record)
/**
* Write to Zend Monitor Events
- * @param string $type Text displayed in "Class Name (custom)" field
- * @param string $message Text displayed in "Error String"
- * @param mixed $formatted Displayed in Custom Variables tab
- * @param int $severity Set the event severity level (-1,0,1)
+ * @param string $type Text displayed in "Class Name (custom)" field
+ * @param string $message Text displayed in "Error String"
+ * @param array $formatted Displayed in Custom Variables tab
+ * @param int $severity Set the event severity level (-1,0,1)
+ *
+ * @phpstan-param FormattedRecord $formatted
*/
- protected function writeZendMonitorCustomEvent($type, $message, $formatted, $severity)
+ protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity): void
{
zend_monitor_custom_event($type, $message, $formatted, $severity);
}
/**
- * {@inheritdoc}
+ * {@inheritDoc}
*/
- public function getDefaultFormatter()
+ public function getDefaultFormatter(): FormatterInterface
{
return new NormalizerFormatter();
}
/**
- * Get the level map
- *
- * @return array
+ * @return array
*/
- public function getLevelMap()
+ public function getLevelMap(): array
{
return $this->levelMap;
}
diff --git a/vendor/monolog/monolog/src/Monolog/LogRecord.php b/vendor/monolog/monolog/src/Monolog/LogRecord.php
new file mode 100644
index 00000000..702807d7
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/LogRecord.php
@@ -0,0 +1,34 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog;
+
+use ArrayAccess;
+
+/**
+ * Monolog log record interface for forward compatibility with Monolog 3.0
+ *
+ * This is just present in Monolog 2.4+ to allow interoperable code to be written against
+ * both versions by type-hinting arguments as `array|\Monolog\LogRecord $record`
+ *
+ * Do not rely on this interface for other purposes, and do not implement it.
+ *
+ * @author Jordi Boggiano
+ * @template-extends \ArrayAccess<'message'|'level'|'context'|'level_name'|'channel'|'datetime'|'extra'|'formatted', mixed>
+ * @phpstan-import-type Record from Logger
+ */
+interface LogRecord extends \ArrayAccess
+{
+ /**
+ * @phpstan-return Record
+ */
+ public function toArray(): array;
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Logger.php b/vendor/monolog/monolog/src/Monolog/Logger.php
index 7d26b291..84a2f551 100644
--- a/vendor/monolog/monolog/src/Monolog/Logger.php
+++ b/vendor/monolog/monolog/src/Monolog/Logger.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY
+ * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY'
+ * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
*/
class Logger implements LoggerInterface, ResettableInterface
{
/**
* Detailed debug information
*/
- const DEBUG = 100;
+ public const DEBUG = 100;
/**
* Interesting events
*
* Examples: User logs in, SQL logs.
*/
- const INFO = 200;
+ public const INFO = 200;
/**
* Uncommon events
*/
- const NOTICE = 250;
+ public const NOTICE = 250;
/**
* Exceptional occurrences that are not errors
@@ -50,19 +56,19 @@ class Logger implements LoggerInterface, ResettableInterface
* Examples: Use of deprecated APIs, poor use of an API,
* undesirable things that are not necessarily wrong.
*/
- const WARNING = 300;
+ public const WARNING = 300;
/**
* Runtime errors
*/
- const ERROR = 400;
+ public const ERROR = 400;
/**
* Critical conditions
*
* Example: Application component unavailable, unexpected exception.
*/
- const CRITICAL = 500;
+ public const CRITICAL = 500;
/**
* Action must be taken immediately
@@ -70,12 +76,12 @@ class Logger implements LoggerInterface, ResettableInterface
* Example: Entire website down, database unavailable, etc.
* This should trigger the SMS alerts and wake you up.
*/
- const ALERT = 550;
+ public const ALERT = 550;
/**
* Urgent alert.
*/
- const EMERGENCY = 600;
+ public const EMERGENCY = 600;
/**
* Monolog API version
@@ -85,14 +91,16 @@ class Logger implements LoggerInterface, ResettableInterface
*
* @var int
*/
- const API = 1;
+ public const API = 2;
/**
- * Logging levels from syslog protocol defined in RFC 5424
+ * This is a static variable and not a constant to serve as an extension point for custom levels
+ *
+ * @var array $levels Logging levels with the levels as key
*
- * @var array $levels Logging levels
+ * @phpstan-var array $levels Logging levels with the levels as key
*/
- protected static $levels = array(
+ protected static $levels = [
self::DEBUG => 'DEBUG',
self::INFO => 'INFO',
self::NOTICE => 'NOTICE',
@@ -101,12 +109,23 @@ class Logger implements LoggerInterface, ResettableInterface
self::CRITICAL => 'CRITICAL',
self::ALERT => 'ALERT',
self::EMERGENCY => 'EMERGENCY',
- );
+ ];
/**
- * @var \DateTimeZone
+ * Mapping between levels numbers defined in RFC 5424 and Monolog ones
+ *
+ * @phpstan-var array $rfc_5424_levels
*/
- protected static $timezone;
+ private const RFC_5424_LEVELS = [
+ 7 => self::DEBUG,
+ 6 => self::INFO,
+ 5 => self::NOTICE,
+ 4 => self::WARNING,
+ 3 => self::ERROR,
+ 2 => self::CRITICAL,
+ 1 => self::ALERT,
+ 0 => self::EMERGENCY,
+ ];
/**
* @var string
@@ -135,36 +154,64 @@ class Logger implements LoggerInterface, ResettableInterface
protected $microsecondTimestamps = true;
/**
- * @var callable
+ * @var DateTimeZone
+ */
+ protected $timezone;
+
+ /**
+ * @var callable|null
*/
protected $exceptionHandler;
/**
- * @param string $name The logging channel
+ * @var int Keeps track of depth to prevent infinite logging loops
+ */
+ private $logDepth = 0;
+
+ /**
+ * @var \WeakMap<\Fiber, int>|null Keeps track of depth inside fibers to prevent infinite logging loops
+ */
+ private $fiberLogDepth;
+
+ /**
+ * @var bool Whether to detect infinite logging loops
+ *
+ * This can be disabled via {@see useLoggingLoopDetection} if you have async handlers that do not play well with this
+ */
+ private $detectCycles = true;
+
+ /**
+ * @psalm-param array $processors
+ *
+ * @param string $name The logging channel, a simple descriptive name that is attached to all log records
* @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
* @param callable[] $processors Optional array of processors
+ * @param DateTimeZone|null $timezone Optional timezone, if not provided date_default_timezone_get() will be used
*/
- public function __construct($name, array $handlers = array(), array $processors = array())
+ public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null)
{
$this->name = $name;
$this->setHandlers($handlers);
$this->processors = $processors;
+ $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
+
+ if (\PHP_VERSION_ID >= 80100) {
+ // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
+ /** @var \WeakMap<\Fiber, int> $fiberLogDepth */
+ $fiberLogDepth = new \WeakMap();
+ $this->fiberLogDepth = $fiberLogDepth;
+ }
}
- /**
- * @return string
- */
- public function getName()
+ public function getName(): string
{
return $this->name;
}
/**
* Return a new cloned instance with the name changed
- *
- * @return static
*/
- public function withName($name)
+ public function withName(string $name): self
{
$new = clone $this;
$new->name = $name;
@@ -174,11 +221,8 @@ public function withName($name)
/**
* Pushes a handler on to the stack.
- *
- * @param HandlerInterface $handler
- * @return $this
*/
- public function pushHandler(HandlerInterface $handler)
+ public function pushHandler(HandlerInterface $handler): self
{
array_unshift($this->handlers, $handler);
@@ -188,9 +232,9 @@ public function pushHandler(HandlerInterface $handler)
/**
* Pops a handler from the stack
*
- * @return HandlerInterface
+ * @throws \LogicException If empty handler stack
*/
- public function popHandler()
+ public function popHandler(): HandlerInterface
{
if (!$this->handlers) {
throw new \LogicException('You tried to pop from an empty handler stack.');
@@ -204,12 +248,11 @@ public function popHandler()
*
* If a map is passed, keys will be ignored.
*
- * @param HandlerInterface[] $handlers
- * @return $this
+ * @param HandlerInterface[] $handlers
*/
- public function setHandlers(array $handlers)
+ public function setHandlers(array $handlers): self
{
- $this->handlers = array();
+ $this->handlers = [];
foreach (array_reverse($handlers) as $handler) {
$this->pushHandler($handler);
}
@@ -220,22 +263,16 @@ public function setHandlers(array $handlers)
/**
* @return HandlerInterface[]
*/
- public function getHandlers()
+ public function getHandlers(): array
{
return $this->handlers;
}
/**
* Adds a processor on to the stack.
- *
- * @param callable $callback
- * @return $this
*/
- public function pushProcessor($callback)
+ public function pushProcessor(callable $callback): self
{
- if (!is_callable($callback)) {
- throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
- }
array_unshift($this->processors, $callback);
return $this;
@@ -244,9 +281,10 @@ public function pushProcessor($callback)
/**
* Removes the processor on top of the stack and returns it.
*
+ * @throws \LogicException If empty processor stack
* @return callable
*/
- public function popProcessor()
+ public function popProcessor(): callable
{
if (!$this->processors) {
throw new \LogicException('You tried to pop from an empty processor stack.');
@@ -258,7 +296,7 @@ public function popProcessor()
/**
* @return callable[]
*/
- public function getProcessors()
+ public function getProcessors(): array
{
return $this->processors;
}
@@ -267,91 +305,117 @@ public function getProcessors()
* Control the use of microsecond resolution timestamps in the 'datetime'
* member of new records.
*
- * Generating microsecond resolution timestamps by calling
- * microtime(true), formatting the result via sprintf() and then parsing
- * the resulting string via \DateTime::createFromFormat() can incur
- * a measurable runtime overhead vs simple usage of DateTime to capture
- * a second resolution timestamp in systems which generate a large number
- * of log events.
+ * As of PHP7.1 microseconds are always included by the engine, so
+ * there is no performance penalty and Monolog 2 enabled microseconds
+ * by default. This function lets you disable them though in case you want
+ * to suppress microseconds from the output.
*
* @param bool $micro True to use microtime() to create timestamps
*/
- public function useMicrosecondTimestamps($micro)
+ public function useMicrosecondTimestamps(bool $micro): self
{
- $this->microsecondTimestamps = (bool) $micro;
+ $this->microsecondTimestamps = $micro;
+
+ return $this;
+ }
+
+ public function useLoggingLoopDetection(bool $detectCycles): self
+ {
+ $this->detectCycles = $detectCycles;
+
+ return $this;
}
/**
* Adds a log record.
*
- * @param int $level The logging level
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param int $level The logging level (a Monolog or RFC 5424 level)
+ * @param string $message The log message
+ * @param mixed[] $context The log context
+ * @param DateTimeImmutable $datetime Optional log date to log into the past or future
+ * @return bool Whether the record has been processed
+ *
+ * @phpstan-param Level $level
*/
- public function addRecord($level, $message, array $context = array())
+ public function addRecord(int $level, string $message, array $context = [], DateTimeImmutable $datetime = null): bool
{
- if (!$this->handlers) {
- $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
+ if (isset(self::RFC_5424_LEVELS[$level])) {
+ $level = self::RFC_5424_LEVELS[$level];
}
- $levelName = static::getLevelName($level);
-
- // check if any handler will handle this message so we can return early and save cycles
- $handlerKey = null;
- reset($this->handlers);
- while ($handler = current($this->handlers)) {
- if ($handler->isHandling(array('level' => $level))) {
- $handlerKey = key($this->handlers);
- break;
+ if ($this->detectCycles) {
+ if (\PHP_VERSION_ID >= 80100 && $fiber = \Fiber::getCurrent()) {
+ $this->fiberLogDepth[$fiber] = $this->fiberLogDepth[$fiber] ?? 0;
+ $logDepth = ++$this->fiberLogDepth[$fiber];
+ } else {
+ $logDepth = ++$this->logDepth;
}
-
- next($this->handlers);
+ } else {
+ $logDepth = 0;
}
- if (null === $handlerKey) {
+ if ($logDepth === 3) {
+ $this->warning('A possible infinite logging loop was detected and aborted. It appears some of your handler code is triggering logging, see the previous log record for a hint as to what may be the cause.');
+ return false;
+ } elseif ($logDepth >= 5) { // log depth 4 is let through, so we can log the warning above
return false;
}
- if (!static::$timezone) {
- static::$timezone = new \DateTimeZone(date_default_timezone_get() ?: 'UTC');
- }
-
- // php7.1+ always has microseconds enabled, so we do not need this hack
- if ($this->microsecondTimestamps && PHP_VERSION_ID < 70100) {
- $ts = \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone);
- } else {
- $ts = new \DateTime('now', static::$timezone);
- }
- $ts->setTimezone(static::$timezone);
+ try {
+ $record = null;
+
+ foreach ($this->handlers as $handler) {
+ if (null === $record) {
+ // skip creating the record as long as no handler is going to handle it
+ if (!$handler->isHandling(['level' => $level])) {
+ continue;
+ }
+
+ $levelName = static::getLevelName($level);
+
+ $record = [
+ 'message' => $message,
+ 'context' => $context,
+ 'level' => $level,
+ 'level_name' => $levelName,
+ 'channel' => $this->name,
+ 'datetime' => $datetime ?? new DateTimeImmutable($this->microsecondTimestamps, $this->timezone),
+ 'extra' => [],
+ ];
+
+ try {
+ foreach ($this->processors as $processor) {
+ $record = $processor($record);
+ }
+ } catch (Throwable $e) {
+ $this->handleException($e, $record);
+
+ return true;
+ }
+ }
- $record = array(
- 'message' => (string) $message,
- 'context' => $context,
- 'level' => $level,
- 'level_name' => $levelName,
- 'channel' => $this->name,
- 'datetime' => $ts,
- 'extra' => array(),
- );
+ // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted
+ try {
+ if (true === $handler->handle($record)) {
+ break;
+ }
+ } catch (Throwable $e) {
+ $this->handleException($e, $record);
- try {
- foreach ($this->processors as $processor) {
- $record = call_user_func($processor, $record);
+ return true;
+ }
}
-
- while ($handler = current($this->handlers)) {
- if (true === $handler->handle($record)) {
- break;
+ } finally {
+ if ($this->detectCycles) {
+ if (isset($fiber)) {
+ $this->fiberLogDepth[$fiber]--;
+ } else {
+ $this->logDepth--;
}
-
- next($this->handlers);
}
- } catch (Exception $e) {
- $this->handleException($e, $record);
}
- return true;
+ return null !== $record;
}
/**
@@ -364,12 +428,10 @@ public function addRecord($level, $message, array $context = array())
* This is useful at the end of a request and will be called automatically on every handler
* when they get destructed.
*/
- public function close()
+ public function close(): void
{
foreach ($this->handlers as $handler) {
- if (method_exists($handler, 'close')) {
- $handler->close();
- }
+ $handler->close();
}
}
@@ -383,7 +445,7 @@ public function close()
* have a long running process like a worker or an application server serving multiple requests
* in one process.
*/
- public function reset()
+ public function reset(): void
{
foreach ($this->handlers as $handler) {
if ($handler instanceof ResettableInterface) {
@@ -398,108 +460,13 @@ public function reset()
}
}
- /**
- * Adds a log record at the DEBUG level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addDebug($message, array $context = array())
- {
- return $this->addRecord(static::DEBUG, $message, $context);
- }
-
- /**
- * Adds a log record at the INFO level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addInfo($message, array $context = array())
- {
- return $this->addRecord(static::INFO, $message, $context);
- }
-
- /**
- * Adds a log record at the NOTICE level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addNotice($message, array $context = array())
- {
- return $this->addRecord(static::NOTICE, $message, $context);
- }
-
- /**
- * Adds a log record at the WARNING level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addWarning($message, array $context = array())
- {
- return $this->addRecord(static::WARNING, $message, $context);
- }
-
- /**
- * Adds a log record at the ERROR level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addError($message, array $context = array())
- {
- return $this->addRecord(static::ERROR, $message, $context);
- }
-
- /**
- * Adds a log record at the CRITICAL level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addCritical($message, array $context = array())
- {
- return $this->addRecord(static::CRITICAL, $message, $context);
- }
-
- /**
- * Adds a log record at the ALERT level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addAlert($message, array $context = array())
- {
- return $this->addRecord(static::ALERT, $message, $context);
- }
-
- /**
- * Adds a log record at the EMERGENCY level.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
- */
- public function addEmergency($message, array $context = array())
- {
- return $this->addRecord(static::EMERGENCY, $message, $context);
- }
-
/**
* Gets all supported logging levels.
*
- * @return array Assoc array with human-readable level names => level codes.
+ * @return array Assoc array with human-readable level names => level codes.
+ * @phpstan-return array
*/
- public static function getLevels()
+ public static function getLevels(): array
{
return array_flip(static::$levels);
}
@@ -507,10 +474,12 @@ public static function getLevels()
/**
* Gets the name of the logging level.
*
- * @param int $level
- * @return string
+ * @throws \Psr\Log\InvalidArgumentException If level is not defined
+ *
+ * @phpstan-param Level $level
+ * @phpstan-return LevelName
*/
- public static function getLevelName($level)
+ public static function getLevelName(int $level): string
{
if (!isset(static::$levels[$level])) {
throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
@@ -522,18 +491,32 @@ public static function getLevelName($level)
/**
* Converts PSR-3 levels to Monolog ones if necessary
*
- * @param string|int $level Level number (monolog) or name (PSR-3)
- * @return int
+ * @param string|int $level Level number (monolog) or name (PSR-3)
+ * @throws \Psr\Log\InvalidArgumentException If level is not defined
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ * @phpstan-return Level
*/
- public static function toMonologLevel($level)
+ public static function toMonologLevel($level): int
{
if (is_string($level)) {
+ if (is_numeric($level)) {
+ /** @phpstan-ignore-next-line */
+ return intval($level);
+ }
+
// Contains chars of all log levels and avoids using strtoupper() which may have
- // strange results depending on locale (for example, "i" will become "İ")
+ // strange results depending on locale (for example, "i" will become "İ" in Turkish locale)
$upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
if (defined(__CLASS__.'::'.$upper)) {
return constant(__CLASS__ . '::' . $upper);
}
+
+ throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels));
+ }
+
+ if (!is_int($level)) {
+ throw new InvalidArgumentException('Level "'.var_export($level, true).'" is not defined, use one of: '.implode(', ', array_keys(static::$levels) + static::$levels));
}
return $level;
@@ -542,14 +525,13 @@ public static function toMonologLevel($level)
/**
* Checks whether the Logger has a handler that listens on the given level
*
- * @param int $level
- * @return bool
+ * @phpstan-param Level $level
*/
- public function isHandling($level)
+ public function isHandling(int $level): bool
{
- $record = array(
+ $record = [
'level' => $level,
- );
+ ];
foreach ($this->handlers as $handler) {
if ($handler->isHandling($record)) {
@@ -561,57 +543,46 @@ public function isHandling($level)
}
/**
- * Set a custom exception handler
+ * Set a custom exception handler that will be called if adding a new record fails
*
- * @param callable $callback
- * @return $this
+ * The callable will receive an exception object and the record that failed to be logged
*/
- public function setExceptionHandler($callback)
+ public function setExceptionHandler(?callable $callback): self
{
- if (!is_callable($callback)) {
- throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callback, true).' given');
- }
$this->exceptionHandler = $callback;
return $this;
}
- /**
- * @return callable
- */
- public function getExceptionHandler()
+ public function getExceptionHandler(): ?callable
{
return $this->exceptionHandler;
}
- /**
- * Delegates exception management to the custom exception handler,
- * or throws the exception if no custom handler is set.
- */
- protected function handleException(Exception $e, array $record)
- {
- if (!$this->exceptionHandler) {
- throw $e;
- }
-
- call_user_func($this->exceptionHandler, $e, $record);
- }
-
/**
* Adds a log record at an arbitrary level.
*
* This method allows for compatibility with common interfaces.
*
- * @param mixed $level The log level
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param mixed $level The log level (a Monolog, PSR-3 or RFC 5424 level)
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
*/
- public function log($level, $message, array $context = array())
+ public function log($level, $message, array $context = []): void
{
+ if (!is_int($level) && !is_string($level)) {
+ throw new \InvalidArgumentException('$level is expected to be a string or int');
+ }
+
+ if (isset(self::RFC_5424_LEVELS[$level])) {
+ $level = self::RFC_5424_LEVELS[$level];
+ }
+
$level = static::toMonologLevel($level);
- return $this->addRecord($level, $message, $context);
+ $this->addRecord($level, (string) $message, $context);
}
/**
@@ -619,13 +590,12 @@ public function log($level, $message, array $context = array())
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function debug($message, array $context = array())
+ public function debug($message, array $context = []): void
{
- return $this->addRecord(static::DEBUG, $message, $context);
+ $this->addRecord(static::DEBUG, (string) $message, $context);
}
/**
@@ -633,13 +603,12 @@ public function debug($message, array $context = array())
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function info($message, array $context = array())
+ public function info($message, array $context = []): void
{
- return $this->addRecord(static::INFO, $message, $context);
+ $this->addRecord(static::INFO, (string) $message, $context);
}
/**
@@ -647,13 +616,12 @@ public function info($message, array $context = array())
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function notice($message, array $context = array())
+ public function notice($message, array $context = []): void
{
- return $this->addRecord(static::NOTICE, $message, $context);
+ $this->addRecord(static::NOTICE, (string) $message, $context);
}
/**
@@ -661,136 +629,133 @@ public function notice($message, array $context = array())
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function warn($message, array $context = array())
+ public function warning($message, array $context = []): void
{
- return $this->addRecord(static::WARNING, $message, $context);
+ $this->addRecord(static::WARNING, (string) $message, $context);
}
/**
- * Adds a log record at the WARNING level.
+ * Adds a log record at the ERROR level.
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function warning($message, array $context = array())
+ public function error($message, array $context = []): void
{
- return $this->addRecord(static::WARNING, $message, $context);
+ $this->addRecord(static::ERROR, (string) $message, $context);
}
/**
- * Adds a log record at the ERROR level.
+ * Adds a log record at the CRITICAL level.
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function err($message, array $context = array())
+ public function critical($message, array $context = []): void
{
- return $this->addRecord(static::ERROR, $message, $context);
+ $this->addRecord(static::CRITICAL, (string) $message, $context);
}
/**
- * Adds a log record at the ERROR level.
+ * Adds a log record at the ALERT level.
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function error($message, array $context = array())
+ public function alert($message, array $context = []): void
{
- return $this->addRecord(static::ERROR, $message, $context);
+ $this->addRecord(static::ALERT, (string) $message, $context);
}
/**
- * Adds a log record at the CRITICAL level.
+ * Adds a log record at the EMERGENCY level.
*
* This method allows for compatibility with common interfaces.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param string|Stringable $message The log message
+ * @param mixed[] $context The log context
*/
- public function crit($message, array $context = array())
+ public function emergency($message, array $context = []): void
{
- return $this->addRecord(static::CRITICAL, $message, $context);
+ $this->addRecord(static::EMERGENCY, (string) $message, $context);
}
/**
- * Adds a log record at the CRITICAL level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * Sets the timezone to be used for the timestamp of log records.
*/
- public function critical($message, array $context = array())
+ public function setTimezone(DateTimeZone $tz): self
{
- return $this->addRecord(static::CRITICAL, $message, $context);
+ $this->timezone = $tz;
+
+ return $this;
}
/**
- * Adds a log record at the ALERT level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * Returns the timezone to be used for the timestamp of log records.
*/
- public function alert($message, array $context = array())
+ public function getTimezone(): DateTimeZone
{
- return $this->addRecord(static::ALERT, $message, $context);
+ return $this->timezone;
}
/**
- * Adds a log record at the EMERGENCY level.
- *
- * This method allows for compatibility with common interfaces.
+ * Delegates exception management to the custom exception handler,
+ * or throws the exception if no custom handler is set.
*
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @param array $record
+ * @phpstan-param Record $record
*/
- public function emerg($message, array $context = array())
+ protected function handleException(Throwable $e, array $record): void
{
- return $this->addRecord(static::EMERGENCY, $message, $context);
+ if (!$this->exceptionHandler) {
+ throw $e;
+ }
+
+ ($this->exceptionHandler)($e, $record);
}
/**
- * Adds a log record at the EMERGENCY level.
- *
- * This method allows for compatibility with common interfaces.
- *
- * @param string $message The log message
- * @param array $context The log context
- * @return bool Whether the record has been processed
+ * @return array
*/
- public function emergency($message, array $context = array())
+ public function __serialize(): array
{
- return $this->addRecord(static::EMERGENCY, $message, $context);
+ return [
+ 'name' => $this->name,
+ 'handlers' => $this->handlers,
+ 'processors' => $this->processors,
+ 'microsecondTimestamps' => $this->microsecondTimestamps,
+ 'timezone' => $this->timezone,
+ 'exceptionHandler' => $this->exceptionHandler,
+ 'logDepth' => $this->logDepth,
+ 'detectCycles' => $this->detectCycles,
+ ];
}
/**
- * Set the timezone to be used for the timestamp of log records.
- *
- * This is stored globally for all Logger instances
- *
- * @param \DateTimeZone $tz Timezone object
+ * @param array $data
*/
- public static function setTimezone(\DateTimeZone $tz)
+ public function __unserialize(array $data): void
{
- self::$timezone = $tz;
+ foreach (['name', 'handlers', 'processors', 'microsecondTimestamps', 'timezone', 'exceptionHandler', 'logDepth', 'detectCycles'] as $property) {
+ if (isset($data[$property])) {
+ $this->$property = $data[$property];
+ }
+ }
+
+ if (\PHP_VERSION_ID >= 80100) {
+ // Local variable for phpstan, see https://github.com/phpstan/phpstan/issues/6732#issuecomment-1111118412
+ /** @var \WeakMap<\Fiber, int> $fiberLogDepth */
+ $fiberLogDepth = new \WeakMap();
+ $this->fiberLogDepth = $fiberLogDepth;
+ }
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php
index cdf5ec73..8166bdca 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class GitProcessor implements ProcessorInterface
{
+ /** @var int */
private $level;
- private static $cache;
+ /** @var array{branch: string, commit: string}|array|null */
+ private static $cache = null;
+ /**
+ * @param string|int $level The minimum logging level at which this Processor will be triggered
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
public function __construct($level = Logger::DEBUG)
{
$this->level = Logger::toMonologLevel($level);
}
/**
- * @param array $record
- * @return array
+ * {@inheritDoc}
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
@@ -45,7 +55,10 @@ public function __invoke(array $record)
return $record;
}
- private static function getGitInfo()
+ /**
+ * @return array{branch: string, commit: string}|array
+ */
+ private static function getGitInfo(): array
{
if (self::$cache) {
return self::$cache;
@@ -53,12 +66,12 @@ private static function getGitInfo()
$branches = `git branch -v --no-abbrev`;
if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
- return self::$cache = array(
+ return self::$cache = [
'branch' => $matches[1],
'commit' => $matches[2],
- );
+ ];
}
- return self::$cache = array();
+ return self::$cache = [];
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php
new file mode 100644
index 00000000..91fda7d6
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.php
@@ -0,0 +1,36 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Processor;
+
+/**
+ * Injects value of gethostname in all records
+ */
+class HostnameProcessor implements ProcessorInterface
+{
+ /** @var string */
+ private static $host;
+
+ public function __construct()
+ {
+ self::$host = (string) gethostname();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public function __invoke(array $record): array
+ {
+ $record['extra']['hostname'] = self::$host;
+
+ return $record;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php
index 6ae192a2..a32e76b2 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class IntrospectionProcessor implements ProcessorInterface
{
+ /** @var int */
private $level;
-
+ /** @var string[] */
private $skipClassesPartials;
-
+ /** @var int */
private $skipStackFramesCount;
-
- private $skipFunctions = array(
+ /** @var string[] */
+ private $skipFunctions = [
'call_user_func',
'call_user_func_array',
- );
+ ];
- public function __construct($level = Logger::DEBUG, array $skipClassesPartials = array(), $skipStackFramesCount = 0)
+ /**
+ * @param string|int $level The minimum logging level at which this Processor will be triggered
+ * @param string[] $skipClassesPartials
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
{
$this->level = Logger::toMonologLevel($level);
- $this->skipClassesPartials = array_merge(array('Monolog\\'), $skipClassesPartials);
+ $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials);
$this->skipStackFramesCount = $skipStackFramesCount;
}
/**
- * @param array $record
- * @return array
+ * {@inheritDoc}
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
return $record;
}
- /*
- * http://php.net/manual/en/function.debug-backtrace.php
- * As of 5.3.6, DEBUG_BACKTRACE_IGNORE_ARGS option was added.
- * Any version less than 5.3.6 must use the DEBUG_BACKTRACE_IGNORE_ARGS constant value '2'.
- */
- $trace = debug_backtrace((PHP_VERSION_ID < 50306) ? 2 : DEBUG_BACKTRACE_IGNORE_ARGS);
+ $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
// skip first since it's always the current method
array_shift($trace);
@@ -74,11 +79,13 @@ public function __invoke(array $record)
foreach ($this->skipClassesPartials as $part) {
if (strpos($trace[$i]['class'], $part) !== false) {
$i++;
+
continue 2;
}
}
} elseif (in_array($trace[$i]['function'], $this->skipFunctions)) {
$i++;
+
continue;
}
@@ -90,18 +97,22 @@ public function __invoke(array $record)
// we should have the call source now
$record['extra'] = array_merge(
$record['extra'],
- array(
+ [
'file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null,
'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null,
'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null,
+ 'callType' => isset($trace[$i]['type']) ? $trace[$i]['type'] : null,
'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null,
- )
+ ]
);
return $record;
}
- private function isTraceClassOrSkippedFunction(array $trace, $index)
+ /**
+ * @param array[] $trace
+ */
+ private function isTraceClassOrSkippedFunction(array $trace, int $index): bool
{
if (!isset($trace[$index])) {
return false;
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php
index 0543e929..37c756fc 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php
@@ -1,4 +1,4 @@
-realUsage);
- $formatted = $this->formatBytes($bytes);
+ $usage = memory_get_peak_usage($this->realUsage);
- $record['extra']['memory_peak_usage'] = $formatted;
+ if ($this->useFormatting) {
+ $usage = $this->formatBytes($usage);
+ }
+
+ $record['extra']['memory_peak_usage'] = $usage;
return $record;
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php
index 2a379a30..227deb7c 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php
@@ -1,4 +1,4 @@
-realUsage = (bool) $realUsage;
- $this->useFormatting = (bool) $useFormatting;
+ $this->realUsage = $realUsage;
+ $this->useFormatting = $useFormatting;
}
/**
* Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is
*
* @param int $bytes
- * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as is
+ * @return string|int Formatted string if $this->useFormatting is true, otherwise return $bytes as int
*/
- protected function formatBytes($bytes)
+ protected function formatBytes(int $bytes)
{
- $bytes = (int) $bytes;
-
if (!$this->useFormatting) {
return $bytes;
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php
index 2783d656..e141921e 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php
@@ -1,4 +1,4 @@
-realUsage);
- $formatted = $this->formatBytes($bytes);
+ $usage = memory_get_usage($this->realUsage);
- $record['extra']['memory_usage'] = $formatted;
+ if ($this->useFormatting) {
+ $usage = $this->formatBytes($usage);
+ }
+
+ $record['extra']['memory_usage'] = $usage;
return $record;
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php
index 2f5b3265..d4a628f5 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php
@@ -1,9 +1,9 @@
-
+ * (c) Jordi Boggiano
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
@@ -12,27 +12,37 @@
namespace Monolog\Processor;
use Monolog\Logger;
+use Psr\Log\LogLevel;
/**
* Injects Hg branch and Hg revision number in all records
*
* @author Jonathan A. Schweder
+ *
+ * @phpstan-import-type LevelName from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
*/
class MercurialProcessor implements ProcessorInterface
{
+ /** @var Level */
private $level;
- private static $cache;
+ /** @var array{branch: string, revision: string}|array|null */
+ private static $cache = null;
+ /**
+ * @param int|string $level The minimum logging level at which this Processor will be triggered
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
public function __construct($level = Logger::DEBUG)
{
$this->level = Logger::toMonologLevel($level);
}
/**
- * @param array $record
- * @return array
+ * {@inheritDoc}
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// return if the level is not high enough
if ($record['level'] < $this->level) {
@@ -44,20 +54,24 @@ public function __invoke(array $record)
return $record;
}
- private static function getMercurialInfo()
+ /**
+ * @return array{branch: string, revision: string}|array
+ */
+ private static function getMercurialInfo(): array
{
if (self::$cache) {
return self::$cache;
}
$result = explode(' ', trim(`hg id -nb`));
+
if (count($result) >= 3) {
- return self::$cache = array(
+ return self::$cache = [
'branch' => $result[1],
'revision' => $result[2],
- );
+ ];
}
- return self::$cache = array();
+ return self::$cache = [];
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php
index 66b80fbb..3b939a95 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
*/
interface ProcessorInterface
{
/**
- * @return array The processed records
+ * @return array The processed record
+ *
+ * @phpstan-param Record $record
+ * @phpstan-return Record
*/
- public function __invoke(array $records);
+ public function __invoke(array $record);
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
index a318af7e..e7c12176 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php
@@ -1,4 +1,4 @@
-dateFormat = $dateFormat;
$this->removeUsedContextFields = $removeUsedContextFields;
}
/**
- * @param array $record
- * @return array
+ * {@inheritDoc}
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
if (false === strpos($record['message'], '{')) {
return $record;
}
- $replacements = array();
+ $replacements = [];
foreach ($record['context'] as $key => $val) {
$placeholder = '{' . $key . '}';
if (strpos($record['message'], $placeholder) === false) {
@@ -59,8 +58,16 @@ public function __invoke(array $record)
if (is_null($val) || is_scalar($val) || (is_object($val) && method_exists($val, "__toString"))) {
$replacements[$placeholder] = $val;
- } elseif ($val instanceof \DateTime) {
- $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
+ } elseif ($val instanceof \DateTimeInterface) {
+ if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
+ // handle monolog dates using __toString if no specific dateFormat was asked for
+ // so that it follows the useMicroseconds flag
+ $replacements[$placeholder] = (string) $val;
+ } else {
+ $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
+ }
+ } elseif ($val instanceof \UnitEnum) {
+ $replacements[$placeholder] = $val instanceof \BackedEnum ? $val->value : $val->name;
} elseif (is_object($val)) {
$replacements[$placeholder] = '[object '.Utils::getClass($val).']';
} elseif (is_array($val)) {
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php
index 615a4d99..80f18747 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php
@@ -1,4 +1,4 @@
-setTags($tags);
}
- public function addTags(array $tags = array())
+ /**
+ * @param string[] $tags
+ */
+ public function addTags(array $tags = []): self
{
$this->tags = array_merge($this->tags, $tags);
+
+ return $this;
}
- public function setTags(array $tags = array())
+ /**
+ * @param string[] $tags
+ */
+ public function setTags(array $tags = []): self
{
$this->tags = $tags;
+
+ return $this;
}
- public function __invoke(array $record)
+ /**
+ * {@inheritDoc}
+ */
+ public function __invoke(array $record): array
{
$record['extra']['tags'] = $this->tags;
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php
index d1f708cf..a27b74db 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.php
@@ -1,4 +1,4 @@
- 32 || $length < 1) {
+ if ($length > 32 || $length < 1) {
throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
}
-
$this->uid = $this->generateUid($length);
}
- public function __invoke(array $record)
+ /**
+ * {@inheritDoc}
+ */
+ public function __invoke(array $record): array
{
$record['extra']['uid'] = $this->uid;
return $record;
}
- /**
- * @return string
- */
- public function getUid()
+ public function getUid(): string
{
return $this->uid;
}
@@ -52,8 +52,8 @@ public function reset()
$this->uid = $this->generateUid(strlen($this->uid));
}
- private function generateUid($length)
+ private function generateUid(int $length): string
{
- return substr(hash('md5', uniqid('', true)), 0, $length);
+ return substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length);
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
index 2e8dfae1..51850e17 100644
--- a/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
+++ b/vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.php
@@ -1,4 +1,4 @@
-|\ArrayAccess
*/
protected $serverData;
@@ -28,19 +28,20 @@ class WebProcessor implements ProcessorInterface
*
* Array is structured as [key in record.extra => key in $serverData]
*
- * @var array
+ * @var array
*/
- protected $extraFields = array(
+ protected $extraFields = [
'url' => 'REQUEST_URI',
'ip' => 'REMOTE_ADDR',
'http_method' => 'REQUEST_METHOD',
'server' => 'SERVER_NAME',
'referrer' => 'HTTP_REFERER',
- );
+ 'user_agent' => 'HTTP_USER_AGENT',
+ ];
/**
- * @param array|\ArrayAccess $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
- * @param array|null $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer
+ * @param array|\ArrayAccess|null $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
+ * @param array|array|null $extraFields Field names and the related key inside $serverData to be added (or just a list of field names to use the default configured $serverData mapping). If not provided it defaults to: [url, ip, http_method, server, referrer] + unique_id if present in server data
*/
public function __construct($serverData = null, array $extraFields = null)
{
@@ -52,28 +53,30 @@ public function __construct($serverData = null, array $extraFields = null)
throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
}
+ $defaultEnabled = ['url', 'ip', 'http_method', 'server', 'referrer'];
if (isset($this->serverData['UNIQUE_ID'])) {
$this->extraFields['unique_id'] = 'UNIQUE_ID';
+ $defaultEnabled[] = 'unique_id';
}
- if (null !== $extraFields) {
- if (isset($extraFields[0])) {
- foreach (array_keys($this->extraFields) as $fieldName) {
- if (!in_array($fieldName, $extraFields)) {
- unset($this->extraFields[$fieldName]);
- }
+ if (null === $extraFields) {
+ $extraFields = $defaultEnabled;
+ }
+ if (isset($extraFields[0])) {
+ foreach (array_keys($this->extraFields) as $fieldName) {
+ if (!in_array($fieldName, $extraFields)) {
+ unset($this->extraFields[$fieldName]);
}
- } else {
- $this->extraFields = $extraFields;
}
+ } else {
+ $this->extraFields = $extraFields;
}
}
/**
- * @param array $record
- * @return array
+ * {@inheritDoc}
*/
- public function __invoke(array $record)
+ public function __invoke(array $record): array
{
// skip processing if for some reason request data
// is not present (CLI or wonky SAPIs)
@@ -86,12 +89,7 @@ public function __invoke(array $record)
return $record;
}
- /**
- * @param string $extraName
- * @param string $serverName
- * @return $this
- */
- public function addExtraField($extraName, $serverName)
+ public function addExtraField(string $extraName, string $serverName): self
{
$this->extraFields[$extraName] = $serverName;
@@ -99,13 +97,13 @@ public function addExtraField($extraName, $serverName)
}
/**
- * @param array $extra
- * @return array
+ * @param mixed[] $extra
+ * @return mixed[]
*/
- private function appendExtraFields(array $extra)
+ private function appendExtraFields(array $extra): array
{
foreach ($this->extraFields as $extraName => $serverName) {
- $extra[$extraName] = isset($this->serverData[$serverName]) ? $this->serverData[$serverName] : null;
+ $extra[$extraName] = $this->serverData[$serverName] ?? null;
}
return $extra;
diff --git a/vendor/monolog/monolog/src/Monolog/Registry.php b/vendor/monolog/monolog/src/Monolog/Registry.php
index 159b751c..ae94ae6c 100644
--- a/vendor/monolog/monolog/src/Monolog/Registry.php
+++ b/vendor/monolog/monolog/src/Monolog/Registry.php
@@ -1,4 +1,4 @@
-addError('Sent to $api Logger instance');
- * Monolog\Registry::application()->addError('Sent to $application Logger instance');
+ * Monolog\Registry::api()->error('Sent to $api Logger instance');
+ * Monolog\Registry::application()->error('Sent to $application Logger instance');
* }
*
*
@@ -42,7 +42,7 @@ class Registry
*
* @var Logger[]
*/
- private static $loggers = array();
+ private static $loggers = [];
/**
* Adds new logging channel to the registry
@@ -51,8 +51,9 @@ class Registry
* @param string|null $name Name of the logging channel ($logger->getName() by default)
* @param bool $overwrite Overwrite instance in the registry if the given name already exists?
* @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
+ * @return void
*/
- public static function addLogger(Logger $logger, $name = null, $overwrite = false)
+ public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false)
{
$name = $name ?: $logger->getName();
@@ -68,15 +69,15 @@ public static function addLogger(Logger $logger, $name = null, $overwrite = fals
*
* @param string|Logger $logger Name or logger instance
*/
- public static function hasLogger($logger)
+ public static function hasLogger($logger): bool
{
if ($logger instanceof Logger) {
$index = array_search($logger, self::$loggers, true);
return false !== $index;
- } else {
- return isset(self::$loggers[$logger]);
}
+
+ return isset(self::$loggers[$logger]);
}
/**
@@ -84,7 +85,7 @@ public static function hasLogger($logger)
*
* @param string|Logger $logger Name or logger instance
*/
- public static function removeLogger($logger)
+ public static function removeLogger($logger): void
{
if ($logger instanceof Logger) {
if (false !== ($idx = array_search($logger, self::$loggers, true))) {
@@ -98,9 +99,9 @@ public static function removeLogger($logger)
/**
* Clears the registry
*/
- public static function clear()
+ public static function clear(): void
{
- self::$loggers = array();
+ self::$loggers = [];
}
/**
@@ -108,9 +109,8 @@ public static function clear()
*
* @param string $name Name of the requested Logger instance
* @throws \InvalidArgumentException If named Logger instance is not in the registry
- * @return Logger Requested instance of Logger
*/
- public static function getInstance($name)
+ public static function getInstance($name): Logger
{
if (!isset(self::$loggers[$name])) {
throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
@@ -123,7 +123,7 @@ public static function getInstance($name)
* Gets Logger instance from the registry via static method call
*
* @param string $name Name of the requested Logger instance
- * @param array $arguments Arguments passed to static method call
+ * @param mixed[] $arguments Arguments passed to static method call
* @throws \InvalidArgumentException If named Logger instance is not in the registry
* @return Logger Requested instance of Logger
*/
diff --git a/vendor/monolog/monolog/src/Monolog/ResettableInterface.php b/vendor/monolog/monolog/src/Monolog/ResettableInterface.php
index 635bc77d..2c5fd785 100644
--- a/vendor/monolog/monolog/src/Monolog/ResettableInterface.php
+++ b/vendor/monolog/monolog/src/Monolog/ResettableInterface.php
@@ -1,4 +1,4 @@
-
+ *
+ * @phpstan-import-type Level from \Monolog\Logger
+ * @phpstan-import-type LevelName from \Monolog\Logger
*/
class SignalHandler
{
+ /** @var LoggerInterface */
private $logger;
- private $previousSignalHandler = array();
- private $signalLevelMap = array();
- private $signalRestartSyscalls = array();
+ /** @var array SIG_DFL, SIG_IGN or previous callable */
+ private $previousSignalHandler = [];
+ /** @var array */
+ private $signalLevelMap = [];
+ /** @var array */
+ private $signalRestartSyscalls = [];
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
- public function registerSignalHandler($signo, $level = LogLevel::CRITICAL, $callPrevious = true, $restartSyscalls = true, $async = true)
+ /**
+ * @param int|string $level Level or level name
+ * @param bool $callPrevious
+ * @param bool $restartSyscalls
+ * @param bool|null $async
+ * @return $this
+ *
+ * @phpstan-param Level|LevelName|LogLevel::* $level
+ */
+ public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true): self
{
if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
return $this;
}
+ $level = Logger::toMonologLevel($level);
+
if ($callPrevious) {
- if (function_exists('pcntl_signal_get_handler')) {
- $handler = pcntl_signal_get_handler($signo);
- if ($handler === false) {
- return $this;
- }
- $this->previousSignalHandler[$signo] = $handler;
- } else {
- $this->previousSignalHandler[$signo] = true;
- }
+ $handler = pcntl_signal_get_handler($signo);
+ $this->previousSignalHandler[$signo] = $handler;
} else {
unset($this->previousSignalHandler[$signo]);
}
$this->signalLevelMap[$signo] = $level;
$this->signalRestartSyscalls[$signo] = $restartSyscalls;
- if (function_exists('pcntl_async_signals') && $async !== null) {
+ if ($async !== null) {
pcntl_async_signals($async);
}
- pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
+ pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
return $this;
}
- public function handleSignal($signo, array $siginfo = null)
+ /**
+ * @param mixed $siginfo
+ */
+ public function handleSignal(int $signo, $siginfo = null): void
{
- static $signals = array();
+ static $signals = [];
if (!$signals && extension_loaded('pcntl')) {
$pcntl = new ReflectionExtension('pcntl');
- $constants = $pcntl->getConstants();
- if (!$constants) {
- // HHVM 3.24.2 returns an empty array.
- $constants = get_defined_constants(true);
- $constants = $constants['Core'];
- }
- foreach ($constants as $name => $value) {
+ // HHVM 3.24.2 returns an empty array.
+ foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) {
if (substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
$signals[$value] = $name;
}
}
- unset($constants);
}
- $level = isset($this->signalLevelMap[$signo]) ? $this->signalLevelMap[$signo] : LogLevel::CRITICAL;
- $signal = isset($signals[$signo]) ? $signals[$signo] : $signo;
- $context = isset($siginfo) ? $siginfo : array();
+ $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL;
+ $signal = $signals[$signo] ?? $signo;
+ $context = $siginfo ?? [];
$this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
if (!isset($this->previousSignalHandler[$signo])) {
return;
}
- if ($this->previousSignalHandler[$signo] === true || $this->previousSignalHandler[$signo] === SIG_DFL) {
+ if ($this->previousSignalHandler[$signo] === SIG_DFL) {
if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch')
- && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
- $restartSyscalls = isset($this->signalRestartSyscalls[$signo]) ? $this->signalRestartSyscalls[$signo] : true;
- pcntl_signal($signo, SIG_DFL, $restartSyscalls);
- pcntl_sigprocmask(SIG_UNBLOCK, array($signo), $oldset);
- posix_kill(posix_getpid(), $signo);
- pcntl_signal_dispatch();
- pcntl_sigprocmask(SIG_SETMASK, $oldset);
- pcntl_signal($signo, array($this, 'handleSignal'), $restartSyscalls);
- }
- } elseif (is_callable($this->previousSignalHandler[$signo])) {
- if (PHP_VERSION_ID >= 70100) {
- $this->previousSignalHandler[$signo]($signo, $siginfo);
- } else {
- $this->previousSignalHandler[$signo]($signo);
+ && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')
+ ) {
+ $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? true;
+ pcntl_signal($signo, SIG_DFL, $restartSyscalls);
+ pcntl_sigprocmask(SIG_UNBLOCK, [$signo], $oldset);
+ posix_kill(posix_getpid(), $signo);
+ pcntl_signal_dispatch();
+ pcntl_sigprocmask(SIG_SETMASK, $oldset);
+ pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
}
+ } elseif (is_callable($this->previousSignalHandler[$signo])) {
+ $this->previousSignalHandler[$signo]($signo, $siginfo);
}
}
}
diff --git a/vendor/monolog/monolog/src/Monolog/Test/TestCase.php b/vendor/monolog/monolog/src/Monolog/Test/TestCase.php
new file mode 100644
index 00000000..bc0b425e
--- /dev/null
+++ b/vendor/monolog/monolog/src/Monolog/Test/TestCase.php
@@ -0,0 +1,85 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Monolog\Test;
+
+use Monolog\Logger;
+use Monolog\DateTimeImmutable;
+use Monolog\Formatter\FormatterInterface;
+
+/**
+ * Lets you easily generate log records and a dummy formatter for testing purposes
+ *
+ * @author Jordi Boggiano
+ *
+ * @phpstan-import-type Record from \Monolog\Logger
+ * @phpstan-import-type Level from \Monolog\Logger
+ *
+ * @internal feel free to reuse this to test your own handlers, this is marked internal to avoid issues with PHPStorm https://github.com/Seldaek/monolog/issues/1677
+ */
+class TestCase extends \PHPUnit\Framework\TestCase
+{
+ public function tearDown(): void
+ {
+ parent::tearDown();
+
+ if (isset($this->handler)) {
+ unset($this->handler);
+ }
+ }
+
+ /**
+ * @param mixed[] $context
+ *
+ * @return array Record
+ *
+ * @phpstan-param Level $level
+ * @phpstan-return Record
+ */
+ protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []): array
+ {
+ return [
+ 'message' => (string) $message,
+ 'context' => $context,
+ 'level' => $level,
+ 'level_name' => Logger::getLevelName($level),
+ 'channel' => 'test',
+ 'datetime' => new DateTimeImmutable(true),
+ 'extra' => [],
+ ];
+ }
+
+ /**
+ * @phpstan-return Record[]
+ */
+ protected function getMultipleRecords(): array
+ {
+ return [
+ $this->getRecord(Logger::DEBUG, 'debug message 1'),
+ $this->getRecord(Logger::DEBUG, 'debug message 2'),
+ $this->getRecord(Logger::INFO, 'information'),
+ $this->getRecord(Logger::WARNING, 'warning'),
+ $this->getRecord(Logger::ERROR, 'error'),
+ ];
+ }
+
+ protected function getIdentityFormatter(): FormatterInterface
+ {
+ $formatter = $this->createMock(FormatterInterface::class);
+ $formatter->expects($this->any())
+ ->method('format')
+ ->will($this->returnCallback(function ($record) {
+ return $record['message'];
+ }));
+
+ return $formatter;
+ }
+}
diff --git a/vendor/monolog/monolog/src/Monolog/Utils.php b/vendor/monolog/monolog/src/Monolog/Utils.php
index 7f1ba129..360c4219 100644
--- a/vendor/monolog/monolog/src/Monolog/Utils.php
+++ b/vendor/monolog/monolog/src/Monolog/Utils.php
@@ -1,4 +1,4 @@
-=')) {
- $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
+ if (null === $encodeFlags) {
+ $encodeFlags = self::DEFAULT_JSON_FLAGS;
}
if ($ignoreErrors) {
@@ -90,16 +104,16 @@ public static function jsonEncode($data, $encodeFlags = null, $ignoreErrors = fa
*
* If the failure is due to invalid string encoding, try to clean the
* input and encode again. If the second encoding attempt fails, the
- * inital error is not encoding related or the input can't be cleaned then
+ * initial error is not encoding related or the input can't be cleaned then
* raise a descriptive exception.
*
- * @param int $code return code of json_last_error function
- * @param mixed $data data that was meant to be encoded
- * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE
+ * @param int $code return code of json_last_error function
+ * @param mixed $data data that was meant to be encoded
+ * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION
* @throws \RuntimeException if failure can't be corrected
* @return string JSON encoded data after error correction
*/
- public static function handleJsonError($code, $data, $encodeFlags = null)
+ public static function handleJsonError(int $code, $data, ?int $encodeFlags = null): string
{
if ($code !== JSON_ERROR_UTF8) {
self::throwEncodeError($code, $data);
@@ -113,8 +127,8 @@ public static function handleJsonError($code, $data, $encodeFlags = null)
self::throwEncodeError($code, $data);
}
- if (null === $encodeFlags && version_compare(PHP_VERSION, '5.4.0', '>=')) {
- $encodeFlags = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE;
+ if (null === $encodeFlags) {
+ $encodeFlags = self::DEFAULT_JSON_FLAGS;
}
$json = json_encode($data, $encodeFlags);
@@ -126,14 +140,35 @@ public static function handleJsonError($code, $data, $encodeFlags = null)
return $json;
}
+ /**
+ * @internal
+ */
+ public static function pcreLastErrorMessage(int $code): string
+ {
+ if (PHP_VERSION_ID >= 80000) {
+ return preg_last_error_msg();
+ }
+
+ $constants = (get_defined_constants(true))['pcre'];
+ $constants = array_filter($constants, function ($key) {
+ return substr($key, -6) == '_ERROR';
+ }, ARRAY_FILTER_USE_KEY);
+
+ $constants = array_flip($constants);
+
+ return $constants[$code] ?? 'UNDEFINED_ERROR';
+ }
+
/**
* Throws an exception according to a given code with a customized message
*
* @param int $code return code of json_last_error function
* @param mixed $data data that was meant to be encoded
* @throws \RuntimeException
+ *
+ * @return never
*/
- private static function throwEncodeError($code, $data)
+ private static function throwEncodeError(int $code, $data): void
{
switch ($code) {
case JSON_ERROR_DEPTH:
@@ -169,21 +204,81 @@ private static function throwEncodeError($code, $data)
* can be used as a callback for array_walk_recursive.
*
* @param mixed $data Input to check and convert if needed, passed by ref
- * @private
*/
- public static function detectAndCleanUtf8(&$data)
+ private static function detectAndCleanUtf8(&$data): void
{
if (is_string($data) && !preg_match('//u', $data)) {
$data = preg_replace_callback(
'/[\x80-\xFF]+/',
- function ($m) { return utf8_encode($m[0]); },
+ function ($m) {
+ return function_exists('mb_convert_encoding') ? mb_convert_encoding($m[0], 'UTF-8', 'ISO-8859-1') : utf8_encode($m[0]);
+ },
$data
);
+ if (!is_string($data)) {
+ $pcreErrorCode = preg_last_error();
+ throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode));
+ }
$data = str_replace(
- array('¤', '¦', '¨', '´', '¸', '¼', '½', '¾'),
- array('€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'),
+ ['¤', '¦', '¨', '´', '¸', '¼', '½', '¾'],
+ ['€', 'Š', 'š', 'Ž', 'ž', 'Œ', 'œ', 'Ÿ'],
$data
);
}
}
+
+ /**
+ * Converts a string with a valid 'memory_limit' format, to bytes.
+ *
+ * @param string|false $val
+ * @return int|false Returns an integer representing bytes. Returns FALSE in case of error.
+ */
+ public static function expandIniShorthandBytes($val)
+ {
+ if (!is_string($val)) {
+ return false;
+ }
+
+ // support -1
+ if ((int) $val < 0) {
+ return (int) $val;
+ }
+
+ if (!preg_match('/^\s*(?\d+)(?:\.\d+)?\s*(?[gmk]?)\s*$/i', $val, $match)) {
+ return false;
+ }
+
+ $val = (int) $match['val'];
+ switch (strtolower($match['unit'] ?? '')) {
+ case 'g':
+ $val *= 1024;
+ case 'm':
+ $val *= 1024;
+ case 'k':
+ $val *= 1024;
+ }
+
+ return $val;
+ }
+
+ /**
+ * @param array $record
+ */
+ public static function getRecordMessageForException(array $record): string
+ {
+ $context = '';
+ $extra = '';
+ try {
+ if ($record['context']) {
+ $context = "\nContext: " . json_encode($record['context']);
+ }
+ if ($record['extra']) {
+ $extra = "\nExtra: " . json_encode($record['extra']);
+ }
+ } catch (\Throwable $e) {
+ // noop
+ }
+
+ return "\nThe exception occurred while attempting to log: " . $record['message'] . $context . $extra;
+ }
}
diff --git a/vendor/phpseclib/phpseclib/README.md b/vendor/phpseclib/phpseclib/README.md
index 64c06ba2..bbb1e9f0 100644
--- a/vendor/phpseclib/phpseclib/README.md
+++ b/vendor/phpseclib/phpseclib/README.md
@@ -51,8 +51,7 @@ SSH-2, SFTP, X.509, an arbitrary-precision integer arithmetic library, Ed25519 /
* PHP4 compatible
* Composer compatible (PSR-0 autoloading)
* Install using Composer: `composer require phpseclib/phpseclib:~1.0`
-* Install using PEAR: See [phpseclib PEAR Channel Documentation](http://phpseclib.sourceforge.net/pear.htm)
-* [Download 1.0.20 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.20.zip/download)
+* [Download 1.0.21 as ZIP](http://sourceforge.net/projects/phpseclib/files/phpseclib1.0.21.zip/download)
## Security contact information
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php b/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php
index 407f0369..256c8690 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php
@@ -130,7 +130,7 @@ protected static function initialize_static_variables()
*
* @param string $key
* @param string $password optional
- * @return AsymmetricKey
+ * @return \phpseclib3\Crypt\Common\PublicKey|\phpseclib3\Crypt\Common\PrivateKey
*/
public static function load($key, $password = false)
{
diff --git a/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php b/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
index cf23dd73..3096ff1a 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/File/ASN1.php
@@ -1402,7 +1402,7 @@ public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::
return false;
}
break;
- case ($c & 0x80000000) != 0:
+ case ($c & (PHP_INT_SIZE == 8 ? 0x80000000 : (1 << 31))) != 0:
return false;
case $c >= 0x04000000:
$v .= chr(0x80 | ($c & 0x3F));
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php
index 3524668e..c6609e4d 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php
@@ -136,7 +136,7 @@ private static function initialize_static_variables()
{
if (!isset(self::$mainEngine)) {
$engines = [
- ['GMP'],
+ ['GMP', ['DefaultEngine']],
['PHP64', ['OpenSSL']],
['BCMath', ['OpenSSL']],
['PHP32', ['OpenSSL']],
@@ -145,7 +145,7 @@ private static function initialize_static_variables()
];
foreach ($engines as $engine) {
try {
- self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
+ self::setEngine($engine[0], $engine[1]);
break;
} catch (\Exception $e) {
}
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php
index 964cd170..18f78cdb 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php
@@ -80,10 +80,10 @@ protected function initialize($base)
}
$step = count($vals) & 3;
if ($step) {
- $digit = floor($digit / pow(2, 2 * $step));
+ $digit = (int) floor($digit / pow(2, 2 * $step));
}
if ($step != 3) {
- $digit &= static::MAX_DIGIT;
+ $digit = (int) fmod($digit, static::BASE_FULL);
$i++;
}
$vals[] = $digit;
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php b/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php
index 748f9a49..ddb04912 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php
@@ -312,8 +312,11 @@ public function negate()
*/
public function toBytes()
{
- $length = static::$modulo[$this->instanceID]->getLengthInBytes();
- return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
+ if (isset(static::$modulo[$this->instanceID])) {
+ $length = static::$modulo[$this->instanceID]->getLengthInBytes();
+ return str_pad($this->value->toBytes(), $length, "\0", STR_PAD_LEFT);
+ }
+ return $this->value->toBytes();
}
/**
diff --git a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php b/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
index fb136bd7..cdf0bec6 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.php
@@ -2489,14 +2489,6 @@ public function get($remote_file, $local_file = false, $offset = 0, $length = -1
}
}
- if ($length > 0 && $length <= $offset - $start) {
- if ($local_file === false) {
- $content = substr($content, 0, $length);
- } else {
- ftruncate($fp, $length + $res_offset);
- }
- }
-
if ($fclose_check) {
fclose($fp);
diff --git a/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php b/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php
index 517106c3..b794d549 100644
--- a/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php
+++ b/vendor/phpseclib/phpseclib/phpseclib/bootstrap.php
@@ -20,3 +20,13 @@
);
}
}
+
+// see https://github.com/php/php-src/issues/11917
+if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && function_exists('opcache_get_status') && !defined('PHPSECLIB_ALLOW_JIT')) {
+ $status = opcache_get_status();
+ if ($status && isset($status['jit']) && $status['jit']['enabled'] && $status['jit']['on']) {
+ throw new UnexpectedValueException(
+ 'JIT on Windows is not currently supported'
+ );
+ }
+}
diff --git a/vendor/psr/container/README.md b/vendor/psr/container/README.md
index 084f6df5..1b9d9e57 100644
--- a/vendor/psr/container/README.md
+++ b/vendor/psr/container/README.md
@@ -1,5 +1,13 @@
-# PSR Container
+Container interface
+==============
-This repository holds all interfaces/classes/traits related to [PSR-11](https://github.com/container-interop/fig-standards/blob/master/proposed/container.md).
+This repository holds all interfaces related to [PSR-11 (Container Interface)][psr-url].
+
+Note that this is not a Container implementation of its own. It is merely abstractions that describe the components of a Dependency Injection Container.
+
+The installable [package][package-url] and [implementations][implementation-url] are listed on Packagist.
+
+[psr-url]: https://www.php-fig.org/psr/psr-11/
+[package-url]: https://packagist.org/packages/psr/container
+[implementation-url]: https://packagist.org/providers/psr/container-implementation
-Note that this is not a container implementation of its own. See the specification for more details.
diff --git a/vendor/psr/container/composer.json b/vendor/psr/container/composer.json
index b8ee0126..017f41ea 100644
--- a/vendor/psr/container/composer.json
+++ b/vendor/psr/container/composer.json
@@ -8,20 +8,15 @@
"authors": [
{
"name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
+ "homepage": "https://www.php-fig.org/"
}
],
"require": {
- "php": ">=5.3.0"
+ "php": ">=7.4.0"
},
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
- },
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
}
}
diff --git a/vendor/psr/container/src/ContainerExceptionInterface.php b/vendor/psr/container/src/ContainerExceptionInterface.php
index d35c6b4d..0f213f2f 100644
--- a/vendor/psr/container/src/ContainerExceptionInterface.php
+++ b/vendor/psr/container/src/ContainerExceptionInterface.php
@@ -1,13 +1,12 @@
Permission is hereby granted, free of charge, to any person obtaining a copy
-> of this software and associated documentation files (the "Software"), to deal
-> in the Software without restriction, including without limitation the rights
-> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-> copies of the Software, and to permit persons to whom the Software is
-> furnished to do so, subject to the following conditions:
->
-> The above copyright notice and this permission notice shall be included in
-> all copies or substantial portions of the Software.
->
-> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-> THE SOFTWARE.
diff --git a/vendor/psr/simple-cache/README.md b/vendor/psr/simple-cache/README.md
deleted file mode 100644
index 43641d17..00000000
--- a/vendor/psr/simple-cache/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-PHP FIG Simple Cache PSR
-========================
-
-This repository holds all interfaces related to PSR-16.
-
-Note that this is not a cache implementation of its own. It is merely an interface that describes a cache implementation. See [the specification](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-16-simple-cache.md) for more details.
-
-You can find implementations of the specification by looking for packages providing the [psr/simple-cache-implementation](https://packagist.org/providers/psr/simple-cache-implementation) virtual package.
diff --git a/vendor/psr/simple-cache/composer.json b/vendor/psr/simple-cache/composer.json
deleted file mode 100644
index 2978fa55..00000000
--- a/vendor/psr/simple-cache/composer.json
+++ /dev/null
@@ -1,25 +0,0 @@
-{
- "name": "psr/simple-cache",
- "description": "Common interfaces for simple caching",
- "keywords": ["psr", "psr-16", "cache", "simple-cache", "caching"],
- "license": "MIT",
- "authors": [
- {
- "name": "PHP-FIG",
- "homepage": "http://www.php-fig.org/"
- }
- ],
- "require": {
- "php": ">=5.3.0"
- },
- "autoload": {
- "psr-4": {
- "Psr\\SimpleCache\\": "src/"
- }
- },
- "extra": {
- "branch-alias": {
- "dev-master": "1.0.x-dev"
- }
- }
-}
diff --git a/vendor/psr/simple-cache/src/CacheException.php b/vendor/psr/simple-cache/src/CacheException.php
deleted file mode 100644
index eba53815..00000000
--- a/vendor/psr/simple-cache/src/CacheException.php
+++ /dev/null
@@ -1,10 +0,0 @@
- value pairs. Cache keys that do not exist or are stale will have $default as value.
- *
- * @throws \Psr\SimpleCache\InvalidArgumentException
- * MUST be thrown if $keys is neither an array nor a Traversable,
- * or if any of the $keys are not a legal value.
- */
- public function getMultiple($keys, $default = null);
-
- /**
- * Persists a set of key => value pairs in the cache, with an optional TTL.
- *
- * @param iterable $values A list of key => value pairs for a multiple-set operation.
- * @param null|int|\DateInterval $ttl Optional. The TTL value of this item. If no value is sent and
- * the driver supports TTL then the library may set a default value
- * for it or let the driver take care of that.
- *
- * @return bool True on success and false on failure.
- *
- * @throws \Psr\SimpleCache\InvalidArgumentException
- * MUST be thrown if $values is neither an array nor a Traversable,
- * or if any of the $values are not a legal value.
- */
- public function setMultiple($values, $ttl = null);
-
- /**
- * Deletes multiple cache items in a single operation.
- *
- * @param iterable $keys A list of string-based keys to be deleted.
- *
- * @return bool True if the items were successfully removed. False if there was an error.
- *
- * @throws \Psr\SimpleCache\InvalidArgumentException
- * MUST be thrown if $keys is neither an array nor a Traversable,
- * or if any of the $keys are not a legal value.
- */
- public function deleteMultiple($keys);
-
- /**
- * Determines whether an item is present in the cache.
- *
- * NOTE: It is recommended that has() is only to be used for cache warming type purposes
- * and not to be used within your live applications operations for get/set, as this method
- * is subject to a race condition where your has() will return true and immediately after,
- * another script can remove it making the state of your app out of date.
- *
- * @param string $key The cache item key.
- *
- * @return bool
- *
- * @throws \Psr\SimpleCache\InvalidArgumentException
- * MUST be thrown if the $key string is not a legal value.
- */
- public function has($key);
-}
diff --git a/vendor/psr/simple-cache/src/InvalidArgumentException.php b/vendor/psr/simple-cache/src/InvalidArgumentException.php
deleted file mode 100644
index 6a9524a2..00000000
--- a/vendor/psr/simple-cache/src/InvalidArgumentException.php
+++ /dev/null
@@ -1,13 +0,0 @@
-
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Covers most simple to advanced caching needs.
+ *
+ * @author Nicolas Grekas
+ */
+interface CacheInterface
+{
+ /**
+ * Fetches a value from the pool or computes it if not found.
+ *
+ * On cache misses, a callback is called that should return the missing value.
+ * This callback is given a PSR-6 CacheItemInterface instance corresponding to the
+ * requested key, that could be used e.g. for expiration control. It could also
+ * be an ItemInterface instance when its additional features are needed.
+ *
+ * @param string $key The key of the item to retrieve from the cache
+ * @param callable|CallbackInterface $callback Should return the computed value for the given key/item
+ * @param float|null $beta A float that, as it grows, controls the likeliness of triggering
+ * early expiration. 0 disables it, INF forces immediate expiration.
+ * The default (or providing null) is implementation dependent but should
+ * typically be 1.0, which should provide optimal stampede protection.
+ * See https://en.wikipedia.org/wiki/Cache_stampede#Probabilistic_early_expiration
+ * @param array &$metadata The metadata of the cached item {@see ItemInterface::getMetadata()}
+ *
+ * @return mixed
+ *
+ * @throws InvalidArgumentException When $key is not valid or when $beta is negative
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null);
+
+ /**
+ * Removes an item from the pool.
+ *
+ * @param string $key The key to delete
+ *
+ * @throws InvalidArgumentException When $key is not valid
+ *
+ * @return bool True if the item was successfully removed, false if there was any error
+ */
+ public function delete(string $key): bool;
+}
diff --git a/vendor/symfony/cache-contracts/CacheTrait.php b/vendor/symfony/cache-contracts/CacheTrait.php
new file mode 100644
index 00000000..d340e069
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CacheTrait.php
@@ -0,0 +1,80 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\Cache\InvalidArgumentException;
+use Psr\Log\LoggerInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(InvalidArgumentException::class);
+
+/**
+ * An implementation of CacheInterface for PSR-6 CacheItemPoolInterface classes.
+ *
+ * @author Nicolas Grekas
+ */
+trait CacheTrait
+{
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ return $this->doGet($this, $key, $callback, $beta, $metadata);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
+
+ private function doGet(CacheItemPoolInterface $pool, string $key, callable $callback, ?float $beta, array &$metadata = null, LoggerInterface $logger = null)
+ {
+ if (0 > $beta = $beta ?? 1.0) {
+ throw new class(sprintf('Argument "$beta" provided to "%s::get()" must be a positive number, %f given.', static::class, $beta)) extends \InvalidArgumentException implements InvalidArgumentException { };
+ }
+
+ $item = $pool->getItem($key);
+ $recompute = !$item->isHit() || \INF === $beta;
+ $metadata = $item instanceof ItemInterface ? $item->getMetadata() : [];
+
+ if (!$recompute && $metadata) {
+ $expiry = $metadata[ItemInterface::METADATA_EXPIRY] ?? false;
+ $ctime = $metadata[ItemInterface::METADATA_CTIME] ?? false;
+
+ if ($recompute = $ctime && $expiry && $expiry <= ($now = microtime(true)) - $ctime / 1000 * $beta * log(random_int(1, \PHP_INT_MAX) / \PHP_INT_MAX)) {
+ // force applying defaultLifetime to expiry
+ $item->expiresAt(null);
+ $logger && $logger->info('Item "{key}" elected for early recomputation {delta}s before its expiration', [
+ 'key' => $key,
+ 'delta' => sprintf('%.1f', $expiry - $now),
+ ]);
+ }
+ }
+
+ if ($recompute) {
+ $save = true;
+ $item->set($callback($item, $save));
+ if ($save) {
+ $pool->save($item);
+ }
+ }
+
+ return $item->get();
+ }
+}
diff --git a/vendor/symfony/cache-contracts/CallbackInterface.php b/vendor/symfony/cache-contracts/CallbackInterface.php
new file mode 100644
index 00000000..7dae2aac
--- /dev/null
+++ b/vendor/symfony/cache-contracts/CallbackInterface.php
@@ -0,0 +1,30 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheItemInterface;
+
+/**
+ * Computes and returns the cached value of an item.
+ *
+ * @author Nicolas Grekas
+ */
+interface CallbackInterface
+{
+ /**
+ * @param CacheItemInterface|ItemInterface $item The item to compute the value for
+ * @param bool &$save Should be set to false when the value should not be saved in the pool
+ *
+ * @return mixed The computed value for the passed item
+ */
+ public function __invoke(CacheItemInterface $item, bool &$save);
+}
diff --git a/vendor/symfony/cache-contracts/ItemInterface.php b/vendor/symfony/cache-contracts/ItemInterface.php
new file mode 100644
index 00000000..10c04889
--- /dev/null
+++ b/vendor/symfony/cache-contracts/ItemInterface.php
@@ -0,0 +1,65 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\CacheException;
+use Psr\Cache\CacheItemInterface;
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Augments PSR-6's CacheItemInterface with support for tags and metadata.
+ *
+ * @author Nicolas Grekas
+ */
+interface ItemInterface extends CacheItemInterface
+{
+ /**
+ * References the Unix timestamp stating when the item will expire.
+ */
+ public const METADATA_EXPIRY = 'expiry';
+
+ /**
+ * References the time the item took to be created, in milliseconds.
+ */
+ public const METADATA_CTIME = 'ctime';
+
+ /**
+ * References the list of tags that were assigned to the item, as string[].
+ */
+ public const METADATA_TAGS = 'tags';
+
+ /**
+ * Reserved characters that cannot be used in a key or tag.
+ */
+ public const RESERVED_CHARACTERS = '{}()/\@:';
+
+ /**
+ * Adds a tag to a cache item.
+ *
+ * Tags are strings that follow the same validation rules as keys.
+ *
+ * @param string|string[] $tags A tag or array of tags
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException When $tag is not valid
+ * @throws CacheException When the item comes from a pool that is not tag-aware
+ */
+ public function tag($tags): self;
+
+ /**
+ * Returns a list of metadata info that were saved alongside with the cached value.
+ *
+ * See ItemInterface::METADATA_* consts for keys potentially found in the returned array.
+ */
+ public function getMetadata(): array;
+}
diff --git a/vendor/symfony/cache-contracts/LICENSE b/vendor/symfony/cache-contracts/LICENSE
new file mode 100644
index 00000000..74cdc2db
--- /dev/null
+++ b/vendor/symfony/cache-contracts/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2018-2022 Fabien Potencier
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is furnished
+to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/symfony/cache-contracts/README.md b/vendor/symfony/cache-contracts/README.md
new file mode 100644
index 00000000..7085a699
--- /dev/null
+++ b/vendor/symfony/cache-contracts/README.md
@@ -0,0 +1,9 @@
+Symfony Cache Contracts
+=======================
+
+A set of abstractions extracted out of the Symfony components.
+
+Can be used to build on semantics that the Symfony components proved useful - and
+that already have battle tested implementations.
+
+See https://github.com/symfony/contracts/blob/main/README.md for more information.
diff --git a/vendor/symfony/cache-contracts/TagAwareCacheInterface.php b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php
new file mode 100644
index 00000000..7c4cf111
--- /dev/null
+++ b/vendor/symfony/cache-contracts/TagAwareCacheInterface.php
@@ -0,0 +1,38 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Contracts\Cache;
+
+use Psr\Cache\InvalidArgumentException;
+
+/**
+ * Allows invalidating cached items using tags.
+ *
+ * @author Nicolas Grekas
+ */
+interface TagAwareCacheInterface extends CacheInterface
+{
+ /**
+ * Invalidates cached items using tags.
+ *
+ * When implemented on a PSR-6 pool, invalidation should not apply
+ * to deferred items. Instead, they should be committed as usual.
+ * This allows replacing old tagged values by new ones without
+ * race conditions.
+ *
+ * @param string[] $tags An array of tags to invalidate
+ *
+ * @return bool True on success
+ *
+ * @throws InvalidArgumentException When $tags is not valid
+ */
+ public function invalidateTags(array $tags);
+}
diff --git a/vendor/symfony/cache-contracts/composer.json b/vendor/symfony/cache-contracts/composer.json
new file mode 100644
index 00000000..9f45e178
--- /dev/null
+++ b/vendor/symfony/cache-contracts/composer.json
@@ -0,0 +1,38 @@
+{
+ "name": "symfony/cache-contracts",
+ "type": "library",
+ "description": "Generic abstractions related to caching",
+ "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Nicolas Grekas",
+ "email": "p@tchwork.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=7.2.5",
+ "psr/cache": "^1.0|^2.0|^3.0"
+ },
+ "suggest": {
+ "symfony/cache-implementation": ""
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Contracts\\Cache\\": "" }
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-main": "2.5-dev"
+ },
+ "thanks": {
+ "name": "symfony/contracts",
+ "url": "https://github.com/symfony/contracts"
+ }
+ }
+}
diff --git a/vendor/symfony/cache/.gitignore b/vendor/symfony/cache/.gitignore
deleted file mode 100644
index 5414c2c6..00000000
--- a/vendor/symfony/cache/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-composer.lock
-phpunit.xml
-vendor/
diff --git a/vendor/symfony/cache/Adapter/AbstractAdapter.php b/vendor/symfony/cache/Adapter/AbstractAdapter.php
index ab7dc960..65647442 100644
--- a/vendor/symfony/cache/Adapter/AbstractAdapter.php
+++ b/vendor/symfony/cache/Adapter/AbstractAdapter.php
@@ -11,37 +11,32 @@
namespace Symfony\Component\Cache\Adapter;
-use Psr\Cache\CacheItemInterface;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\ResettableInterface;
-use Symfony\Component\Cache\Traits\AbstractTrait;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
/**
* @author Nicolas Grekas
*/
-abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface
+abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
{
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
/**
* @internal
*/
- const NS_SEPARATOR = ':';
-
- use AbstractTrait;
+ protected const NS_SEPARATOR = ':';
private static $apcuSupported;
private static $phpFilesSupported;
- private $createCacheItem;
- private $mergeByLifetime;
-
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- */
- protected function __construct($namespace = '', $defaultLifetime = 0)
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
{
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
@@ -51,31 +46,45 @@ protected function __construct($namespace = '', $defaultLifetime = 0)
static function ($key, $value, $isHit) {
$item = new CacheItem();
$item->key = $key;
- $item->value = $value;
+ $item->value = $v = $value;
$item->isHit = $isHit;
+ // Detect wrapped values that encode for their expiry and creation duration
+ // For compactness, these values are packed in the key of an array using
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
+ $item->value = $v[$k];
+ $v = unpack('Ve/Nc', substr($k, 1, -1));
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ }
return $item;
},
null,
CacheItem::class
);
- $getId = function ($key) { return $this->getId((string) $key); };
+ $getId = \Closure::fromCallable([$this, 'getId']);
$this->mergeByLifetime = \Closure::bind(
static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifetime) {
$byLifetime = [];
- $now = time();
+ $now = microtime(true);
$expiredIds = [];
foreach ($deferred as $key => $item) {
+ $key = (string) $key;
if (null === $item->expiry) {
- $byLifetime[0 < $defaultLifetime ? $defaultLifetime : 0][$getId($key)] = $item->value;
- } elseif (0 === $item->expiry) {
- $byLifetime[0][$getId($key)] = $item->value;
- } elseif ($item->expiry > $now) {
- $byLifetime[$item->expiry - $now][$getId($key)] = $item->value;
- } else {
+ $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
+ } elseif (!$item->expiry) {
+ $ttl = 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
$expiredIds[] = $getId($key);
+ continue;
+ }
+ if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
+ unset($metadata[CacheItem::METADATA_TAGS]);
}
+ // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
+ $byLifetime[$ttl][$getId($key)] = $metadata ? ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item->value] : $item->value;
}
return $byLifetime;
@@ -86,6 +95,10 @@ static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifet
}
/**
+ * Returns the best possible adapter that your runtime supports.
+ *
+ * Using ApcuAdapter makes system caches compatible with read-only filesystems.
+ *
* @param string $namespace
* @param int $defaultLifetime
* @param string $version
@@ -95,37 +108,25 @@ static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifet
*/
public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null)
{
- if (null === self::$apcuSupported) {
- self::$apcuSupported = ApcuAdapter::isSupported();
- }
-
- if (!self::$apcuSupported && null === self::$phpFilesSupported) {
- self::$phpFilesSupported = PhpFilesAdapter::isSupported();
+ $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory, true);
+ if (null !== $logger) {
+ $opcache->setLogger($logger);
}
- if (self::$phpFilesSupported) {
- $opcache = new PhpFilesAdapter($namespace, $defaultLifetime, $directory);
- if (null !== $logger) {
- $opcache->setLogger($logger);
- }
-
+ if (!self::$apcuSupported = self::$apcuSupported ?? ApcuAdapter::isSupported()) {
return $opcache;
}
- $fs = new FilesystemAdapter($namespace, $defaultLifetime, $directory);
- if (null !== $logger) {
- $fs->setLogger($logger);
- }
- if (!self::$apcuSupported || (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN))) {
- return $fs;
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
+ return $opcache;
}
- $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version);
+ $apcu = new ApcuAdapter($namespace, intdiv($defaultLifetime, 5), $version);
if (null !== $logger) {
$apcu->setLogger($logger);
}
- return new ChainAdapter([$apcu, $fs]);
+ return new ChainAdapter([$apcu, $opcache]);
}
public static function createConnection($dsn, array $options = [])
@@ -133,10 +134,10 @@ public static function createConnection($dsn, array $options = [])
if (!\is_string($dsn)) {
throw new InvalidArgumentException(sprintf('The "%s()" method expect argument #1 to be string, "%s" given.', __METHOD__, \gettype($dsn)));
}
- if (0 === strpos($dsn, 'redis://')) {
+ if (str_starts_with($dsn, 'redis:') || str_starts_with($dsn, 'rediss:')) {
return RedisAdapter::createConnection($dsn, $options);
}
- if (0 === strpos($dsn, 'memcached://')) {
+ if (str_starts_with($dsn, 'memcached:')) {
return MemcachedAdapter::createConnection($dsn, $options);
}
@@ -145,81 +146,8 @@ public static function createConnection($dsn, array $options = [])
/**
* {@inheritdoc}
- */
- public function getItem($key)
- {
- if ($this->deferred) {
- $this->commit();
- }
- $id = $this->getId($key);
-
- $f = $this->createCacheItem;
- $isHit = false;
- $value = null;
-
- try {
- foreach ($this->doFetch([$id]) as $value) {
- $isHit = true;
- }
- } catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]);
- }
-
- return $f($key, $value, $isHit);
- }
-
- /**
- * {@inheritdoc}
- */
- public function getItems(array $keys = [])
- {
- if ($this->deferred) {
- $this->commit();
- }
- $ids = [];
-
- foreach ($keys as $key) {
- $ids[] = $this->getId($key);
- }
- try {
- $items = $this->doFetch($ids);
- } catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => $keys, 'exception' => $e]);
- $items = [];
- }
- $ids = array_combine($ids, $keys);
-
- return $this->generateItems($items, $ids);
- }
-
- /**
- * {@inheritdoc}
- */
- public function save(CacheItemInterface $item)
- {
- if (!$item instanceof CacheItem) {
- return false;
- }
- $this->deferred[$item->getKey()] = $item;
-
- return $this->commit();
- }
-
- /**
- * {@inheritdoc}
- */
- public function saveDeferred(CacheItemInterface $item)
- {
- if (!$item instanceof CacheItem) {
- return false;
- }
- $this->deferred[$item->getKey()] = $item;
-
- return true;
- }
-
- /**
- * {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
@@ -229,7 +157,12 @@ public function commit()
$retry = $this->deferred = [];
if ($expiredIds) {
- $this->doDelete($expiredIds);
+ try {
+ $this->doDelete($expiredIds);
+ } catch (\Exception $e) {
+ $ok = false;
+ CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
}
foreach ($byLifetime as $lifetime => $values) {
try {
@@ -244,7 +177,8 @@ public function commit()
$ok = false;
$v = $values[$id];
$type = \is_object($v) ? \get_class($v) : \gettype($v);
- CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
}
} else {
foreach ($values as $id => $v) {
@@ -266,49 +200,11 @@ public function commit()
}
$ok = false;
$type = \is_object($v) ? \get_class($v) : \gettype($v);
- CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => substr($id, \strlen($this->namespace)), 'type' => $type, 'exception' => $e instanceof \Exception ? $e : null]);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
}
}
return $ok;
}
-
- public function __sleep()
- {
- throw new \BadMethodCallException('Cannot serialize '.__CLASS__);
- }
-
- public function __wakeup()
- {
- throw new \BadMethodCallException('Cannot unserialize '.__CLASS__);
- }
-
- public function __destruct()
- {
- if ($this->deferred) {
- $this->commit();
- }
- }
-
- private function generateItems($items, &$keys)
- {
- $f = $this->createCacheItem;
-
- try {
- foreach ($items as $id => $value) {
- if (!isset($keys[$id])) {
- $id = key($keys);
- }
- $key = $keys[$id];
- unset($keys[$id]);
- yield $key => $f($key, $value, true);
- }
- } catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch requested items', ['keys' => array_values($keys), 'exception' => $e]);
- }
-
- foreach ($keys as $key) {
- yield $key => $f($key, null, false);
- }
- }
}
diff --git a/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
new file mode 100644
index 00000000..6b62ae98
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/AbstractTagAwareAdapter.php
@@ -0,0 +1,334 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\Log\LoggerAwareInterface;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\AbstractAdapterTrait;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\TagAwareCacheInterface;
+
+/**
+ * Abstract for native TagAware adapters.
+ *
+ * To keep info on tags, the tags are both serialized as part of cache value and provided as tag ids
+ * to Adapters on operations when needed for storage to doSave(), doDelete() & doInvalidate().
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ *
+ * @internal
+ */
+abstract class AbstractTagAwareAdapter implements TagAwareAdapterInterface, TagAwareCacheInterface, LoggerAwareInterface, ResettableInterface
+{
+ use AbstractAdapterTrait;
+ use ContractsTrait;
+
+ private const TAGS_PREFIX = "\0tags\0";
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
+ {
+ $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
+ if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
+ throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
+ }
+ $this->createCacheItem = \Closure::bind(
+ static function ($key, $value, $isHit) {
+ $item = new CacheItem();
+ $item->key = $key;
+ $item->isTaggable = true;
+ // If structure does not match what we expect return item as is (no value and not a hit)
+ if (!\is_array($value) || !\array_key_exists('value', $value)) {
+ return $item;
+ }
+ $item->isHit = $isHit;
+ // Extract value, tags and meta data from the cache value
+ $item->value = $value['value'];
+ $item->metadata[CacheItem::METADATA_TAGS] = $value['tags'] ?? [];
+ if (isset($value['meta'])) {
+ // For compactness these values are packed, & expiry is offset to reduce size
+ $v = unpack('Ve/Nc', $value['meta']);
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ }
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $getId = \Closure::fromCallable([$this, 'getId']);
+ $tagPrefix = self::TAGS_PREFIX;
+ $this->mergeByLifetime = \Closure::bind(
+ static function ($deferred, &$expiredIds) use ($getId, $tagPrefix, $defaultLifetime) {
+ $byLifetime = [];
+ $now = microtime(true);
+ $expiredIds = [];
+
+ foreach ($deferred as $key => $item) {
+ $key = (string) $key;
+ if (null === $item->expiry) {
+ $ttl = 0 < $defaultLifetime ? $defaultLifetime : 0;
+ } elseif (!$item->expiry) {
+ $ttl = 0;
+ } elseif (0 >= $ttl = (int) (0.1 + $item->expiry - $now)) {
+ $expiredIds[] = $getId($key);
+ continue;
+ }
+ // Store Value and Tags on the cache value
+ if (isset(($metadata = $item->newMetadata)[CacheItem::METADATA_TAGS])) {
+ $value = ['value' => $item->value, 'tags' => $metadata[CacheItem::METADATA_TAGS]];
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ } else {
+ $value = ['value' => $item->value, 'tags' => []];
+ }
+
+ if ($metadata) {
+ // For compactness, expiry and creation duration are packed, using magic numbers as separators
+ $value['meta'] = pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME]);
+ }
+
+ // Extract tag changes, these should be removed from values in doSave()
+ $value['tag-operations'] = ['add' => [], 'remove' => []];
+ $oldTags = $item->metadata[CacheItem::METADATA_TAGS] ?? [];
+ foreach (array_diff($value['tags'], $oldTags) as $addedTag) {
+ $value['tag-operations']['add'][] = $getId($tagPrefix.$addedTag);
+ }
+ foreach (array_diff($oldTags, $value['tags']) as $removedTag) {
+ $value['tag-operations']['remove'][] = $getId($tagPrefix.$removedTag);
+ }
+
+ $byLifetime[$ttl][$getId($key)] = $value;
+ $item->metadata = $item->newMetadata;
+ }
+
+ return $byLifetime;
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * Persists several cache items immediately.
+ *
+ * @param array $values The values to cache, indexed by their cache identifier
+ * @param int $lifetime The lifetime of the cached values, 0 for persisting until manual cleaning
+ * @param array[] $addTagData Hash where key is tag id, and array value is list of cache id's to add to tag
+ * @param array[] $removeTagData Hash where key is tag id, and array value is list of cache id's to remove to tag
+ *
+ * @return array The identifiers that failed to be cached or a boolean stating if caching succeeded or not
+ */
+ abstract protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array;
+
+ /**
+ * Removes multiple items from the pool and their corresponding tags.
+ *
+ * @param array $ids An array of identifiers that should be removed from the pool
+ *
+ * @return bool True if the items were successfully removed, false otherwise
+ */
+ abstract protected function doDelete(array $ids);
+
+ /**
+ * Removes relations between tags and deleted items.
+ *
+ * @param array $tagData Array of tag => key identifiers that should be removed from the pool
+ */
+ abstract protected function doDeleteTagRelations(array $tagData): bool;
+
+ /**
+ * Invalidates cached items using tags.
+ *
+ * @param string[] $tagIds An array of tags to invalidate, key is tag and value is tag id
+ *
+ * @return bool True on success
+ */
+ abstract protected function doInvalidate(array $tagIds): bool;
+
+ /**
+ * Delete items and yields the tags they were bound to.
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($this->doFetch($ids) as $id => $value) {
+ yield $id => \is_array($value) && \is_array($value['tags'] ?? null) ? $value['tags'] : [];
+ }
+
+ $this->doDelete($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function commit(): bool
+ {
+ $ok = true;
+ $byLifetime = $this->mergeByLifetime;
+ $byLifetime = $byLifetime($this->deferred, $expiredIds);
+ $retry = $this->deferred = [];
+
+ if ($expiredIds) {
+ // Tags are not cleaned up in this case, however that is done on invalidateTags().
+ try {
+ $this->doDelete($expiredIds);
+ } catch (\Exception $e) {
+ $ok = false;
+ CacheItem::log($this->logger, 'Failed to delete expired items: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+ }
+ foreach ($byLifetime as $lifetime => $values) {
+ try {
+ $values = $this->extractTagData($values, $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ if (\is_array($e) || 1 === \count($values)) {
+ foreach (\is_array($e) ? $e : array_keys($values) as $id) {
+ $ok = false;
+ $v = $values[$id];
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ } else {
+ foreach ($values as $id => $v) {
+ $retry[$lifetime][] = $id;
+ }
+ }
+ }
+
+ // When bulk-save failed, retry each item individually
+ foreach ($retry as $lifetime => $ids) {
+ foreach ($ids as $id) {
+ try {
+ $v = $byLifetime[$lifetime][$id];
+ $values = $this->extractTagData([$id => $v], $addTagData, $removeTagData);
+ $e = $this->doSave($values, $lifetime, $addTagData, $removeTagData);
+ } catch (\Exception $e) {
+ }
+ if (true === $e || [] === $e) {
+ continue;
+ }
+ $ok = false;
+ $type = \is_object($v) ? \get_class($v) : \gettype($v);
+ $message = sprintf('Failed to save key "{key}" of type %s%s', $type, $e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => substr($id, \strlen($this->namespace)), 'exception' => $e instanceof \Exception ? $e : null]);
+ }
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function deleteItems(array $keys): bool
+ {
+ if (!$keys) {
+ return true;
+ }
+
+ $ok = true;
+ $ids = [];
+ $tagData = [];
+
+ foreach ($keys as $key) {
+ $ids[$key] = $this->getId($key);
+ unset($this->deferred[$key]);
+ }
+
+ try {
+ foreach ($this->doDeleteYieldTags(array_values($ids)) as $id => $tags) {
+ foreach ($tags as $tag) {
+ $tagData[$this->getId(self::TAGS_PREFIX.$tag)][] = $id;
+ }
+ }
+ } catch (\Exception $e) {
+ $ok = false;
+ }
+
+ try {
+ if ((!$tagData || $this->doDeleteTagRelations($tagData)) && $ok) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ }
+
+ // When bulk-delete failed, retry each item individually
+ foreach ($ids as $key => $id) {
+ try {
+ $e = null;
+ if ($this->doDelete([$id])) {
+ continue;
+ }
+ } catch (\Exception $e) {
+ }
+ $message = 'Failed to delete key "{key}"'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['key' => $key, 'exception' => $e]);
+ $ok = false;
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function invalidateTags(array $tags)
+ {
+ if (empty($tags)) {
+ return false;
+ }
+
+ $tagIds = [];
+ foreach (array_unique($tags) as $tag) {
+ $tagIds[] = $this->getId(self::TAGS_PREFIX.$tag);
+ }
+
+ try {
+ if ($this->doInvalidate($tagIds)) {
+ return true;
+ }
+ } catch (\Exception $e) {
+ CacheItem::log($this->logger, 'Failed to invalidate tags: '.$e->getMessage(), ['exception' => $e, 'cache-adapter' => get_debug_type($this)]);
+ }
+
+ return false;
+ }
+
+ /**
+ * Extracts tags operation data from $values set in mergeByLifetime, and returns values without it.
+ */
+ private function extractTagData(array $values, ?array &$addTagData, ?array &$removeTagData): array
+ {
+ $addTagData = $removeTagData = [];
+ foreach ($values as $id => $value) {
+ foreach ($value['tag-operations']['add'] as $tag => $tagId) {
+ $addTagData[$tagId][] = $id;
+ }
+
+ foreach ($value['tag-operations']['remove'] as $tag => $tagId) {
+ $removeTagData[$tagId][] = $id;
+ }
+
+ unset($values[$id]['tag-operations']);
+ }
+
+ return $values;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/AdapterInterface.php b/vendor/symfony/cache/Adapter/AdapterInterface.php
index 85fe0768..9e359e17 100644
--- a/vendor/symfony/cache/Adapter/AdapterInterface.php
+++ b/vendor/symfony/cache/Adapter/AdapterInterface.php
@@ -14,6 +14,9 @@
use Psr\Cache\CacheItemPoolInterface;
use Symfony\Component\Cache\CacheItem;
+// Help opcache.preload discover always-needed symbols
+class_exists(CacheItem::class);
+
/**
* Interface for adapters managing instances of Symfony's CacheItem.
*
@@ -34,4 +37,13 @@ public function getItem($key);
* @return \Traversable|CacheItem[]
*/
public function getItems(array $keys = []);
+
+ /**
+ * {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
+ */
+ public function clear(/* string $prefix = '' */);
}
diff --git a/vendor/symfony/cache/Adapter/ApcuAdapter.php b/vendor/symfony/cache/Adapter/ApcuAdapter.php
index 50554ed6..7db39565 100644
--- a/vendor/symfony/cache/Adapter/ApcuAdapter.php
+++ b/vendor/symfony/cache/Adapter/ApcuAdapter.php
@@ -18,13 +18,9 @@ class ApcuAdapter extends AbstractAdapter
use ApcuTrait;
/**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $version
- *
* @throws CacheException if APCu is not enabled
*/
- public function __construct($namespace = '', $defaultLifetime = 0, $version = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null)
{
$this->init($namespace, $defaultLifetime, $version);
}
diff --git a/vendor/symfony/cache/Adapter/ArrayAdapter.php b/vendor/symfony/cache/Adapter/ArrayAdapter.php
index 33f55a86..20043dec 100644
--- a/vendor/symfony/cache/Adapter/ArrayAdapter.php
+++ b/vendor/symfony/cache/Adapter/ArrayAdapter.php
@@ -16,11 +16,12 @@
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
/**
* @author Nicolas Grekas
*/
-class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface
+class ArrayAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
{
use ArrayTrait;
@@ -28,10 +29,9 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable
private $defaultLifetime;
/**
- * @param int $defaultLifetime
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
*/
- public function __construct($defaultLifetime = 0, $storeSerialized = true)
+ public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true)
{
$this->defaultLifetime = $defaultLifetime;
$this->storeSerialized = $storeSerialized;
@@ -52,24 +52,32 @@ static function ($key, $value, $isHit) {
/**
* {@inheritdoc}
*/
- public function getItem($key)
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
{
- $isHit = $this->hasItem($key);
- try {
- if (!$isHit) {
- $this->values[$key] = $value = null;
- } elseif (!$this->storeSerialized) {
- $value = $this->values[$key];
- } elseif ('b:0;' === $value = $this->values[$key]) {
- $value = false;
- } elseif (false === $value = unserialize($value)) {
- $this->values[$key] = $value = null;
- $isHit = false;
+ $item = $this->getItem($key);
+ $metadata = $item->getMetadata();
+
+ // ArrayAdapter works in memory, we don't care about stampede protection
+ if (\INF === $beta || !$item->isHit()) {
+ $save = true;
+ $item->set($callback($item, $save));
+ if ($save) {
+ $this->save($item);
}
- } catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to unserialize key "{key}"', ['key' => $key, 'exception' => $e]);
+ }
+
+ return $item->get();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getItem($key)
+ {
+ if (!$isHit = $this->hasItem($key)) {
$this->values[$key] = $value = null;
- $isHit = false;
+ } else {
+ $value = $this->storeSerialized ? $this->unfreeze($key, $isHit) : $this->values[$key];
}
$f = $this->createCacheItem;
@@ -82,14 +90,18 @@ public function getItem($key)
public function getItems(array $keys = [])
{
foreach ($keys as $key) {
- CacheItem::validateKey($key);
+ if (!\is_string($key) || !isset($this->expiries[$key])) {
+ CacheItem::validateKey($key);
+ }
}
- return $this->generateItems($keys, time(), $this->createCacheItem);
+ return $this->generateItems($keys, microtime(true), $this->createCacheItem);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItems(array $keys)
{
@@ -102,6 +114,8 @@ public function deleteItems(array $keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function save(CacheItemInterface $item)
{
@@ -113,37 +127,32 @@ public function save(CacheItemInterface $item)
$value = $item["\0*\0value"];
$expiry = $item["\0*\0expiry"];
- if (0 === $expiry) {
- $expiry = \PHP_INT_MAX;
- }
+ if (null !== $expiry) {
+ if (!$expiry) {
+ $expiry = \PHP_INT_MAX;
+ } elseif ($expiry <= microtime(true)) {
+ $this->deleteItem($key);
- if (null !== $expiry && $expiry <= time()) {
- $this->deleteItem($key);
-
- return true;
- }
- if ($this->storeSerialized) {
- try {
- $value = serialize($value);
- } catch (\Exception $e) {
- $type = \is_object($value) ? \get_class($value) : \gettype($value);
- CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]);
-
- return false;
+ return true;
}
}
+ if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
+ return false;
+ }
if (null === $expiry && 0 < $this->defaultLifetime) {
- $expiry = time() + $this->defaultLifetime;
+ $expiry = microtime(true) + $this->defaultLifetime;
}
$this->values[$key] = $value;
- $this->expiries[$key] = null !== $expiry ? $expiry : \PHP_INT_MAX;
+ $this->expiries[$key] = $expiry ?? \PHP_INT_MAX;
return true;
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function saveDeferred(CacheItemInterface $item)
{
@@ -152,9 +161,19 @@ public function saveDeferred(CacheItemInterface $item)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
return true;
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
+ }
}
diff --git a/vendor/symfony/cache/Adapter/ChainAdapter.php b/vendor/symfony/cache/Adapter/ChainAdapter.php
index fdb28846..57fb096b 100644
--- a/vendor/symfony/cache/Adapter/ChainAdapter.php
+++ b/vendor/symfony/cache/Adapter/ChainAdapter.php
@@ -17,6 +17,9 @@
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
/**
* Chains several adapters together.
@@ -26,8 +29,10 @@
*
* @author Kévin Dunglas
*/
-class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
+class ChainAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
+ use ContractsTrait;
+
private $adapters = [];
private $adapterCount;
private $syncItem;
@@ -36,7 +41,7 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn
* @param CacheItemPoolInterface[] $adapters The ordered list of adapters used to fetch cached items
* @param int $defaultLifetime The default lifetime of items propagated from lower adapters to upper ones
*/
- public function __construct(array $adapters, $defaultLifetime = 0)
+ public function __construct(array $adapters, int $defaultLifetime = 0)
{
if (!$adapters) {
throw new InvalidArgumentException('At least one adapter must be specified.');
@@ -46,7 +51,7 @@ public function __construct(array $adapters, $defaultLifetime = 0)
if (!$adapter instanceof CacheItemPoolInterface) {
throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($adapter), CacheItemPoolInterface::class));
}
- if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
+ if (\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && $adapter instanceof ApcuAdapter && !filter_var(\ini_get('apc.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
continue; // skip putting APCu in the chain when the backend is disabled
}
@@ -59,11 +64,18 @@ public function __construct(array $adapters, $defaultLifetime = 0)
$this->adapterCount = \count($this->adapters);
$this->syncItem = \Closure::bind(
- static function ($sourceItem, $item) use ($defaultLifetime) {
+ static function ($sourceItem, $item, $sourceMetadata = null) use ($defaultLifetime) {
+ $sourceItem->isTaggable = false;
+ $sourceMetadata = $sourceMetadata ?? $sourceItem->metadata;
+ unset($sourceMetadata[CacheItem::METADATA_TAGS]);
+
$item->value = $sourceItem->value;
$item->isHit = $sourceItem->isHit;
+ $item->metadata = $item->newMetadata = $sourceItem->metadata = $sourceMetadata;
- if (0 < $defaultLifetime) {
+ if (isset($item->metadata[CacheItem::METADATA_EXPIRY])) {
+ $item->expiresAt(\DateTime::createFromFormat('U.u', sprintf('%.6F', $item->metadata[CacheItem::METADATA_EXPIRY])));
+ } elseif (0 < $defaultLifetime) {
$item->expiresAfter($defaultLifetime);
}
@@ -74,6 +86,43 @@ static function ($sourceItem, $item) use ($defaultLifetime) {
);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $doSave = true;
+ $callback = static function (CacheItem $item, bool &$save) use ($callback, &$doSave) {
+ $value = $callback($item, $save);
+ $doSave = $save;
+
+ return $value;
+ };
+
+ $lastItem = null;
+ $i = 0;
+ $wrap = function (CacheItem $item = null, bool &$save = true) use ($key, $callback, $beta, &$wrap, &$i, &$doSave, &$lastItem, &$metadata) {
+ $adapter = $this->adapters[$i];
+ if (isset($this->adapters[++$i])) {
+ $callback = $wrap;
+ $beta = \INF === $beta ? \INF : 0;
+ }
+ if ($adapter instanceof CacheInterface) {
+ $value = $adapter->get($key, $callback, $beta, $metadata);
+ } else {
+ $value = $this->doGet($adapter, $key, $callback, $beta, $metadata);
+ }
+ if (null !== $item) {
+ ($this->syncItem)($lastItem = $lastItem ?? $item, $item, $metadata);
+ }
+ $save = $doSave;
+
+ return $value;
+ };
+
+ return $wrap();
+ }
+
/**
* {@inheritdoc}
*/
@@ -107,12 +156,12 @@ public function getItems(array $keys = [])
return $this->generateItems($this->adapters[0]->getItems($keys), 0);
}
- private function generateItems($items, $adapterIndex)
+ private function generateItems(iterable $items, int $adapterIndex)
{
$missing = [];
$misses = [];
$nextAdapterIndex = $adapterIndex + 1;
- $nextAdapter = isset($this->adapters[$nextAdapterIndex]) ? $this->adapters[$nextAdapterIndex] : null;
+ $nextAdapter = $this->adapters[$nextAdapterIndex] ?? null;
foreach ($items as $k => $item) {
if (!$nextAdapter || $item->isHit()) {
@@ -140,6 +189,8 @@ private function generateItems($items, $adapterIndex)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function hasItem($key)
{
@@ -154,14 +205,23 @@ public function hasItem($key)
/**
* {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
*/
- public function clear()
+ public function clear(/* string $prefix = '' */)
{
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
$cleared = true;
$i = $this->adapterCount;
while ($i--) {
- $cleared = $this->adapters[$i]->clear() && $cleared;
+ if ($this->adapters[$i] instanceof AdapterInterface) {
+ $cleared = $this->adapters[$i]->clear($prefix) && $cleared;
+ } else {
+ $cleared = $this->adapters[$i]->clear() && $cleared;
+ }
}
return $cleared;
@@ -169,6 +229,8 @@ public function clear()
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItem($key)
{
@@ -184,6 +246,8 @@ public function deleteItem($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItems(array $keys)
{
@@ -199,6 +263,8 @@ public function deleteItems(array $keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function save(CacheItemInterface $item)
{
@@ -214,6 +280,8 @@ public function save(CacheItemInterface $item)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function saveDeferred(CacheItemInterface $item)
{
@@ -229,6 +297,8 @@ public function saveDeferred(CacheItemInterface $item)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
@@ -264,7 +334,7 @@ public function prune()
public function reset()
{
foreach ($this->adapters as $adapter) {
- if ($adapter instanceof ResettableInterface) {
+ if ($adapter instanceof ResetInterface) {
$adapter->reset();
}
}
diff --git a/vendor/symfony/cache/Adapter/DoctrineAdapter.php b/vendor/symfony/cache/Adapter/DoctrineAdapter.php
index 8081d7dc..75ae4cb7 100644
--- a/vendor/symfony/cache/Adapter/DoctrineAdapter.php
+++ b/vendor/symfony/cache/Adapter/DoctrineAdapter.php
@@ -18,11 +18,7 @@ class DoctrineAdapter extends AbstractAdapter
{
use DoctrineTrait;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- */
- public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0)
+ public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
{
parent::__construct('', $defaultLifetime);
$this->provider = $provider;
diff --git a/vendor/symfony/cache/Adapter/FilesystemAdapter.php b/vendor/symfony/cache/Adapter/FilesystemAdapter.php
index d071964e..7185dd48 100644
--- a/vendor/symfony/cache/Adapter/FilesystemAdapter.php
+++ b/vendor/symfony/cache/Adapter/FilesystemAdapter.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\Cache\Adapter;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\FilesystemTrait;
@@ -18,13 +20,9 @@ class FilesystemAdapter extends AbstractAdapter implements PruneableInterface
{
use FilesystemTrait;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $directory
- */
- public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
{
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
parent::__construct('', $defaultLifetime);
$this->init($namespace, $directory);
}
diff --git a/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
new file mode 100644
index 00000000..6dccbf08
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/FilesystemTagAwareAdapter.php
@@ -0,0 +1,239 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\Traits\FilesystemTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a symlink, and lookup on invalidation calls.
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ */
+class FilesystemTagAwareAdapter extends AbstractTagAwareAdapter implements PruneableInterface
+{
+ use FilesystemTrait {
+ doClear as private doClearCache;
+ doSave as private doSaveCache;
+ }
+
+ /**
+ * Folder used for tag symlinks.
+ */
+ private const TAG_FOLDER = 'tags';
+
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = new TagAwareMarshaller($marshaller);
+ parent::__construct('', $defaultLifetime);
+ $this->init($namespace, $directory);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear($namespace)
+ {
+ $ok = $this->doClearCache($namespace);
+
+ if ('' !== $namespace) {
+ return $ok;
+ }
+
+ set_error_handler(static function () {});
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ try {
+ foreach ($this->scanHashDir($this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR) as $dir) {
+ if (rename($dir, $renamed = substr_replace($dir, bin2hex(random_bytes(4)), -8))) {
+ $dir = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $dir .= \DIRECTORY_SEPARATOR;
+ $renamed = null;
+ }
+
+ for ($i = 0; $i < 38; ++$i) {
+ if (!file_exists($dir.$chars[$i])) {
+ continue;
+ }
+ for ($j = 0; $j < 38; ++$j) {
+ if (!file_exists($d = $dir.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j])) {
+ continue;
+ }
+ foreach (scandir($d, \SCANDIR_SORT_NONE) ?: [] as $link) {
+ if ('.' !== $link && '..' !== $link && (null !== $renamed || !realpath($d.\DIRECTORY_SEPARATOR.$link))) {
+ unlink($d.\DIRECTORY_SEPARATOR.$link);
+ }
+ }
+ null === $renamed ?: rmdir($d);
+ }
+ null === $renamed ?: rmdir($dir.$chars[$i]);
+ }
+ null === $renamed ?: rmdir($renamed);
+ }
+ } finally {
+ restore_error_handler();
+ }
+
+ return $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime, array $addTagData = [], array $removeTagData = []): array
+ {
+ $failed = $this->doSaveCache($values, $lifetime);
+
+ // Add Tags as symlinks
+ foreach ($addTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ $file = $this->getFile($id);
+
+ if (!@symlink($file, $tagLink = $this->getFile($id, true, $tagFolder)) && !is_link($tagLink)) {
+ @unlink($file);
+ $failed[] = $id;
+ }
+ }
+ }
+
+ // Unlink removed Tags
+ foreach ($removeTagData as $tagId => $ids) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($ids as $id) {
+ if ($failed && \in_array($id, $failed, true)) {
+ continue;
+ }
+
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ foreach ($ids as $id) {
+ $file = $this->getFile($id);
+ if (!file_exists($file) || !$h = @fopen($file, 'r')) {
+ continue;
+ }
+
+ if ((\PHP_VERSION_ID >= 70300 || '\\' !== \DIRECTORY_SEPARATOR) && !@unlink($file)) {
+ fclose($h);
+ continue;
+ }
+
+ $meta = explode("\n", fread($h, 4096), 3)[2] ?? '';
+
+ // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (13 < \strlen($meta) && "\x9D" === $meta[0] && "\0" === $meta[5] && "\x5F" === $meta[9]) {
+ $meta[9] = "\0";
+ $tagLen = unpack('Nlen', $meta, 9)['len'];
+ $meta = substr($meta, 13, $tagLen);
+
+ if (0 < $tagLen -= \strlen($meta)) {
+ $meta .= fread($h, $tagLen);
+ }
+
+ try {
+ yield $id => '' === $meta ? [] : $this->marshaller->unmarshall($meta);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+
+ fclose($h);
+
+ if (\PHP_VERSION_ID < 70300 && '\\' === \DIRECTORY_SEPARATOR) {
+ @unlink($file);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ foreach ($tagData as $tagId => $idList) {
+ $tagFolder = $this->getTagFolder($tagId);
+ foreach ($idList as $id) {
+ @unlink($this->getFile($id, false, $tagFolder));
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ foreach ($tagIds as $tagId) {
+ if (!file_exists($tagFolder = $this->getTagFolder($tagId))) {
+ continue;
+ }
+
+ set_error_handler(static function () {});
+
+ try {
+ if (rename($tagFolder, $renamed = substr_replace($tagFolder, bin2hex(random_bytes(4)), -9))) {
+ $tagFolder = $renamed.\DIRECTORY_SEPARATOR;
+ } else {
+ $renamed = null;
+ }
+
+ foreach ($this->scanHashDir($tagFolder) as $itemLink) {
+ unlink(realpath($itemLink) ?: $itemLink);
+ unlink($itemLink);
+ }
+
+ if (null === $renamed) {
+ continue;
+ }
+
+ $chars = '+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
+
+ for ($i = 0; $i < 38; ++$i) {
+ for ($j = 0; $j < 38; ++$j) {
+ rmdir($tagFolder.$chars[$i].\DIRECTORY_SEPARATOR.$chars[$j]);
+ }
+ rmdir($tagFolder.$chars[$i]);
+ }
+ rmdir($renamed);
+ } finally {
+ restore_error_handler();
+ }
+ }
+
+ return true;
+ }
+
+ private function getTagFolder(string $tagId): string
+ {
+ return $this->getFile($tagId, false, $this->directory.self::TAG_FOLDER.\DIRECTORY_SEPARATOR).\DIRECTORY_SEPARATOR;
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/MemcachedAdapter.php b/vendor/symfony/cache/Adapter/MemcachedAdapter.php
index 5637141a..b678bb5d 100644
--- a/vendor/symfony/cache/Adapter/MemcachedAdapter.php
+++ b/vendor/symfony/cache/Adapter/MemcachedAdapter.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\Cache\Adapter;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\Traits\MemcachedTrait;
class MemcachedAdapter extends AbstractAdapter
@@ -29,8 +30,8 @@ class MemcachedAdapter extends AbstractAdapter
*
* Using a MemcachedAdapter as a pure items store is fine.
*/
- public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0)
+ public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
- $this->init($client, $namespace, $defaultLifetime);
+ $this->init($client, $namespace, $defaultLifetime, $marshaller);
}
}
diff --git a/vendor/symfony/cache/Adapter/NullAdapter.php b/vendor/symfony/cache/Adapter/NullAdapter.php
index c81a1cd6..3c2979bd 100644
--- a/vendor/symfony/cache/Adapter/NullAdapter.php
+++ b/vendor/symfony/cache/Adapter/NullAdapter.php
@@ -13,11 +13,12 @@
use Psr\Cache\CacheItemInterface;
use Symfony\Component\Cache\CacheItem;
+use Symfony\Contracts\Cache\CacheInterface;
/**
* @author Titouan Galopin
*/
-class NullAdapter implements AdapterInterface
+class NullAdapter implements AdapterInterface, CacheInterface
{
private $createCacheItem;
@@ -36,6 +37,16 @@ function ($key) {
);
}
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ $save = true;
+
+ return $callback(($this->createCacheItem)($key), $save);
+ }
+
/**
* {@inheritdoc}
*/
@@ -56,6 +67,8 @@ public function getItems(array $keys = [])
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function hasItem($key)
{
@@ -64,14 +77,20 @@ public function hasItem($key)
/**
* {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
*/
- public function clear()
+ public function clear(/* string $prefix = '' */)
{
return true;
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItem($key)
{
@@ -80,6 +99,8 @@ public function deleteItem($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItems(array $keys)
{
@@ -88,26 +109,40 @@ public function deleteItems(array $keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function save(CacheItemInterface $item)
{
- return false;
+ return true;
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function saveDeferred(CacheItemInterface $item)
{
- return false;
+ return true;
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
- return false;
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function delete(string $key): bool
+ {
+ return $this->deleteItem($key);
}
private function generateItems(array $keys)
diff --git a/vendor/symfony/cache/Adapter/PdoAdapter.php b/vendor/symfony/cache/Adapter/PdoAdapter.php
index 59038679..d118736a 100644
--- a/vendor/symfony/cache/Adapter/PdoAdapter.php
+++ b/vendor/symfony/cache/Adapter/PdoAdapter.php
@@ -13,6 +13,7 @@
use Doctrine\DBAL\Connection;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\PdoTrait;
@@ -27,6 +28,9 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
* a Doctrine DBAL Connection or a DSN string that will be used to
* lazy-connect to the database when the cache is actually used.
*
+ * When a Doctrine DBAL Connection is passed, the cache table is created
+ * automatically when possible. Otherwise, use the createTable() method.
+ *
* List of available options:
* * db_table: The name of the table [default: cache_items]
* * db_id_col: The column where to store the cache id [default: item_id]
@@ -37,17 +41,14 @@ class PdoAdapter extends AbstractAdapter implements PruneableInterface
* * db_password: The password when lazy-connect [default: '']
* * db_connection_options: An array of driver-specific connection options [default: []]
*
- * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null
- * @param string $namespace
- * @param int $defaultLifetime
- * @param array $options An associative array of options
+ * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null
*
* @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
* @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
* @throws InvalidArgumentException When namespace contains invalid characters
*/
- public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = [])
+ public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
{
- $this->init($connOrDsn, $namespace, $defaultLifetime, $options);
+ $this->init($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller);
}
}
diff --git a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
index 47a259c1..bdce6e1a 100644
--- a/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
+++ b/vendor/symfony/cache/Adapter/PhpArrayAdapter.php
@@ -17,7 +17,9 @@
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
use Symfony\Component\Cache\Traits\PhpArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
/**
* Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
@@ -26,8 +28,9 @@
* @author Titouan Galopin
* @author Nicolas Grekas
*/
-class PhpArrayAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
+class PhpArrayAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
+ use ContractsTrait;
use PhpArrayTrait;
private $createCacheItem;
@@ -36,11 +39,10 @@ class PhpArrayAdapter implements AdapterInterface, PruneableInterface, Resettabl
* @param string $file The PHP file were values are cached
* @param AdapterInterface $fallbackPool A pool to fallback on when an item is not hit
*/
- public function __construct($file, AdapterInterface $fallbackPool)
+ public function __construct(string $file, AdapterInterface $fallbackPool)
{
$this->file = $file;
$this->pool = $fallbackPool;
- $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN);
$this->createCacheItem = \Closure::bind(
static function ($key, $value, $isHit) {
$item = new CacheItem();
@@ -56,9 +58,7 @@ static function ($key, $value, $isHit) {
}
/**
- * This adapter should only be used on PHP 7.0+ to take advantage of how PHP
- * stores arrays in its latest versions. This factory method decorates the given
- * fallback pool with this adapter only if the current PHP version is supported.
+ * This adapter takes advantage of how PHP stores arrays in its latest versions.
*
* @param string $file The PHP file were values are cached
* @param CacheItemPoolInterface $fallbackPool A pool to fallback on when an item is not hit
@@ -67,15 +67,44 @@ static function ($key, $value, $isHit) {
*/
public static function create($file, CacheItemPoolInterface $fallbackPool)
{
- if (\PHP_VERSION_ID >= 70000) {
- if (!$fallbackPool instanceof AdapterInterface) {
- $fallbackPool = new ProxyAdapter($fallbackPool);
+ if (!$fallbackPool instanceof AdapterInterface) {
+ $fallbackPool = new ProxyAdapter($fallbackPool);
+ }
+
+ return new static($file, $fallbackPool);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (null === $this->values) {
+ $this->initialize();
+ }
+ if (!isset($this->keys[$key])) {
+ get_from_pool:
+ if ($this->pool instanceof CacheInterface) {
+ return $this->pool->get($key, $callback, $beta, $metadata);
}
- return new static($file, $fallbackPool);
+ return $this->doGet($this->pool, $key, $callback, $beta, $metadata);
}
+ $value = $this->values[$this->keys[$key]];
- return $fallbackPool;
+ if ('N;' === $value) {
+ return null;
+ }
+ try {
+ if ($value instanceof \Closure) {
+ return $value();
+ }
+ } catch (\Throwable $e) {
+ unset($this->keys[$key]);
+ goto get_from_pool;
+ }
+
+ return $value;
}
/**
@@ -89,23 +118,19 @@ public function getItem($key)
if (null === $this->values) {
$this->initialize();
}
- if (!isset($this->values[$key])) {
+ if (!isset($this->keys[$key])) {
return $this->pool->getItem($key);
}
- $value = $this->values[$key];
+ $value = $this->values[$this->keys[$key]];
$isHit = true;
if ('N;' === $value) {
$value = null;
- } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
+ } elseif ($value instanceof \Closure) {
try {
- $e = null;
- $value = unserialize($value);
- } catch (\Error $e) {
- } catch (\Exception $e) {
- }
- if (null !== $e) {
+ $value = $value();
+ } catch (\Throwable $e) {
$value = null;
$isHit = false;
}
@@ -135,6 +160,8 @@ public function getItems(array $keys = [])
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function hasItem($key)
{
@@ -145,11 +172,13 @@ public function hasItem($key)
$this->initialize();
}
- return isset($this->values[$key]) || $this->pool->hasItem($key);
+ return isset($this->keys[$key]) || $this->pool->hasItem($key);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItem($key)
{
@@ -160,11 +189,13 @@ public function deleteItem($key)
$this->initialize();
}
- return !isset($this->values[$key]) && $this->pool->deleteItem($key);
+ return !isset($this->keys[$key]) && $this->pool->deleteItem($key);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItems(array $keys)
{
@@ -176,7 +207,7 @@ public function deleteItems(array $keys)
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
}
- if (isset($this->values[$key])) {
+ if (isset($this->keys[$key])) {
$deleted = false;
} else {
$fallbackKeys[] = $key;
@@ -195,6 +226,8 @@ public function deleteItems(array $keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function save(CacheItemInterface $item)
{
@@ -202,11 +235,13 @@ public function save(CacheItemInterface $item)
$this->initialize();
}
- return !isset($this->values[$item->getKey()]) && $this->pool->save($item);
+ return !isset($this->keys[$item->getKey()]) && $this->pool->save($item);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function saveDeferred(CacheItemInterface $item)
{
@@ -214,37 +249,34 @@ public function saveDeferred(CacheItemInterface $item)
$this->initialize();
}
- return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item);
+ return !isset($this->keys[$item->getKey()]) && $this->pool->saveDeferred($item);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
return $this->pool->commit();
}
- /**
- * @return \Generator
- */
- private function generateItems(array $keys)
+ private function generateItems(array $keys): \Generator
{
$f = $this->createCacheItem;
$fallbackKeys = [];
foreach ($keys as $key) {
- if (isset($this->values[$key])) {
- $value = $this->values[$key];
+ if (isset($this->keys[$key])) {
+ $value = $this->values[$this->keys[$key]];
if ('N;' === $value) {
yield $key => $f($key, null, true);
- } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
+ } elseif ($value instanceof \Closure) {
try {
- yield $key => $f($key, unserialize($value), true);
- } catch (\Error $e) {
- yield $key => $f($key, null, false);
- } catch (\Exception $e) {
+ yield $key => $f($key, $value(), true);
+ } catch (\Throwable $e) {
yield $key => $f($key, null, false);
}
} else {
@@ -256,9 +288,7 @@ private function generateItems(array $keys)
}
if ($fallbackKeys) {
- foreach ($this->pool->getItems($fallbackKeys) as $key => $item) {
- yield $key => $item;
- }
+ yield from $this->pool->getItems($fallbackKeys);
}
}
diff --git a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
index b56143c2..10938a0a 100644
--- a/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
+++ b/vendor/symfony/cache/Adapter/PhpFilesAdapter.php
@@ -20,22 +20,19 @@ class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface
use PhpFilesTrait;
/**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $directory
+ * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
+ * Doing so is encouraged because it fits perfectly OPcache's memory model.
*
* @throws CacheException if OPcache is not enabled
*/
- public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false)
{
- if (!static::isSupported()) {
- throw new CacheException('OPcache is not enabled.');
- }
+ $this->appendOnly = $appendOnly;
+ self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
parent::__construct('', $defaultLifetime);
$this->init($namespace, $directory);
-
- $e = new \Exception();
- $this->includeHandler = function () use ($e) { throw $e; };
- $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN);
+ $this->includeHandler = static function ($type, $msg, $file, $line) {
+ throw new \ErrorException($msg, 0, $type, $file, $line);
+ };
}
}
diff --git a/vendor/symfony/cache/Adapter/ProxyAdapter.php b/vendor/symfony/cache/Adapter/ProxyAdapter.php
index c89a760e..e006ea01 100644
--- a/vendor/symfony/cache/Adapter/ProxyAdapter.php
+++ b/vendor/symfony/cache/Adapter/ProxyAdapter.php
@@ -16,26 +16,26 @@
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ContractsTrait;
use Symfony\Component\Cache\Traits\ProxyTrait;
+use Symfony\Contracts\Cache\CacheInterface;
/**
* @author Nicolas Grekas
*/
-class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableInterface
+class ProxyAdapter implements AdapterInterface, CacheInterface, PruneableInterface, ResettableInterface
{
+ use ContractsTrait;
use ProxyTrait;
private $namespace;
private $namespaceLen;
private $createCacheItem;
+ private $setInnerItem;
private $poolHash;
private $defaultLifetime;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- */
- public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0)
+ public function __construct(CacheItemPoolInterface $pool, string $namespace = '', int $defaultLifetime = 0)
{
$this->pool = $pool;
$this->poolHash = $poolHash = spl_object_hash($pool);
@@ -46,20 +46,71 @@ public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defa
static function ($key, $innerItem) use ($poolHash) {
$item = new CacheItem();
$item->key = $key;
+
+ if (null === $innerItem) {
+ return $item;
+ }
+
+ $item->value = $v = $innerItem->get();
+ $item->isHit = $innerItem->isHit();
+ $item->innerItem = $innerItem;
$item->poolHash = $poolHash;
- if (null !== $innerItem) {
- $item->value = $innerItem->get();
- $item->isHit = $innerItem->isHit();
- $item->innerItem = $innerItem;
- $innerItem->set(null);
+ // Detect wrapped values that encode for their expiry and creation duration
+ // For compactness, these values are packed in the key of an array using
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (\is_array($v) && 1 === \count($v) && 10 === \strlen($k = (string) array_key_first($v)) && "\x9D" === $k[0] && "\0" === $k[5] && "\x5F" === $k[9]) {
+ $item->value = $v[$k];
+ $v = unpack('Ve/Nc', substr($k, 1, -1));
+ $item->metadata[CacheItem::METADATA_EXPIRY] = $v['e'] + CacheItem::METADATA_EXPIRY_OFFSET;
+ $item->metadata[CacheItem::METADATA_CTIME] = $v['c'];
+ } elseif ($innerItem instanceof CacheItem) {
+ $item->metadata = $innerItem->metadata;
}
+ $innerItem->set(null);
return $item;
},
null,
CacheItem::class
);
+ $this->setInnerItem = \Closure::bind(
+ /**
+ * @param array $item A CacheItem cast to (array); accessing protected properties requires adding the "\0*\0" PHP prefix
+ */
+ static function (CacheItemInterface $innerItem, array $item) {
+ // Tags are stored separately, no need to account for them when considering this item's newly set metadata
+ if (isset(($metadata = $item["\0*\0newMetadata"])[CacheItem::METADATA_TAGS])) {
+ unset($metadata[CacheItem::METADATA_TAGS]);
+ }
+ if ($metadata) {
+ // For compactness, expiry and creation duration are packed in the key of an array, using magic numbers as separators
+ $item["\0*\0value"] = ["\x9D".pack('VN', (int) (0.1 + $metadata[self::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[self::METADATA_CTIME])."\x5F" => $item["\0*\0value"]];
+ }
+ $innerItem->set($item["\0*\0value"]);
+ $innerItem->expiresAt(null !== $item["\0*\0expiry"] ? \DateTime::createFromFormat('U.u', sprintf('%.6F', $item["\0*\0expiry"])) : null);
+ },
+ null,
+ CacheItem::class
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function get(string $key, callable $callback, float $beta = null, array &$metadata = null)
+ {
+ if (!$this->pool instanceof CacheInterface) {
+ return $this->doGet($this, $key, $callback, $beta, $metadata);
+ }
+
+ return $this->pool->get($this->getId($key), function ($innerItem, bool &$save) use ($key, $callback) {
+ $item = ($this->createCacheItem)($key, $innerItem);
+ $item->set($value = $callback($item, $save));
+ ($this->setInnerItem)($innerItem, (array) $item);
+
+ return $value;
+ }, $beta, $metadata);
}
/**
@@ -89,6 +140,8 @@ public function getItems(array $keys = [])
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function hasItem($key)
{
@@ -97,14 +150,26 @@ public function hasItem($key)
/**
* {@inheritdoc}
+ *
+ * @param string $prefix
+ *
+ * @return bool
*/
- public function clear()
+ public function clear(/* string $prefix = '' */)
{
+ $prefix = 0 < \func_num_args() ? (string) func_get_arg(0) : '';
+
+ if ($this->pool instanceof AdapterInterface) {
+ return $this->pool->clear($this->namespace.$prefix);
+ }
+
return $this->pool->clear();
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItem($key)
{
@@ -113,6 +178,8 @@ public function deleteItem($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteItems(array $keys)
{
@@ -127,6 +194,8 @@ public function deleteItems(array $keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function save(CacheItemInterface $item)
{
@@ -135,6 +204,8 @@ public function save(CacheItemInterface $item)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function saveDeferred(CacheItemInterface $item)
{
@@ -143,21 +214,22 @@ public function saveDeferred(CacheItemInterface $item)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function commit()
{
return $this->pool->commit();
}
- private function doSave(CacheItemInterface $item, $method)
+ private function doSave(CacheItemInterface $item, string $method)
{
if (!$item instanceof CacheItem) {
return false;
}
$item = (array) $item;
- $expiry = $item["\0*\0expiry"];
- if (null === $expiry && 0 < $this->defaultLifetime) {
- $expiry = time() + $this->defaultLifetime;
+ if (null === $item["\0*\0expiry"] && 0 < $this->defaultLifetime) {
+ $item["\0*\0expiry"] = microtime(true) + $this->defaultLifetime;
}
if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) {
@@ -171,13 +243,12 @@ private function doSave(CacheItemInterface $item, $method)
$innerItem = $this->pool->getItem($this->namespace.$item["\0*\0key"]);
}
- $innerItem->set($item["\0*\0value"]);
- $innerItem->expiresAt(null !== $expiry ? \DateTime::createFromFormat('U', $expiry) : null);
+ ($this->setInnerItem)($innerItem, $item);
return $this->pool->$method($innerItem);
}
- private function generateItems($items)
+ private function generateItems(iterable $items)
{
$f = $this->createCacheItem;
@@ -190,7 +261,7 @@ private function generateItems($items)
}
}
- private function getId($key)
+ private function getId($key): string
{
CacheItem::validateKey($key);
diff --git a/vendor/symfony/cache/Adapter/Psr16Adapter.php b/vendor/symfony/cache/Adapter/Psr16Adapter.php
new file mode 100644
index 00000000..e959d784
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/Psr16Adapter.php
@@ -0,0 +1,86 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Psr\SimpleCache\CacheInterface;
+use Symfony\Component\Cache\PruneableInterface;
+use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+
+/**
+ * Turns a PSR-16 cache into a PSR-6 one.
+ *
+ * @author Nicolas Grekas
+ */
+class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
+{
+ use ProxyTrait;
+
+ /**
+ * @internal
+ */
+ protected const NS_SEPARATOR = '_';
+
+ private $miss;
+
+ public function __construct(CacheInterface $pool, string $namespace = '', int $defaultLifetime = 0)
+ {
+ parent::__construct($namespace, $defaultLifetime);
+
+ $this->pool = $pool;
+ $this->miss = new \stdClass();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doFetch(array $ids)
+ {
+ foreach ($this->pool->getMultiple($ids, $this->miss) as $key => $value) {
+ if ($this->miss !== $value) {
+ yield $key => $value;
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doHave($id)
+ {
+ return $this->pool->has($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doClear($namespace)
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDelete(array $ids)
+ {
+ return $this->pool->deleteMultiple($ids);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime)
+ {
+ return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/RedisAdapter.php b/vendor/symfony/cache/Adapter/RedisAdapter.php
index c1e17997..eb5950e5 100644
--- a/vendor/symfony/cache/Adapter/RedisAdapter.php
+++ b/vendor/symfony/cache/Adapter/RedisAdapter.php
@@ -11,6 +11,9 @@
namespace Symfony\Component\Cache\Adapter;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
use Symfony\Component\Cache\Traits\RedisTrait;
class RedisAdapter extends AbstractAdapter
@@ -18,12 +21,12 @@ class RedisAdapter extends AbstractAdapter
use RedisTrait;
/**
- * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient The redis client
- * @param string $namespace The default namespace
- * @param int $defaultLifetime The default lifetime
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
*/
- public function __construct($redisClient, $namespace = '', $defaultLifetime = 0)
+ public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
- $this->init($redisClient, $namespace, $defaultLifetime);
+ $this->init($redis, $namespace, $defaultLifetime, $marshaller);
}
}
diff --git a/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
new file mode 100644
index 00000000..fd263da3
--- /dev/null
+++ b/vendor/symfony/cache/Adapter/RedisTagAwareAdapter.php
@@ -0,0 +1,321 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Adapter;
+
+use Predis\Connection\Aggregate\ClusterInterface;
+use Predis\Connection\Aggregate\PredisCluster;
+use Predis\Connection\Aggregate\ReplicationInterface;
+use Predis\Response\ErrorInterface;
+use Predis\Response\Status;
+use Symfony\Component\Cache\CacheItem;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Exception\LogicException;
+use Symfony\Component\Cache\Marshaller\DeflateMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
+use Symfony\Component\Cache\Marshaller\TagAwareMarshaller;
+use Symfony\Component\Cache\Traits\RedisClusterProxy;
+use Symfony\Component\Cache\Traits\RedisProxy;
+use Symfony\Component\Cache\Traits\RedisTrait;
+
+/**
+ * Stores tag id <> cache id relationship as a Redis Set.
+ *
+ * Set (tag relation info) is stored without expiry (non-volatile), while cache always gets an expiry (volatile) even
+ * if not set by caller. Thus if you configure redis with the right eviction policy you can be safe this tag <> cache
+ * relationship survives eviction (cache cleanup when Redis runs out of memory).
+ *
+ * Redis server 2.8+ with any `volatile-*` eviction policy, OR `noeviction` if you're sure memory will NEVER fill up
+ *
+ * Design limitations:
+ * - Max 4 billion cache keys per cache tag as limited by Redis Set datatype.
+ * E.g. If you use a "all" items tag for expiry instead of clear(), that limits you to 4 billion cache items also.
+ *
+ * @see https://redis.io/topics/lru-cache#eviction-policies Documentation for Redis eviction policies.
+ * @see https://redis.io/topics/data-types#sets Documentation for Redis Set datatype.
+ *
+ * @author Nicolas Grekas
+ * @author André Rømcke
+ */
+class RedisTagAwareAdapter extends AbstractTagAwareAdapter
+{
+ use RedisTrait;
+
+ /**
+ * On cache items without a lifetime set, we set it to 100 days. This is to make sure cache items are
+ * preferred to be evicted over tag Sets, if eviction policy is configured according to requirements.
+ */
+ private const DEFAULT_CACHE_TTL = 8640000;
+
+ /**
+ * @var string|null detected eviction policy used on Redis server
+ */
+ private $redisEvictionPolicy;
+ private $namespace;
+
+ /**
+ * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy|RedisClusterProxy $redis The redis client
+ * @param string $namespace The default namespace
+ * @param int $defaultLifetime The default lifetime
+ */
+ public function __construct($redis, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
+ {
+ if ($redis instanceof \Predis\ClientInterface && $redis->getConnection() instanceof ClusterInterface && !$redis->getConnection() instanceof PredisCluster) {
+ throw new InvalidArgumentException(sprintf('Unsupported Predis cluster connection: only "%s" is, "%s" given.', PredisCluster::class, \get_class($redis->getConnection())));
+ }
+
+ if (\defined('Redis::OPT_COMPRESSION') && ($redis instanceof \Redis || $redis instanceof \RedisArray || $redis instanceof \RedisCluster)) {
+ $compression = $redis->getOption(\Redis::OPT_COMPRESSION);
+
+ foreach (\is_array($compression) ? $compression : [$compression] as $c) {
+ if (\Redis::COMPRESSION_NONE !== $c) {
+ throw new InvalidArgumentException(sprintf('phpredis compression must be disabled when using "%s", use "%s" instead.', static::class, DeflateMarshaller::class));
+ }
+ }
+ }
+
+ $this->init($redis, $namespace, $defaultLifetime, new TagAwareMarshaller($marshaller));
+ $this->namespace = $namespace;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doSave(array $values, int $lifetime, array $addTagData = [], array $delTagData = []): array
+ {
+ $eviction = $this->getRedisEvictionPolicy();
+ if ('noeviction' !== $eviction && !str_starts_with($eviction, 'volatile-')) {
+ throw new LogicException(sprintf('Redis maxmemory-policy setting "%s" is *not* supported by RedisTagAwareAdapter, use "noeviction" or "volatile-*" eviction policies.', $eviction));
+ }
+
+ // serialize values
+ if (!$serialized = $this->marshaller->marshall($values, $failed)) {
+ return $failed;
+ }
+
+ // While pipeline isn't supported on RedisCluster, other setups will at least benefit from doing this in one op
+ $results = $this->pipeline(static function () use ($serialized, $lifetime, $addTagData, $delTagData, $failed) {
+ // Store cache items, force a ttl if none is set, as there is no MSETEX we need to set each one
+ foreach ($serialized as $id => $value) {
+ yield 'setEx' => [
+ $id,
+ 0 >= $lifetime ? self::DEFAULT_CACHE_TTL : $lifetime,
+ $value,
+ ];
+ }
+
+ // Add and Remove Tags
+ foreach ($addTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sAdd' => array_merge([$tagId], $ids);
+ }
+ }
+
+ foreach ($delTagData as $tagId => $ids) {
+ if (!$failed || $ids = array_diff($ids, $failed)) {
+ yield 'sRem' => array_merge([$tagId], $ids);
+ }
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ // Skip results of SADD/SREM operations, they'll be 1 or 0 depending on if set value already existed or not
+ if (is_numeric($result)) {
+ continue;
+ }
+ // setEx results
+ if (true !== $result && (!$result instanceof Status || Status::get('OK') !== $result)) {
+ $failed[] = $id;
+ }
+ }
+
+ return $failed;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteYieldTags(array $ids): iterable
+ {
+ $lua = <<<'EOLUA'
+ local v = redis.call('GET', KEYS[1])
+ redis.call('DEL', KEYS[1])
+
+ if not v or v:len() <= 13 or v:byte(1) ~= 0x9D or v:byte(6) ~= 0 or v:byte(10) ~= 0x5F then
+ return ''
+ end
+
+ return v:sub(14, 13 + v:byte(13) + v:byte(12) * 256 + v:byte(11) * 65536)
+EOLUA;
+
+ $results = $this->pipeline(function () use ($ids, $lua) {
+ foreach ($ids as $id) {
+ yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id] : [$lua, [$id], 1];
+ }
+ });
+
+ foreach ($results as $id => $result) {
+ if ($result instanceof \RedisException || $result instanceof ErrorInterface) {
+ CacheItem::log($this->logger, 'Failed to delete key "{key}": '.$result->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $result]);
+
+ continue;
+ }
+
+ try {
+ yield $id => !\is_string($result) || '' === $result ? [] : $this->marshaller->unmarshall($result);
+ } catch (\Exception $e) {
+ yield $id => [];
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doDeleteTagRelations(array $tagData): bool
+ {
+ $results = $this->pipeline(static function () use ($tagData) {
+ foreach ($tagData as $tagId => $idList) {
+ array_unshift($idList, $tagId);
+ yield 'sRem' => $idList;
+ }
+ });
+ foreach ($results as $result) {
+ // no-op
+ }
+
+ return true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function doInvalidate(array $tagIds): bool
+ {
+ // This script scans the set of items linked to tag: it empties the set
+ // and removes the linked items. When the set is still not empty after
+ // the scan, it means we're in cluster mode and that the linked items
+ // are on other nodes: we move the links to a temporary set and we
+ // garbage collect that set from the client side.
+
+ $lua = <<<'EOLUA'
+ redis.replicate_commands()
+
+ local cursor = '0'
+ local id = KEYS[1]
+ repeat
+ local result = redis.call('SSCAN', id, cursor, 'COUNT', 5000);
+ cursor = result[1];
+ local rems = {}
+
+ for _, v in ipairs(result[2]) do
+ local ok, _ = pcall(redis.call, 'DEL', ARGV[1]..v)
+ if ok then
+ table.insert(rems, v)
+ end
+ end
+ if 0 < #rems then
+ redis.call('SREM', id, unpack(rems))
+ end
+ until '0' == cursor;
+
+ redis.call('SUNIONSTORE', '{'..id..'}'..id, id)
+ redis.call('DEL', id)
+
+ return redis.call('SSCAN', '{'..id..'}'..id, '0', 'COUNT', 5000)
+EOLUA;
+
+ $results = $this->pipeline(function () use ($tagIds, $lua) {
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ $prefix = $this->redis->getOptions()->prefix ? $this->redis->getOptions()->prefix->getPrefix() : '';
+ } elseif (\is_array($prefix = $this->redis->getOption(\Redis::OPT_PREFIX) ?? '')) {
+ $prefix = current($prefix);
+ }
+
+ foreach ($tagIds as $id) {
+ yield 'eval' => $this->redis instanceof \Predis\ClientInterface ? [$lua, 1, $id, $prefix] : [$lua, [$id, $prefix], 1];
+ }
+ });
+
+ $lua = <<<'EOLUA'
+ redis.replicate_commands()
+
+ local id = KEYS[1]
+ local cursor = table.remove(ARGV)
+ redis.call('SREM', '{'..id..'}'..id, unpack(ARGV))
+
+ return redis.call('SSCAN', '{'..id..'}'..id, cursor, 'COUNT', 5000)
+EOLUA;
+
+ $success = true;
+ foreach ($results as $id => $values) {
+ if ($values instanceof \RedisException || $values instanceof ErrorInterface) {
+ CacheItem::log($this->logger, 'Failed to invalidate key "{key}": '.$values->getMessage(), ['key' => substr($id, \strlen($this->namespace)), 'exception' => $values]);
+ $success = false;
+
+ continue;
+ }
+
+ [$cursor, $ids] = $values;
+
+ while ($ids || '0' !== $cursor) {
+ $this->doDelete($ids);
+
+ $evalArgs = [$id, $cursor];
+ array_splice($evalArgs, 1, 0, $ids);
+
+ if ($this->redis instanceof \Predis\ClientInterface) {
+ array_unshift($evalArgs, $lua, 1);
+ } else {
+ $evalArgs = [$lua, $evalArgs, 1];
+ }
+
+ $results = $this->pipeline(function () use ($evalArgs) {
+ yield 'eval' => $evalArgs;
+ });
+
+ foreach ($results as [$cursor, $ids]) {
+ // no-op
+ }
+ }
+ }
+
+ return $success;
+ }
+
+ private function getRedisEvictionPolicy(): string
+ {
+ if (null !== $this->redisEvictionPolicy) {
+ return $this->redisEvictionPolicy;
+ }
+
+ $hosts = $this->getHosts();
+ $host = reset($hosts);
+ if ($host instanceof \Predis\Client && $host->getConnection() instanceof ReplicationInterface) {
+ // Predis supports info command only on the master in replication environments
+ $hosts = [$host->getClientFor('master')];
+ }
+
+ foreach ($hosts as $host) {
+ $info = $host->info('Memory');
+
+ if ($info instanceof ErrorInterface) {
+ continue;
+ }
+
+ $info = $info['Memory'] ?? $info;
+
+ return $this->redisEvictionPolicy = $info['maxmemory_policy'];
+ }
+
+ return $this->redisEvictionPolicy = '';
+ }
+}
diff --git a/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php b/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php
index d3d0ede6..5f14a85b 100644
--- a/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php
+++ b/vendor/symfony/cache/Adapter/SimpleCacheAdapter.php
@@ -11,73 +11,11 @@
namespace Symfony\Component\Cache\Adapter;
-use Psr\SimpleCache\CacheInterface;
-use Symfony\Component\Cache\PruneableInterface;
-use Symfony\Component\Cache\Traits\ProxyTrait;
+@trigger_error(sprintf('The "%s" class is @deprecated since Symfony 4.3, use "Psr16Adapter" instead.', SimpleCacheAdapter::class), \E_USER_DEPRECATED);
/**
- * @author Nicolas Grekas
@@ -39,7 +44,7 @@ public function prune()
*/
public function reset()
{
- if ($this->pool instanceof ResettableInterface) {
+ if ($this->pool instanceof ResetInterface) {
$this->pool->reset();
}
$this->setNamespace($this->getNamespace());
@@ -47,6 +52,8 @@ public function reset()
/**
* {@inheritdoc}
+ *
+ * @return mixed
*/
protected function doFetch($id)
{
@@ -57,6 +64,8 @@ protected function doFetch($id)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
protected function doContains($id)
{
@@ -65,6 +74,8 @@ protected function doContains($id)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
protected function doSave($id, $data, $lifeTime = 0)
{
@@ -79,6 +90,8 @@ protected function doSave($id, $data, $lifeTime = 0)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
protected function doDelete($id)
{
@@ -87,6 +100,8 @@ protected function doDelete($id)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
protected function doFlush()
{
@@ -95,6 +110,8 @@ protected function doFlush()
/**
* {@inheritdoc}
+ *
+ * @return array|null
*/
protected function doGetStats()
{
diff --git a/vendor/symfony/cache/Exception/CacheException.php b/vendor/symfony/cache/Exception/CacheException.php
index e87b2db8..d2e975b2 100644
--- a/vendor/symfony/cache/Exception/CacheException.php
+++ b/vendor/symfony/cache/Exception/CacheException.php
@@ -14,6 +14,12 @@
use Psr\Cache\CacheException as Psr6CacheInterface;
use Psr\SimpleCache\CacheException as SimpleCacheInterface;
-class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface
-{
+if (interface_exists(SimpleCacheInterface::class)) {
+ class CacheException extends \Exception implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class CacheException extends \Exception implements Psr6CacheInterface
+ {
+ }
}
diff --git a/vendor/symfony/cache/Exception/InvalidArgumentException.php b/vendor/symfony/cache/Exception/InvalidArgumentException.php
index 828bf3ed..7f9584a2 100644
--- a/vendor/symfony/cache/Exception/InvalidArgumentException.php
+++ b/vendor/symfony/cache/Exception/InvalidArgumentException.php
@@ -14,6 +14,12 @@
use Psr\Cache\InvalidArgumentException as Psr6CacheInterface;
use Psr\SimpleCache\InvalidArgumentException as SimpleCacheInterface;
-class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface
-{
+if (interface_exists(SimpleCacheInterface::class)) {
+ class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class InvalidArgumentException extends \InvalidArgumentException implements Psr6CacheInterface
+ {
+ }
}
diff --git a/vendor/symfony/cache/Exception/LogicException.php b/vendor/symfony/cache/Exception/LogicException.php
new file mode 100644
index 00000000..9ffa7ed6
--- /dev/null
+++ b/vendor/symfony/cache/Exception/LogicException.php
@@ -0,0 +1,25 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Exception;
+
+use Psr\Cache\CacheException as Psr6CacheInterface;
+use Psr\SimpleCache\CacheException as SimpleCacheInterface;
+
+if (interface_exists(SimpleCacheInterface::class)) {
+ class LogicException extends \LogicException implements Psr6CacheInterface, SimpleCacheInterface
+ {
+ }
+} else {
+ class LogicException extends \LogicException implements Psr6CacheInterface
+ {
+ }
+}
diff --git a/vendor/symfony/cache/LICENSE b/vendor/symfony/cache/LICENSE
index a7ec7080..7fa95390 100644
--- a/vendor/symfony/cache/LICENSE
+++ b/vendor/symfony/cache/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2016-2020 Fabien Potencier
+Copyright (c) 2016-2022 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/symfony/cache/LockRegistry.php b/vendor/symfony/cache/LockRegistry.php
new file mode 100644
index 00000000..26574f10
--- /dev/null
+++ b/vendor/symfony/cache/LockRegistry.php
@@ -0,0 +1,161 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Cache\ItemInterface;
+
+/**
+ * LockRegistry is used internally by existing adapters to protect against cache stampede.
+ *
+ * It does so by wrapping the computation of items in a pool of locks.
+ * Foreach each apps, there can be at most 20 concurrent processes that
+ * compute items at the same time and only one per cache-key.
+ *
+ * @author Nicolas Grekas
+ */
+final class LockRegistry
+{
+ private static $openedFiles = [];
+ private static $lockedFiles;
+ private static $signalingException;
+ private static $signalingCallback;
+
+ /**
+ * The number of items in this list controls the max number of concurrent processes.
+ */
+ private static $files = [
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AbstractTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'AdapterInterface.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ApcuAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ArrayAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ChainAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'DoctrineAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'FilesystemTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'MemcachedAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'NullAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PdoAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpArrayAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'PhpFilesAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'ProxyAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'Psr16Adapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'RedisTagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'SimpleCacheAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TagAwareAdapterInterface.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableAdapter.php',
+ __DIR__.\DIRECTORY_SEPARATOR.'Adapter'.\DIRECTORY_SEPARATOR.'TraceableTagAwareAdapter.php',
+ ];
+
+ /**
+ * Defines a set of existing files that will be used as keys to acquire locks.
+ *
+ * @return array The previously defined set of files
+ */
+ public static function setFiles(array $files): array
+ {
+ $previousFiles = self::$files;
+ self::$files = $files;
+
+ foreach (self::$openedFiles as $file) {
+ if ($file) {
+ flock($file, \LOCK_UN);
+ fclose($file);
+ }
+ }
+ self::$openedFiles = self::$lockedFiles = [];
+
+ return $previousFiles;
+ }
+
+ public static function compute(callable $callback, ItemInterface $item, bool &$save, CacheInterface $pool, \Closure $setMetadata = null, LoggerInterface $logger = null)
+ {
+ if ('\\' === \DIRECTORY_SEPARATOR && null === self::$lockedFiles) {
+ // disable locking on Windows by default
+ self::$files = self::$lockedFiles = [];
+ }
+
+ $key = self::$files ? abs(crc32($item->getKey())) % \count(self::$files) : -1;
+
+ if ($key < 0 || self::$lockedFiles || !$lock = self::open($key)) {
+ return $callback($item, $save);
+ }
+
+ self::$signalingException ?? self::$signalingException = unserialize("O:9:\"Exception\":1:{s:16:\"\0Exception\0trace\";a:0:{}}");
+ self::$signalingCallback ?? self::$signalingCallback = function () { throw self::$signalingException; };
+
+ while (true) {
+ try {
+ // race to get the lock in non-blocking mode
+ $locked = flock($lock, \LOCK_EX | \LOCK_NB, $wouldBlock);
+
+ if ($locked || !$wouldBlock) {
+ $logger && $logger->info(sprintf('Lock %s, now computing item "{key}"', $locked ? 'acquired' : 'not supported'), ['key' => $item->getKey()]);
+ self::$lockedFiles[$key] = true;
+
+ $value = $callback($item, $save);
+
+ if ($save) {
+ if ($setMetadata) {
+ $setMetadata($item);
+ }
+
+ $pool->save($item->set($value));
+ $save = false;
+ }
+
+ return $value;
+ }
+ // if we failed the race, retry locking in blocking mode to wait for the winner
+ $logger && $logger->info('Item "{key}" is locked, waiting for it to be released', ['key' => $item->getKey()]);
+ flock($lock, \LOCK_SH);
+ } finally {
+ flock($lock, \LOCK_UN);
+ unset(self::$lockedFiles[$key]);
+ }
+
+ try {
+ $value = $pool->get($item->getKey(), self::$signalingCallback, 0);
+ $logger && $logger->info('Item "{key}" retrieved after lock was released', ['key' => $item->getKey()]);
+ $save = false;
+
+ return $value;
+ } catch (\Exception $e) {
+ if (self::$signalingException !== $e) {
+ throw $e;
+ }
+ $logger && $logger->info('Item "{key}" not found while lock was released, now retrying', ['key' => $item->getKey()]);
+ }
+ }
+
+ return null;
+ }
+
+ private static function open(int $key)
+ {
+ if (null !== $h = self::$openedFiles[$key] ?? null) {
+ return $h;
+ }
+ set_error_handler(function () {});
+ try {
+ $h = fopen(self::$files[$key], 'r+');
+ } finally {
+ restore_error_handler();
+ }
+
+ return self::$openedFiles[$key] = $h ?: @fopen(self::$files[$key], 'r');
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/DefaultMarshaller.php b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php
new file mode 100644
index 00000000..7493a2ef
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/DefaultMarshaller.php
@@ -0,0 +1,99 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+use Symfony\Component\Cache\Exception\CacheException;
+
+/**
+ * Serializes/unserializes values using igbinary_serialize() if available, serialize() otherwise.
+ *
+ * @author Nicolas Grekas
+ */
+class DefaultMarshaller implements MarshallerInterface
+{
+ private $useIgbinarySerialize = true;
+
+ public function __construct(bool $useIgbinarySerialize = null)
+ {
+ if (null === $useIgbinarySerialize) {
+ $useIgbinarySerialize = \extension_loaded('igbinary') && (\PHP_VERSION_ID < 70400 || version_compare('3.1.6', phpversion('igbinary'), '<='));
+ } elseif ($useIgbinarySerialize && (!\extension_loaded('igbinary') || (\PHP_VERSION_ID >= 70400 && version_compare('3.1.6', phpversion('igbinary'), '>')))) {
+ throw new CacheException(\extension_loaded('igbinary') && \PHP_VERSION_ID >= 70400 ? 'Please upgrade the "igbinary" PHP extension to v3.1.6 or higher.' : 'The "igbinary" PHP extension is not loaded.');
+ }
+ $this->useIgbinarySerialize = $useIgbinarySerialize;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ $serialized = $failed = [];
+
+ foreach ($values as $id => $value) {
+ try {
+ if ($this->useIgbinarySerialize) {
+ $serialized[$id] = igbinary_serialize($value);
+ } else {
+ $serialized[$id] = serialize($value);
+ }
+ } catch (\Exception $e) {
+ $failed[] = $id;
+ }
+ }
+
+ return $serialized;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ if ('b:0;' === $value) {
+ return false;
+ }
+ if ('N;' === $value) {
+ return null;
+ }
+ static $igbinaryNull;
+ if ($value === ($igbinaryNull ?? $igbinaryNull = \extension_loaded('igbinary') ? igbinary_serialize(null) : false)) {
+ return null;
+ }
+ $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
+ try {
+ if (':' === ($value[1] ?? ':')) {
+ if (false !== $value = unserialize($value)) {
+ return $value;
+ }
+ } elseif (false === $igbinaryNull) {
+ throw new \RuntimeException('Failed to unserialize values, did you forget to install the "igbinary" extension?');
+ } elseif (null !== $value = igbinary_unserialize($value)) {
+ return $value;
+ }
+
+ throw new \DomainException(error_get_last() ? error_get_last()['message'] : 'Failed to unserialize values.');
+ } catch (\Error $e) {
+ throw new \ErrorException($e->getMessage(), $e->getCode(), \E_ERROR, $e->getFile(), $e->getLine());
+ } finally {
+ ini_set('unserialize_callback_func', $unserializeCallbackHandler);
+ }
+ }
+
+ /**
+ * @internal
+ */
+ public static function handleUnserializeCallback($class)
+ {
+ throw new \DomainException('Class not found: '.$class);
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/DeflateMarshaller.php b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php
new file mode 100644
index 00000000..55448061
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/DeflateMarshaller.php
@@ -0,0 +1,53 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+use Symfony\Component\Cache\Exception\CacheException;
+
+/**
+ * Compresses values using gzdeflate().
+ *
+ * @author Nicolas Grekas
+ */
+class DeflateMarshaller implements MarshallerInterface
+{
+ private $marshaller;
+
+ public function __construct(MarshallerInterface $marshaller)
+ {
+ if (!\function_exists('gzdeflate')) {
+ throw new CacheException('The "zlib" PHP extension is not loaded.');
+ }
+
+ $this->marshaller = $marshaller;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ return array_map('gzdeflate', $this->marshaller->marshall($values, $failed));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ if (false !== $inflatedValue = @gzinflate($value)) {
+ $value = $inflatedValue;
+ }
+
+ return $this->marshaller->unmarshall($value);
+ }
+}
diff --git a/vendor/symfony/cache/Marshaller/MarshallerInterface.php b/vendor/symfony/cache/Marshaller/MarshallerInterface.php
new file mode 100644
index 00000000..cdd6c402
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/MarshallerInterface.php
@@ -0,0 +1,40 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+/**
+ * Serializes/unserializes PHP values.
+ *
+ * Implementations of this interface MUST deal with errors carefully. They MUST
+ * also deal with forward and backward compatibility at the storage format level.
+ *
+ * @author Nicolas Grekas
+ */
+interface MarshallerInterface
+{
+ /**
+ * Serializes a list of values.
+ *
+ * When serialization fails for a specific value, no exception should be
+ * thrown. Instead, its key should be listed in $failed.
+ */
+ public function marshall(array $values, ?array &$failed): array;
+
+ /**
+ * Unserializes a single value and throws an exception if anything goes wrong.
+ *
+ * @return mixed
+ *
+ * @throws \Exception Whenever unserialization fails
+ */
+ public function unmarshall(string $value);
+}
diff --git a/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php
new file mode 100644
index 00000000..5d1e303b
--- /dev/null
+++ b/vendor/symfony/cache/Marshaller/TagAwareMarshaller.php
@@ -0,0 +1,89 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache\Marshaller;
+
+/**
+ * A marshaller optimized for data structures generated by AbstractTagAwareAdapter.
+ *
+ * @author Nicolas Grekas
+ */
+class TagAwareMarshaller implements MarshallerInterface
+{
+ private $marshaller;
+
+ public function __construct(MarshallerInterface $marshaller = null)
+ {
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function marshall(array $values, ?array &$failed): array
+ {
+ $failed = $notSerialized = $serialized = [];
+
+ foreach ($values as $id => $value) {
+ if (\is_array($value) && \is_array($value['tags'] ?? null) && \array_key_exists('value', $value) && \count($value) === 2 + (\is_string($value['meta'] ?? null) && 8 === \strlen($value['meta']))) {
+ // if the value is an array with keys "tags", "value" and "meta", use a compact serialization format
+ // magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F allow detecting this format quickly in unmarshall()
+
+ $v = $this->marshaller->marshall($value, $f);
+
+ if ($f) {
+ $f = [];
+ $failed[] = $id;
+ } else {
+ if ([] === $value['tags']) {
+ $v['tags'] = '';
+ }
+
+ $serialized[$id] = "\x9D".($value['meta'] ?? "\0\0\0\0\0\0\0\0").pack('N', \strlen($v['tags'])).$v['tags'].$v['value'];
+ $serialized[$id][9] = "\x5F";
+ }
+ } else {
+ // other arbitratry values are serialized using the decorated marshaller below
+ $notSerialized[$id] = $value;
+ }
+ }
+
+ if ($notSerialized) {
+ $serialized += $this->marshaller->marshall($notSerialized, $f);
+ $failed = array_merge($failed, $f);
+ }
+
+ return $serialized;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function unmarshall(string $value)
+ {
+ // detect the compact format used in marshall() using magic numbers in the form 9D-..-..-..-..-00-..-..-..-5F
+ if (13 >= \strlen($value) || "\x9D" !== $value[0] || "\0" !== $value[5] || "\x5F" !== $value[9]) {
+ return $this->marshaller->unmarshall($value);
+ }
+
+ // data consists of value, tags and metadata which we need to unpack
+ $meta = substr($value, 1, 12);
+ $meta[8] = "\0";
+ $tagLen = unpack('Nlen', $meta, 8)['len'];
+ $meta = substr($meta, 0, 8);
+
+ return [
+ 'value' => $this->marshaller->unmarshall(substr($value, 13 + $tagLen)),
+ 'tags' => $tagLen ? $this->marshaller->unmarshall(substr($value, 13, $tagLen)) : [],
+ 'meta' => "\0\0\0\0\0\0\0\0" === $meta ? null : $meta,
+ ];
+ }
+}
diff --git a/vendor/symfony/cache/Psr16Cache.php b/vendor/symfony/cache/Psr16Cache.php
new file mode 100644
index 00000000..ac265a57
--- /dev/null
+++ b/vendor/symfony/cache/Psr16Cache.php
@@ -0,0 +1,284 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\Cache;
+
+use Psr\Cache\CacheException as Psr6CacheException;
+use Psr\Cache\CacheItemPoolInterface;
+use Psr\SimpleCache\CacheException as SimpleCacheException;
+use Psr\SimpleCache\CacheInterface;
+use Symfony\Component\Cache\Adapter\AdapterInterface;
+use Symfony\Component\Cache\Exception\InvalidArgumentException;
+use Symfony\Component\Cache\Traits\ProxyTrait;
+
+if (null !== (new \ReflectionMethod(CacheInterface::class, 'get'))->getReturnType()) {
+ throw new \LogicException('psr/simple-cache 3.0+ is not compatible with this version of symfony/cache. Please upgrade symfony/cache to 6.0+ or downgrade psr/simple-cache to 1.x or 2.x.');
+}
+
+/**
+ * Turns a PSR-6 cache into a PSR-16 one.
+ *
+ * @author Nicolas Grekas
+ */
+class Psr16Cache implements CacheInterface, PruneableInterface, ResettableInterface
+{
+ use ProxyTrait;
+
+ private const METADATA_EXPIRY_OFFSET = 1527506807;
+
+ private $createCacheItem;
+ private $cacheItemPrototype;
+
+ public function __construct(CacheItemPoolInterface $pool)
+ {
+ $this->pool = $pool;
+
+ if (!$pool instanceof AdapterInterface) {
+ return;
+ }
+ $cacheItemPrototype = &$this->cacheItemPrototype;
+ $createCacheItem = \Closure::bind(
+ static function ($key, $value, $allowInt = false) use (&$cacheItemPrototype) {
+ $item = clone $cacheItemPrototype;
+ $item->poolHash = $item->innerItem = null;
+ $item->key = $allowInt && \is_int($key) ? (string) $key : CacheItem::validateKey($key);
+ $item->value = $value;
+ $item->isHit = false;
+
+ return $item;
+ },
+ null,
+ CacheItem::class
+ );
+ $this->createCacheItem = function ($key, $value, $allowInt = false) use ($createCacheItem) {
+ if (null === $this->cacheItemPrototype) {
+ $this->get($allowInt && \is_int($key) ? (string) $key : $key);
+ }
+ $this->createCacheItem = $createCacheItem;
+
+ return $createCacheItem($key, null, $allowInt)->set($value);
+ };
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get($key, $default = null)
+ {
+ try {
+ $item = $this->pool->getItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ if (null === $this->cacheItemPrototype) {
+ $this->cacheItemPrototype = clone $item;
+ $this->cacheItemPrototype->set(null);
+ }
+
+ return $item->isHit() ? $item->get() : $default;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function set($key, $value, $ttl = null)
+ {
+ try {
+ if (null !== $f = $this->createCacheItem) {
+ $item = $f($key, $value);
+ } else {
+ $item = $this->pool->getItem($key)->set($value);
+ }
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ if (null !== $ttl) {
+ $item->expiresAfter($ttl);
+ }
+
+ return $this->pool->save($item);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function delete($key)
+ {
+ try {
+ return $this->pool->deleteItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function clear()
+ {
+ return $this->pool->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return iterable
+ */
+ public function getMultiple($keys, $default = null)
+ {
+ if ($keys instanceof \Traversable) {
+ $keys = iterator_to_array($keys, false);
+ } elseif (!\is_array($keys)) {
+ throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys)));
+ }
+
+ try {
+ $items = $this->pool->getItems($keys);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ $values = [];
+
+ if (!$this->pool instanceof AdapterInterface) {
+ foreach ($items as $key => $item) {
+ $values[$key] = $item->isHit() ? $item->get() : $default;
+ }
+
+ return $values;
+ }
+
+ foreach ($items as $key => $item) {
+ if (!$item->isHit()) {
+ $values[$key] = $default;
+ continue;
+ }
+ $values[$key] = $item->get();
+
+ if (!$metadata = $item->getMetadata()) {
+ continue;
+ }
+ unset($metadata[CacheItem::METADATA_TAGS]);
+
+ if ($metadata) {
+ $values[$key] = ["\x9D".pack('VN', (int) (0.1 + $metadata[CacheItem::METADATA_EXPIRY] - self::METADATA_EXPIRY_OFFSET), $metadata[CacheItem::METADATA_CTIME])."\x5F" => $values[$key]];
+ }
+ }
+
+ return $values;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function setMultiple($values, $ttl = null)
+ {
+ $valuesIsArray = \is_array($values);
+ if (!$valuesIsArray && !$values instanceof \Traversable) {
+ throw new InvalidArgumentException(sprintf('Cache values must be array or Traversable, "%s" given.', \is_object($values) ? \get_class($values) : \gettype($values)));
+ }
+ $items = [];
+
+ try {
+ if (null !== $f = $this->createCacheItem) {
+ $valuesIsArray = false;
+ foreach ($values as $key => $value) {
+ $items[$key] = $f($key, $value, true);
+ }
+ } elseif ($valuesIsArray) {
+ $items = [];
+ foreach ($values as $key => $value) {
+ $items[] = (string) $key;
+ }
+ $items = $this->pool->getItems($items);
+ } else {
+ foreach ($values as $key => $value) {
+ if (\is_int($key)) {
+ $key = (string) $key;
+ }
+ $items[$key] = $this->pool->getItem($key)->set($value);
+ }
+ }
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ $ok = true;
+
+ foreach ($items as $key => $item) {
+ if ($valuesIsArray) {
+ $item->set($values[$key]);
+ }
+ if (null !== $ttl) {
+ $item->expiresAfter($ttl);
+ }
+ $ok = $this->pool->saveDeferred($item) && $ok;
+ }
+
+ return $this->pool->commit() && $ok;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function deleteMultiple($keys)
+ {
+ if ($keys instanceof \Traversable) {
+ $keys = iterator_to_array($keys, false);
+ } elseif (!\is_array($keys)) {
+ throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys)));
+ }
+
+ try {
+ return $this->pool->deleteItems($keys);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return bool
+ */
+ public function has($key)
+ {
+ try {
+ return $this->pool->hasItem($key);
+ } catch (SimpleCacheException $e) {
+ throw $e;
+ } catch (Psr6CacheException $e) {
+ throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
+ }
+ }
+}
diff --git a/vendor/symfony/cache/README.md b/vendor/symfony/cache/README.md
index c4ab7520..c466d578 100644
--- a/vendor/symfony/cache/README.md
+++ b/vendor/symfony/cache/README.md
@@ -1,18 +1,19 @@
Symfony PSR-6 implementation for caching
========================================
-This component provides an extended [PSR-6](http://www.php-fig.org/psr/psr-6/)
-implementation for adding cache to your applications. It is designed to have a
-low overhead so that caching is fastest. It ships with a few caching adapters
-for the most widespread and suited to caching backends. It also provides a
-`doctrine/cache` proxy adapter to cover more advanced caching needs and a proxy
-adapter for greater interoperability between PSR-6 implementations.
+The Cache component provides extended
+[PSR-6](https://www.php-fig.org/psr/psr-6/) implementations for adding cache to
+your applications. It is designed to have a low overhead so that caching is
+fastest. It ships with adapters for the most widespread caching backends.
+It also provides a [PSR-16](https://www.php-fig.org/psr/psr-16/) adapter,
+and implementations for [symfony/cache-contracts](https://github.com/symfony/cache-contracts)'
+`CacheInterface` and `TagAwareCacheInterface`.
Resources
---------
- * [Documentation](https://symfony.com/doc/current/components/cache.html)
- * [Contributing](https://symfony.com/doc/current/contributing/index.html)
- * [Report issues](https://github.com/symfony/symfony/issues) and
- [send Pull Requests](https://github.com/symfony/symfony/pulls)
- in the [main Symfony repository](https://github.com/symfony/symfony)
+ * [Documentation](https://symfony.com/doc/current/components/cache.html)
+ * [Contributing](https://symfony.com/doc/current/contributing/index.html)
+ * [Report issues](https://github.com/symfony/symfony/issues) and
+ [send Pull Requests](https://github.com/symfony/symfony/pulls)
+ in the [main Symfony repository](https://github.com/symfony/symfony)
diff --git a/vendor/symfony/cache/ResettableInterface.php b/vendor/symfony/cache/ResettableInterface.php
index 6be72861..7b0a853f 100644
--- a/vendor/symfony/cache/ResettableInterface.php
+++ b/vendor/symfony/cache/ResettableInterface.php
@@ -11,10 +11,11 @@
namespace Symfony\Component\Cache;
+use Symfony\Contracts\Service\ResetInterface;
+
/**
* Resets a pool's local state.
*/
-interface ResettableInterface
+interface ResettableInterface extends ResetInterface
{
- public function reset();
}
diff --git a/vendor/symfony/cache/Simple/AbstractCache.php b/vendor/symfony/cache/Simple/AbstractCache.php
index baedb737..c3d8b38c 100644
--- a/vendor/symfony/cache/Simple/AbstractCache.php
+++ b/vendor/symfony/cache/Simple/AbstractCache.php
@@ -12,37 +12,37 @@
namespace Symfony\Component\Cache\Simple;
use Psr\Log\LoggerAwareInterface;
-use Psr\SimpleCache\CacheInterface;
+use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
+use Symfony\Component\Cache\Adapter\AbstractAdapter;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\AbstractTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', AbstractCache::class, AbstractAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
/**
- * @author Nicolas Grekas
+ * @deprecated since Symfony 4.3, use AbstractAdapter and type-hint for CacheInterface instead.
*/
-abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, ResettableInterface
+abstract class AbstractCache implements Psr16CacheInterface, LoggerAwareInterface, ResettableInterface
{
- /**
- * @internal
- */
- const NS_SEPARATOR = ':';
-
use AbstractTrait {
deleteItems as private;
AbstractTrait::deleteItem as delete;
AbstractTrait::hasItem as has;
}
- private $defaultLifetime;
-
/**
- * @param string $namespace
- * @param int $defaultLifetime
+ * @internal
*/
- protected function __construct($namespace = '', $defaultLifetime = 0)
+ protected const NS_SEPARATOR = ':';
+
+ private $defaultLifetime;
+
+ protected function __construct(string $namespace = '', int $defaultLifetime = 0)
{
- $this->defaultLifetime = max(0, (int) $defaultLifetime);
+ $this->defaultLifetime = max(0, $defaultLifetime);
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace));
@@ -61,7 +61,7 @@ public function get($key, $default = null)
return $value;
}
} catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch key "{key}"', ['key' => $key, 'exception' => $e]);
+ CacheItem::log($this->logger, 'Failed to fetch key "{key}": '.$e->getMessage(), ['key' => $key, 'exception' => $e]);
}
return $default;
@@ -69,6 +69,8 @@ public function get($key, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function set($key, $value, $ttl = null)
{
@@ -79,6 +81,8 @@ public function set($key, $value, $ttl = null)
/**
* {@inheritdoc}
+ *
+ * @return iterable
*/
public function getMultiple($keys, $default = null)
{
@@ -95,7 +99,7 @@ public function getMultiple($keys, $default = null)
try {
$values = $this->doFetch($ids);
} catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => $keys, 'exception' => $e]);
+ CacheItem::log($this->logger, 'Failed to fetch values: '.$e->getMessage(), ['keys' => $keys, 'exception' => $e]);
$values = [];
}
$ids = array_combine($ids, $keys);
@@ -105,6 +109,8 @@ public function getMultiple($keys, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function setMultiple($values, $ttl = null)
{
@@ -134,13 +140,16 @@ public function setMultiple($values, $ttl = null)
foreach (\is_array($e) ? $e : array_keys($valuesById) as $id) {
$keys[] = substr($id, \strlen($this->namespace));
}
- CacheItem::log($this->logger, 'Failed to save values', ['keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null]);
+ $message = 'Failed to save values'.($e instanceof \Exception ? ': '.$e->getMessage() : '.');
+ CacheItem::log($this->logger, $message, ['keys' => $keys, 'exception' => $e instanceof \Exception ? $e : null]);
return false;
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteMultiple($keys)
{
@@ -168,19 +177,19 @@ private function normalizeTtl($ttl)
throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given.', \is_object($ttl) ? \get_class($ttl) : \gettype($ttl)));
}
- private function generateValues($values, &$keys, $default)
+ private function generateValues(iterable $values, array &$keys, $default): iterable
{
try {
foreach ($values as $id => $value) {
if (!isset($keys[$id])) {
- $id = key($keys);
+ throw new InvalidArgumentException(sprintf('Could not match value id "%s" to keys "%s".', $id, implode('", "', $keys)));
}
$key = $keys[$id];
unset($keys[$id]);
yield $key => $value;
}
} catch (\Exception $e) {
- CacheItem::log($this->logger, 'Failed to fetch requested values', ['keys' => array_values($keys), 'exception' => $e]);
+ CacheItem::log($this->logger, 'Failed to fetch values: '.$e->getMessage(), ['keys' => array_values($keys), 'exception' => $e]);
}
foreach ($keys as $key) {
diff --git a/vendor/symfony/cache/Simple/ApcuCache.php b/vendor/symfony/cache/Simple/ApcuCache.php
index e583b443..bef89e27 100644
--- a/vendor/symfony/cache/Simple/ApcuCache.php
+++ b/vendor/symfony/cache/Simple/ApcuCache.php
@@ -11,18 +11,20 @@
namespace Symfony\Component\Cache\Simple;
+use Symfony\Component\Cache\Adapter\ApcuAdapter;
use Symfony\Component\Cache\Traits\ApcuTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ApcuCache::class, ApcuAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use ApcuAdapter and type-hint for CacheInterface instead.
+ */
class ApcuCache extends AbstractCache
{
use ApcuTrait;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $version
- */
- public function __construct($namespace = '', $defaultLifetime = 0, $version = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $version = null)
{
$this->init($namespace, $defaultLifetime, $version);
}
diff --git a/vendor/symfony/cache/Simple/ArrayCache.php b/vendor/symfony/cache/Simple/ArrayCache.php
index 6013f0ad..469edf1c 100644
--- a/vendor/symfony/cache/Simple/ArrayCache.php
+++ b/vendor/symfony/cache/Simple/ArrayCache.php
@@ -12,16 +12,20 @@
namespace Symfony\Component\Cache\Simple;
use Psr\Log\LoggerAwareInterface;
-use Psr\SimpleCache\CacheInterface;
+use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
+use Symfony\Component\Cache\Adapter\ArrayAdapter;
use Symfony\Component\Cache\CacheItem;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\ArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ArrayCache::class, ArrayAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
/**
- * @author Nicolas Grekas
+ * @deprecated since Symfony 4.3, use ArrayAdapter and type-hint for CacheInterface instead.
*/
-class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInterface
+class ArrayCache implements Psr16CacheInterface, LoggerAwareInterface, ResettableInterface
{
use ArrayTrait {
ArrayTrait::deleteItem as delete;
@@ -31,12 +35,11 @@ class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInte
private $defaultLifetime;
/**
- * @param int $defaultLifetime
* @param bool $storeSerialized Disabling serialization can lead to cache corruptions when storing mutable values but increases performance otherwise
*/
- public function __construct($defaultLifetime = 0, $storeSerialized = true)
+ public function __construct(int $defaultLifetime = 0, bool $storeSerialized = true)
{
- $this->defaultLifetime = (int) $defaultLifetime;
+ $this->defaultLifetime = $defaultLifetime;
$this->storeSerialized = $storeSerialized;
}
@@ -45,13 +48,26 @@ public function __construct($defaultLifetime = 0, $storeSerialized = true)
*/
public function get($key, $default = null)
{
- foreach ($this->getMultiple([$key], $default) as $v) {
- return $v;
+ if (!\is_string($key) || !isset($this->expiries[$key])) {
+ CacheItem::validateKey($key);
+ }
+ if (!$isHit = isset($this->expiries[$key]) && ($this->expiries[$key] > microtime(true) || !$this->delete($key))) {
+ $this->values[$key] = null;
+
+ return $default;
}
+ if (!$this->storeSerialized) {
+ return $this->values[$key];
+ }
+ $value = $this->unfreeze($key, $isHit);
+
+ return $isHit ? $value : $default;
}
/**
* {@inheritdoc}
+ *
+ * @return iterable
*/
public function getMultiple($keys, $default = null)
{
@@ -61,14 +77,18 @@ public function getMultiple($keys, $default = null)
throw new InvalidArgumentException(sprintf('Cache keys must be array or Traversable, "%s" given.', \is_object($keys) ? \get_class($keys) : \gettype($keys)));
}
foreach ($keys as $key) {
- CacheItem::validateKey($key);
+ if (!\is_string($key) || !isset($this->expiries[$key])) {
+ CacheItem::validateKey($key);
+ }
}
- return $this->generateItems($keys, time(), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; });
+ return $this->generateItems($keys, microtime(true), function ($k, $v, $hit) use ($default) { return $hit ? $v : $default; });
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteMultiple($keys)
{
@@ -84,16 +104,22 @@ public function deleteMultiple($keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function set($key, $value, $ttl = null)
{
- CacheItem::validateKey($key);
+ if (!\is_string($key)) {
+ CacheItem::validateKey($key);
+ }
return $this->setMultiple([$key => $value], $ttl);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function setMultiple($values, $ttl = null)
{
@@ -103,27 +129,20 @@ public function setMultiple($values, $ttl = null)
$valuesArray = [];
foreach ($values as $key => $value) {
- \is_int($key) || CacheItem::validateKey($key);
+ if (!\is_int($key) && !(\is_string($key) && isset($this->expiries[$key]))) {
+ CacheItem::validateKey($key);
+ }
$valuesArray[$key] = $value;
}
if (false === $ttl = $this->normalizeTtl($ttl)) {
return $this->deleteMultiple(array_keys($valuesArray));
}
- if ($this->storeSerialized) {
- foreach ($valuesArray as $key => $value) {
- try {
- $valuesArray[$key] = serialize($value);
- } catch (\Exception $e) {
- $type = \is_object($value) ? \get_class($value) : \gettype($value);
- CacheItem::log($this->logger, 'Failed to save key "{key}" ({type})', ['key' => $key, 'type' => $type, 'exception' => $e]);
-
- return false;
- }
- }
- }
- $expiry = 0 < $ttl ? time() + $ttl : \PHP_INT_MAX;
+ $expiry = 0 < $ttl ? microtime(true) + $ttl : \PHP_INT_MAX;
foreach ($valuesArray as $key => $value) {
+ if ($this->storeSerialized && null === $value = $this->freeze($value, $key)) {
+ return false;
+ }
$this->values[$key] = $value;
$this->expiries[$key] = $expiry;
}
diff --git a/vendor/symfony/cache/Simple/ChainCache.php b/vendor/symfony/cache/Simple/ChainCache.php
index 2e6c7277..bae95072 100644
--- a/vendor/symfony/cache/Simple/ChainCache.php
+++ b/vendor/symfony/cache/Simple/ChainCache.php
@@ -11,10 +11,15 @@
namespace Symfony\Component\Cache\Simple;
-use Psr\SimpleCache\CacheInterface;
+use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
+use Symfony\Component\Cache\Adapter\ChainAdapter;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
+use Symfony\Contracts\Cache\CacheInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', ChainCache::class, ChainAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
/**
* Chains several caches together.
@@ -22,9 +27,9 @@
* Cached items are fetched from the first cache having them in its data store.
* They are saved and deleted in all caches at once.
*
- * @author Nicolas Grekas
+ * @deprecated since Symfony 4.3, use ChainAdapter and type-hint for CacheInterface instead.
*/
-class ChainCache implements CacheInterface, PruneableInterface, ResettableInterface
+class ChainCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface
{
private $miss;
private $caches = [];
@@ -32,25 +37,25 @@ class ChainCache implements CacheInterface, PruneableInterface, ResettableInterf
private $cacheCount;
/**
- * @param CacheInterface[] $caches The ordered list of caches used to fetch cached items
- * @param int $defaultLifetime The lifetime of items propagated from lower caches to upper ones
+ * @param Psr16CacheInterface[] $caches The ordered list of caches used to fetch cached items
+ * @param int $defaultLifetime The lifetime of items propagated from lower caches to upper ones
*/
- public function __construct(array $caches, $defaultLifetime = 0)
+ public function __construct(array $caches, int $defaultLifetime = 0)
{
if (!$caches) {
throw new InvalidArgumentException('At least one cache must be specified.');
}
foreach ($caches as $cache) {
- if (!$cache instanceof CacheInterface) {
- throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($cache), CacheInterface::class));
+ if (!$cache instanceof Psr16CacheInterface) {
+ throw new InvalidArgumentException(sprintf('The class "%s" does not implement the "%s" interface.', \get_class($cache), Psr16CacheInterface::class));
}
}
$this->miss = new \stdClass();
$this->caches = array_values($caches);
$this->cacheCount = \count($this->caches);
- $this->defaultLifetime = 0 < $defaultLifetime ? (int) $defaultLifetime : null;
+ $this->defaultLifetime = 0 < $defaultLifetime ? $defaultLifetime : null;
}
/**
@@ -77,6 +82,8 @@ public function get($key, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return iterable
*/
public function getMultiple($keys, $default = null)
{
@@ -85,11 +92,11 @@ public function getMultiple($keys, $default = null)
return $this->generateItems($this->caches[0]->getMultiple($keys, $miss), 0, $miss, $default);
}
- private function generateItems($values, $cacheIndex, $miss, $default)
+ private function generateItems(iterable $values, int $cacheIndex, $miss, $default): iterable
{
$missing = [];
$nextCacheIndex = $cacheIndex + 1;
- $nextCache = isset($this->caches[$nextCacheIndex]) ? $this->caches[$nextCacheIndex] : null;
+ $nextCache = $this->caches[$nextCacheIndex] ?? null;
foreach ($values as $k => $value) {
if ($miss !== $value) {
@@ -118,6 +125,8 @@ private function generateItems($values, $cacheIndex, $miss, $default)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function has($key)
{
@@ -132,6 +141,8 @@ public function has($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function clear()
{
@@ -147,6 +158,8 @@ public function clear()
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function delete($key)
{
@@ -162,6 +175,8 @@ public function delete($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteMultiple($keys)
{
@@ -180,6 +195,8 @@ public function deleteMultiple($keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function set($key, $value, $ttl = null)
{
@@ -195,6 +212,8 @@ public function set($key, $value, $ttl = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function setMultiple($values, $ttl = null)
{
@@ -244,7 +263,7 @@ public function prune()
public function reset()
{
foreach ($this->caches as $cache) {
- if ($cache instanceof ResettableInterface) {
+ if ($cache instanceof ResetInterface) {
$cache->reset();
}
}
diff --git a/vendor/symfony/cache/Simple/DoctrineCache.php b/vendor/symfony/cache/Simple/DoctrineCache.php
index ea1a4eda..d7feb4d3 100644
--- a/vendor/symfony/cache/Simple/DoctrineCache.php
+++ b/vendor/symfony/cache/Simple/DoctrineCache.php
@@ -12,17 +12,20 @@
namespace Symfony\Component\Cache\Simple;
use Doctrine\Common\Cache\CacheProvider;
+use Symfony\Component\Cache\Adapter\DoctrineAdapter;
use Symfony\Component\Cache\Traits\DoctrineTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', DoctrineCache::class, DoctrineAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use DoctrineAdapter and type-hint for CacheInterface instead.
+ */
class DoctrineCache extends AbstractCache
{
use DoctrineTrait;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- */
- public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0)
+ public function __construct(CacheProvider $provider, string $namespace = '', int $defaultLifetime = 0)
{
parent::__construct('', $defaultLifetime);
$this->provider = $provider;
diff --git a/vendor/symfony/cache/Simple/FilesystemCache.php b/vendor/symfony/cache/Simple/FilesystemCache.php
index ccd57953..fcc8a170 100644
--- a/vendor/symfony/cache/Simple/FilesystemCache.php
+++ b/vendor/symfony/cache/Simple/FilesystemCache.php
@@ -11,20 +11,25 @@
namespace Symfony\Component\Cache\Simple;
+use Symfony\Component\Cache\Adapter\FilesystemAdapter;
+use Symfony\Component\Cache\Marshaller\DefaultMarshaller;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\FilesystemTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', FilesystemCache::class, FilesystemAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use FilesystemAdapter and type-hint for CacheInterface instead.
+ */
class FilesystemCache extends AbstractCache implements PruneableInterface
{
use FilesystemTrait;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $directory
- */
- public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, MarshallerInterface $marshaller = null)
{
+ $this->marshaller = $marshaller ?? new DefaultMarshaller();
parent::__construct('', $defaultLifetime);
$this->init($namespace, $directory);
}
diff --git a/vendor/symfony/cache/Simple/MemcachedCache.php b/vendor/symfony/cache/Simple/MemcachedCache.php
index 94a9f297..1f636486 100644
--- a/vendor/symfony/cache/Simple/MemcachedCache.php
+++ b/vendor/symfony/cache/Simple/MemcachedCache.php
@@ -11,20 +11,24 @@
namespace Symfony\Component\Cache\Simple;
+use Symfony\Component\Cache\Adapter\MemcachedAdapter;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\Traits\MemcachedTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', MemcachedCache::class, MemcachedAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use MemcachedAdapter and type-hint for CacheInterface instead.
+ */
class MemcachedCache extends AbstractCache
{
use MemcachedTrait;
protected $maxIdLength = 250;
- /**
- * @param string $namespace
- * @param int $defaultLifetime
- */
- public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0)
+ public function __construct(\Memcached $client, string $namespace = '', int $defaultLifetime = 0, MarshallerInterface $marshaller = null)
{
- $this->init($client, $namespace, $defaultLifetime);
+ $this->init($client, $namespace, $defaultLifetime, $marshaller);
}
}
diff --git a/vendor/symfony/cache/Simple/NullCache.php b/vendor/symfony/cache/Simple/NullCache.php
index fa986aeb..fcbd39d5 100644
--- a/vendor/symfony/cache/Simple/NullCache.php
+++ b/vendor/symfony/cache/Simple/NullCache.php
@@ -11,12 +11,16 @@
namespace Symfony\Component\Cache\Simple;
-use Psr\SimpleCache\CacheInterface;
+use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
+use Symfony\Component\Cache\Adapter\NullAdapter;
+use Symfony\Contracts\Cache\CacheInterface;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', NullCache::class, NullAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
/**
- * @author Nicolas Grekas
+ * @deprecated since Symfony 4.3, use NullAdapter and type-hint for CacheInterface instead.
*/
-class NullCache implements CacheInterface
+class NullCache implements Psr16CacheInterface
{
/**
* {@inheritdoc}
@@ -28,6 +32,8 @@ public function get($key, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return iterable
*/
public function getMultiple($keys, $default = null)
{
@@ -38,6 +44,8 @@ public function getMultiple($keys, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function has($key)
{
@@ -46,6 +54,8 @@ public function has($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function clear()
{
@@ -54,6 +64,8 @@ public function clear()
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function delete($key)
{
@@ -62,6 +74,8 @@ public function delete($key)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteMultiple($keys)
{
@@ -70,6 +84,8 @@ public function deleteMultiple($keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function set($key, $value, $ttl = null)
{
@@ -78,6 +94,8 @@ public function set($key, $value, $ttl = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function setMultiple($values, $ttl = null)
{
diff --git a/vendor/symfony/cache/Simple/PdoCache.php b/vendor/symfony/cache/Simple/PdoCache.php
index c92e049a..7011ea07 100644
--- a/vendor/symfony/cache/Simple/PdoCache.php
+++ b/vendor/symfony/cache/Simple/PdoCache.php
@@ -11,9 +11,17 @@
namespace Symfony\Component\Cache\Simple;
+use Symfony\Component\Cache\Adapter\PdoAdapter;
+use Symfony\Component\Cache\Marshaller\MarshallerInterface;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\PdoTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PdoCache::class, PdoAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use PdoAdapter and type-hint for CacheInterface instead.
+ */
class PdoCache extends AbstractCache implements PruneableInterface
{
use PdoTrait;
@@ -25,6 +33,9 @@ class PdoCache extends AbstractCache implements PruneableInterface
* a Doctrine DBAL Connection or a DSN string that will be used to
* lazy-connect to the database when the cache is actually used.
*
+ * When a Doctrine DBAL Connection is passed, the cache table is created
+ * automatically when possible. Otherwise, use the createTable() method.
+ *
* List of available options:
* * db_table: The name of the table [default: cache_items]
* * db_id_col: The column where to store the cache id [default: item_id]
@@ -35,17 +46,14 @@ class PdoCache extends AbstractCache implements PruneableInterface
* * db_password: The password when lazy-connect [default: '']
* * db_connection_options: An array of driver-specific connection options [default: []]
*
- * @param \PDO|Connection|string $connOrDsn A \PDO or Connection instance or DSN string or null
- * @param string $namespace
- * @param int $defaultLifetime
- * @param array $options An associative array of options
+ * @param \PDO|Connection|string $connOrDsn a \PDO or Connection instance or DSN string or null
*
* @throws InvalidArgumentException When first argument is not PDO nor Connection nor string
* @throws InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION
* @throws InvalidArgumentException When namespace contains invalid characters
*/
- public function __construct($connOrDsn, $namespace = '', $defaultLifetime = 0, array $options = [])
+ public function __construct($connOrDsn, string $namespace = '', int $defaultLifetime = 0, array $options = [], MarshallerInterface $marshaller = null)
{
- $this->init($connOrDsn, $namespace, $defaultLifetime, $options);
+ $this->init($connOrDsn, $namespace, $defaultLifetime, $options, $marshaller);
}
}
diff --git a/vendor/symfony/cache/Simple/PhpArrayCache.php b/vendor/symfony/cache/Simple/PhpArrayCache.php
index 7bb25ff8..10c7340a 100644
--- a/vendor/symfony/cache/Simple/PhpArrayCache.php
+++ b/vendor/symfony/cache/Simple/PhpArrayCache.php
@@ -11,51 +11,44 @@
namespace Symfony\Component\Cache\Simple;
-use Psr\SimpleCache\CacheInterface;
+use Psr\SimpleCache\CacheInterface as Psr16CacheInterface;
+use Symfony\Component\Cache\Adapter\PhpArrayAdapter;
use Symfony\Component\Cache\Exception\InvalidArgumentException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\ResettableInterface;
use Symfony\Component\Cache\Traits\PhpArrayTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PhpArrayCache::class, PhpArrayAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
/**
- * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0.
- * Warmed up items are read-only and run-time discovered items are cached using a fallback adapter.
- *
- * @author Titouan Galopin
- * @author Nicolas Grekas
+ * @deprecated since Symfony 4.3, use PhpArrayAdapter and type-hint for CacheInterface instead.
*/
-class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInterface
+class PhpArrayCache implements Psr16CacheInterface, PruneableInterface, ResettableInterface
{
use PhpArrayTrait;
/**
- * @param string $file The PHP file were values are cached
- * @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit
+ * @param string $file The PHP file were values are cached
+ * @param Psr16CacheInterface $fallbackPool A pool to fallback on when an item is not hit
*/
- public function __construct($file, CacheInterface $fallbackPool)
+ public function __construct(string $file, Psr16CacheInterface $fallbackPool)
{
$this->file = $file;
$this->pool = $fallbackPool;
- $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN);
}
/**
- * This adapter should only be used on PHP 7.0+ to take advantage of how PHP
- * stores arrays in its latest versions. This factory method decorates the given
- * fallback pool with this adapter only if the current PHP version is supported.
+ * This adapter takes advantage of how PHP stores arrays in its latest versions.
*
* @param string $file The PHP file were values are cached
* @param CacheInterface $fallbackPool A pool to fallback on when an item is not hit
*
- * @return CacheInterface
+ * @return Psr16CacheInterface
*/
- public static function create($file, CacheInterface $fallbackPool)
+ public static function create($file, Psr16CacheInterface $fallbackPool)
{
- if (\PHP_VERSION_ID >= 70000) {
- return new static($file, $fallbackPool);
- }
-
- return $fallbackPool;
+ return new static($file, $fallbackPool);
}
/**
@@ -69,22 +62,18 @@ public function get($key, $default = null)
if (null === $this->values) {
$this->initialize();
}
- if (!isset($this->values[$key])) {
+ if (!isset($this->keys[$key])) {
return $this->pool->get($key, $default);
}
-
- $value = $this->values[$key];
+ $value = $this->values[$this->keys[$key]];
if ('N;' === $value) {
- $value = null;
- } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
+ return null;
+ }
+ if ($value instanceof \Closure) {
try {
- $e = null;
- $value = unserialize($value);
- } catch (\Error $e) {
- } catch (\Exception $e) {
- }
- if (null !== $e) {
+ return $value();
+ } catch (\Throwable $e) {
return $default;
}
}
@@ -94,6 +83,8 @@ public function get($key, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return iterable
*/
public function getMultiple($keys, $default = null)
{
@@ -116,6 +107,8 @@ public function getMultiple($keys, $default = null)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function has($key)
{
@@ -126,11 +119,13 @@ public function has($key)
$this->initialize();
}
- return isset($this->values[$key]) || $this->pool->has($key);
+ return isset($this->keys[$key]) || $this->pool->has($key);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function delete($key)
{
@@ -141,11 +136,13 @@ public function delete($key)
$this->initialize();
}
- return !isset($this->values[$key]) && $this->pool->delete($key);
+ return !isset($this->keys[$key]) && $this->pool->delete($key);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function deleteMultiple($keys)
{
@@ -161,7 +158,7 @@ public function deleteMultiple($keys)
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
}
- if (isset($this->values[$key])) {
+ if (isset($this->keys[$key])) {
$deleted = false;
} else {
$fallbackKeys[] = $key;
@@ -180,6 +177,8 @@ public function deleteMultiple($keys)
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function set($key, $value, $ttl = null)
{
@@ -190,11 +189,13 @@ public function set($key, $value, $ttl = null)
$this->initialize();
}
- return !isset($this->values[$key]) && $this->pool->set($key, $value, $ttl);
+ return !isset($this->keys[$key]) && $this->pool->set($key, $value, $ttl);
}
/**
* {@inheritdoc}
+ *
+ * @return bool
*/
public function setMultiple($values, $ttl = null)
{
@@ -210,7 +211,7 @@ public function setMultiple($values, $ttl = null)
throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
}
- if (isset($this->values[$key])) {
+ if (isset($this->keys[$key])) {
$saved = false;
} else {
$fallbackValues[$key] = $value;
@@ -224,22 +225,20 @@ public function setMultiple($values, $ttl = null)
return $saved;
}
- private function generateItems(array $keys, $default)
+ private function generateItems(array $keys, $default): iterable
{
$fallbackKeys = [];
foreach ($keys as $key) {
- if (isset($this->values[$key])) {
- $value = $this->values[$key];
+ if (isset($this->keys[$key])) {
+ $value = $this->values[$this->keys[$key]];
if ('N;' === $value) {
yield $key => null;
- } elseif (\is_string($value) && isset($value[2]) && ':' === $value[1]) {
+ } elseif ($value instanceof \Closure) {
try {
- yield $key => unserialize($value);
- } catch (\Error $e) {
- yield $key => $default;
- } catch (\Exception $e) {
+ yield $key => $value();
+ } catch (\Throwable $e) {
yield $key => $default;
}
} else {
@@ -251,9 +250,7 @@ private function generateItems(array $keys, $default)
}
if ($fallbackKeys) {
- foreach ($this->pool->getMultiple($fallbackKeys, $default) as $key => $item) {
- yield $key => $item;
- }
+ yield from $this->pool->getMultiple($fallbackKeys, $default);
}
}
}
diff --git a/vendor/symfony/cache/Simple/PhpFilesCache.php b/vendor/symfony/cache/Simple/PhpFilesCache.php
index 50c19034..9c79ae9a 100644
--- a/vendor/symfony/cache/Simple/PhpFilesCache.php
+++ b/vendor/symfony/cache/Simple/PhpFilesCache.php
@@ -11,31 +11,35 @@
namespace Symfony\Component\Cache\Simple;
+use Symfony\Component\Cache\Adapter\PhpFilesAdapter;
use Symfony\Component\Cache\Exception\CacheException;
use Symfony\Component\Cache\PruneableInterface;
use Symfony\Component\Cache\Traits\PhpFilesTrait;
+use Symfony\Contracts\Cache\CacheInterface;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" and type-hint for "%s" instead.', PhpFilesCache::class, PhpFilesAdapter::class, CacheInterface::class), \E_USER_DEPRECATED);
+
+/**
+ * @deprecated since Symfony 4.3, use PhpFilesAdapter and type-hint for CacheInterface instead.
+ */
class PhpFilesCache extends AbstractCache implements PruneableInterface
{
use PhpFilesTrait;
/**
- * @param string $namespace
- * @param int $defaultLifetime
- * @param string|null $directory
+ * @param $appendOnly Set to `true` to gain extra performance when the items stored in this pool never expire.
+ * Doing so is encouraged because it fits perfectly OPcache's memory model.
*
* @throws CacheException if OPcache is not enabled
*/
- public function __construct($namespace = '', $defaultLifetime = 0, $directory = null)
+ public function __construct(string $namespace = '', int $defaultLifetime = 0, string $directory = null, bool $appendOnly = false)
{
- if (!static::isSupported()) {
- throw new CacheException('OPcache is not enabled.');
- }
+ $this->appendOnly = $appendOnly;
+ self::$startTime = self::$startTime ?? $_SERVER['REQUEST_TIME'] ?? time();
parent::__construct('', $defaultLifetime);
$this->init($namespace, $directory);
-
- $e = new \Exception();
- $this->includeHandler = function () use ($e) { throw $e; };
- $this->zendDetectUnicode = filter_var(ini_get('zend.detect_unicode'), \FILTER_VALIDATE_BOOLEAN);
+ $this->includeHandler = static function ($type, $msg, $file, $line) {
+ throw new \ErrorException($msg, 0, $type, $file, $line);
+ };
}
}
diff --git a/vendor/symfony/cache/Simple/Psr6Cache.php b/vendor/symfony/cache/Simple/Psr6Cache.php
index 6b3de205..366284b2 100644
--- a/vendor/symfony/cache/Simple/Psr6Cache.php
+++ b/vendor/symfony/cache/Simple/Psr6Cache.php
@@ -11,231 +11,13 @@
namespace Symfony\Component\Cache\Simple;
-use Psr\Cache\CacheException as Psr6CacheException;
-use Psr\Cache\CacheItemPoolInterface;
-use Psr\SimpleCache\CacheException as SimpleCacheException;
-use Psr\SimpleCache\CacheInterface;
-use Symfony\Component\Cache\Adapter\AdapterInterface;
-use Symfony\Component\Cache\CacheItem;
-use Symfony\Component\Cache\Exception\InvalidArgumentException;
-use Symfony\Component\Cache\PruneableInterface;
-use Symfony\Component\Cache\ResettableInterface;
-use Symfony\Component\Cache\Traits\ProxyTrait;
+use Symfony\Component\Cache\Psr16Cache;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', Psr6Cache::class, Psr16Cache::class), \E_USER_DEPRECATED);
/**
- * @author Nicolas Grekas
+ *
+ * @final since Symfony 4.3
*/
-class ReflectionClassResource implements SelfCheckingResourceInterface, \Serializable
+class ReflectionClassResource implements SelfCheckingResourceInterface
{
private $files = [];
private $className;
@@ -25,7 +29,7 @@ class ReflectionClassResource implements SelfCheckingResourceInterface, \Seriali
private $excludedVendors = [];
private $hash;
- public function __construct(\ReflectionClass $classReflector, $excludedVendors = [])
+ public function __construct(\ReflectionClass $classReflector, array $excludedVendors = [])
{
$this->className = $classReflector->name;
$this->classReflector = $classReflector;
@@ -60,22 +64,14 @@ public function __toString()
/**
* @internal
*/
- public function serialize()
+ public function __sleep(): array
{
if (null === $this->hash) {
$this->hash = $this->computeHash();
$this->loadFiles($this->classReflector);
}
- return serialize([$this->files, $this->className, $this->hash]);
- }
-
- /**
- * @internal
- */
- public function unserialize($serialized)
- {
- list($this->files, $this->className, $this->hash) = unserialize($serialized);
+ return ['files', 'className', 'hash'];
}
private function loadFiles(\ReflectionClass $class)
@@ -87,7 +83,7 @@ private function loadFiles(\ReflectionClass $class)
$file = $class->getFileName();
if (false !== $file && file_exists($file)) {
foreach ($this->excludedVendors as $vendor) {
- if (0 === strpos($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
+ if (str_starts_with($file, $vendor) && false !== strpbrk(substr($file, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
$file = false;
break;
}
@@ -102,7 +98,7 @@ private function loadFiles(\ReflectionClass $class)
} while ($class = $class->getParentClass());
}
- private function computeHash()
+ private function computeHash(): string
{
if (null === $this->classReflector) {
try {
@@ -121,8 +117,17 @@ private function computeHash()
return hash_final($hash);
}
- private function generateSignature(\ReflectionClass $class)
+ private function generateSignature(\ReflectionClass $class): iterable
{
+ if (\PHP_VERSION_ID >= 80000) {
+ $attributes = [];
+ foreach ($class->getAttributes() as $a) {
+ $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()];
+ }
+ yield print_r($attributes, true);
+ $attributes = [];
+ }
+
yield $class->getDocComment();
yield (int) $class->isFinal();
yield (int) $class->isAbstract();
@@ -139,6 +144,14 @@ private function generateSignature(\ReflectionClass $class)
$defaults = $class->getDefaultProperties();
foreach ($class->getProperties(\ReflectionProperty::IS_PUBLIC | \ReflectionProperty::IS_PROTECTED) as $p) {
+ if (\PHP_VERSION_ID >= 80000) {
+ foreach ($p->getAttributes() as $a) {
+ $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()];
+ }
+ yield print_r($attributes, true);
+ $attributes = [];
+ }
+
yield $p->getDocComment();
yield $p->isDefault() ? '' : '';
yield $p->isPublic() ? 'public' : 'protected';
@@ -148,67 +161,84 @@ private function generateSignature(\ReflectionClass $class)
}
}
- if (\defined('HHVM_VERSION')) {
- foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
- // workaround HHVM bug with variadics, see https://github.com/facebook/hhvm/issues/5762
- yield preg_replace('/^ @@.*/m', '', new ReflectionMethodHhvmWrapper($m->class, $m->name));
+ $defined = \Closure::bind(static function ($c) { return \defined($c); }, null, $class->name);
+
+ foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
+ if (\PHP_VERSION_ID >= 80000) {
+ foreach ($m->getAttributes() as $a) {
+ $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()];
+ }
+ yield print_r($attributes, true);
+ $attributes = [];
}
- } else {
- foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) {
- $defaults = [];
- $parametersWithUndefinedConstants = [];
- foreach ($m->getParameters() as $p) {
- if (!$p->isDefaultValueAvailable()) {
- $defaults[$p->name] = null;
- continue;
+ $defaults = [];
+ $parametersWithUndefinedConstants = [];
+ foreach ($m->getParameters() as $p) {
+ if (\PHP_VERSION_ID >= 80000) {
+ foreach ($p->getAttributes() as $a) {
+ $attributes[] = [$a->getName(), \PHP_VERSION_ID >= 80100 ? (string) $a : $a->getArguments()];
}
+ yield print_r($attributes, true);
+ $attributes = [];
+ }
- if (!$p->isDefaultValueConstant() || \defined($p->getDefaultValueConstantName())) {
- $defaults[$p->name] = $p->getDefaultValue();
+ if (!$p->isDefaultValueAvailable()) {
+ $defaults[$p->name] = null;
- continue;
- }
+ continue;
+ }
+
+ if (\PHP_VERSION_ID >= 80100) {
+ $defaults[$p->name] = (string) $p;
- $defaults[$p->name] = $p->getDefaultValueConstantName();
- $parametersWithUndefinedConstants[$p->name] = true;
+ continue;
}
- if (!$parametersWithUndefinedConstants) {
- yield preg_replace('/^ @@.*/m', '', $m);
- } else {
- $t = \PHP_VERSION_ID >= 70000 ? $m->getReturnType() : '';
- $stack = [
- $m->getDocComment(),
- $m->getName(),
- $m->isAbstract(),
- $m->isFinal(),
- $m->isStatic(),
- $m->isPublic(),
- $m->isPrivate(),
- $m->isProtected(),
- $m->returnsReference(),
- $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t,
- ];
-
- foreach ($m->getParameters() as $p) {
- if (!isset($parametersWithUndefinedConstants[$p->name])) {
- $stack[] = (string) $p;
- } else {
- $t = \PHP_VERSION_ID >= 70000 ? $p->getType() : '';
- $stack[] = $p->isOptional();
- $stack[] = $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t;
- $stack[] = $p->isPassedByReference();
- $stack[] = \PHP_VERSION_ID >= 50600 ? $p->isVariadic() : '';
- $stack[] = $p->getName();
- }
- }
+ if (!$p->isDefaultValueConstant() || $defined($p->getDefaultValueConstantName())) {
+ $defaults[$p->name] = $p->getDefaultValue();
+
+ continue;
+ }
- yield implode(',', $stack);
+ $defaults[$p->name] = $p->getDefaultValueConstantName();
+ $parametersWithUndefinedConstants[$p->name] = true;
+ }
+
+ if (!$parametersWithUndefinedConstants) {
+ yield preg_replace('/^ @@.*/m', '', $m);
+ } else {
+ $t = $m->getReturnType();
+ $stack = [
+ $m->getDocComment(),
+ $m->getName(),
+ $m->isAbstract(),
+ $m->isFinal(),
+ $m->isStatic(),
+ $m->isPublic(),
+ $m->isPrivate(),
+ $m->isProtected(),
+ $m->returnsReference(),
+ $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t,
+ ];
+
+ foreach ($m->getParameters() as $p) {
+ if (!isset($parametersWithUndefinedConstants[$p->name])) {
+ $stack[] = (string) $p;
+ } else {
+ $t = $p->getType();
+ $stack[] = $p->isOptional();
+ $stack[] = $t instanceof \ReflectionNamedType ? ((string) $t->allowsNull()).$t->getName() : (string) $t;
+ $stack[] = $p->isPassedByReference();
+ $stack[] = $p->isVariadic();
+ $stack[] = $p->getName();
+ }
}
- yield print_r($defaults, true);
+ yield implode(',', $stack);
}
+
+ yield print_r($defaults, true);
}
if ($class->isAbstract() || $class->isInterface() || $class->isTrait()) {
@@ -217,40 +247,22 @@ private function generateSignature(\ReflectionClass $class)
if (interface_exists(EventSubscriberInterface::class, false) && $class->isSubclassOf(EventSubscriberInterface::class)) {
yield EventSubscriberInterface::class;
- yield print_r(\call_user_func([$class->name, 'getSubscribedEvents']), true);
+ yield print_r($class->name::getSubscribedEvents(), true);
}
- if (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
- yield ServiceSubscriberInterface::class;
- yield print_r(\call_user_func([$class->name, 'getSubscribedServices']), true);
+ if (interface_exists(MessageSubscriberInterface::class, false) && $class->isSubclassOf(MessageSubscriberInterface::class)) {
+ yield MessageSubscriberInterface::class;
+ foreach ($class->name::getHandledMessages() as $key => $value) {
+ yield $key.print_r($value, true);
+ }
}
- }
-}
-
-/**
- * @internal
- */
-class ReflectionMethodHhvmWrapper extends \ReflectionMethod
-{
- public function getParameters()
- {
- $params = [];
- foreach (parent::getParameters() as $i => $p) {
- $params[] = new ReflectionParameterHhvmWrapper([$this->class, $this->name], $i);
+ if (interface_exists(LegacyServiceSubscriberInterface::class, false) && $class->isSubclassOf(LegacyServiceSubscriberInterface::class)) {
+ yield LegacyServiceSubscriberInterface::class;
+ yield print_r([$class->name, 'getSubscribedServices'](), true);
+ } elseif (interface_exists(ServiceSubscriberInterface::class, false) && $class->isSubclassOf(ServiceSubscriberInterface::class)) {
+ yield ServiceSubscriberInterface::class;
+ yield print_r($class->name::getSubscribedServices(), true);
}
-
- return $params;
- }
-}
-
-/**
- * @internal
- */
-class ReflectionParameterHhvmWrapper extends \ReflectionParameter
-{
- public function getDefaultValue()
- {
- return [$this->isVariadic(), $this->isDefaultValueAvailable() ? parent::getDefaultValue() : null];
}
}
diff --git a/vendor/symfony/config/Resource/ResourceInterface.php b/vendor/symfony/config/Resource/ResourceInterface.php
index d98fd427..9a0cd9a4 100644
--- a/vendor/symfony/config/Resource/ResourceInterface.php
+++ b/vendor/symfony/config/Resource/ResourceInterface.php
@@ -26,8 +26,6 @@ interface ResourceInterface
* to be identical for different ResourceInterface instances referring to the same
* resource; and it should be unlikely to collide with that of other, unrelated
* resource instances.
- *
- * @return string A string representation unique to the underlying Resource
*/
public function __toString();
}
diff --git a/vendor/symfony/config/ResourceCheckerConfigCache.php b/vendor/symfony/config/ResourceCheckerConfigCache.php
index 0538f3f4..51311731 100644
--- a/vendor/symfony/config/ResourceCheckerConfigCache.php
+++ b/vendor/symfony/config/ResourceCheckerConfigCache.php
@@ -37,7 +37,7 @@ class ResourceCheckerConfigCache implements ConfigCacheInterface
* @param string $file The absolute cache path
* @param iterable|ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check
*/
- public function __construct($file, $resourceCheckers = [])
+ public function __construct(string $file, iterable $resourceCheckers = [])
{
$this->file = $file;
$this->resourceCheckers = $resourceCheckers;
@@ -137,28 +137,25 @@ public function write($content, array $metadata = null)
}
}
- if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) {
+ if (\function_exists('opcache_invalidate') && filter_var(\ini_get('opcache.enable'), \FILTER_VALIDATE_BOOLEAN)) {
@opcache_invalidate($this->file, true);
}
}
/**
* Gets the meta file path.
- *
- * @return string The meta file path
*/
- private function getMetaFile()
+ private function getMetaFile(): string
{
return $this->file.'.meta';
}
- private function safelyUnserialize($file)
+ private function safelyUnserialize(string $file)
{
- $e = null;
$meta = false;
$content = file_get_contents($file);
$signalingException = new \UnexpectedValueException();
- $prevUnserializeHandler = ini_set('unserialize_callback_func', '');
+ $prevUnserializeHandler = ini_set('unserialize_callback_func', self::class.'::handleUnserializeCallback');
$prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = []) use (&$prevErrorHandler, $signalingException) {
if (__FILE__ === $file) {
throw $signalingException;
@@ -169,15 +166,23 @@ private function safelyUnserialize($file)
try {
$meta = unserialize($content);
- } catch (\Error $e) {
- } catch (\Exception $e) {
- }
- restore_error_handler();
- ini_set('unserialize_callback_func', $prevUnserializeHandler);
- if (null !== $e && $e !== $signalingException) {
- throw $e;
+ } catch (\Throwable $e) {
+ if ($e !== $signalingException) {
+ throw $e;
+ }
+ } finally {
+ restore_error_handler();
+ ini_set('unserialize_callback_func', $prevUnserializeHandler);
}
return $meta;
}
+
+ /**
+ * @internal
+ */
+ public static function handleUnserializeCallback($class)
+ {
+ trigger_error('Class not found: '.$class);
+ }
}
diff --git a/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php b/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
index c00fa7db..0338635f 100644
--- a/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
+++ b/vendor/symfony/config/ResourceCheckerConfigCacheFactory.php
@@ -24,7 +24,7 @@ class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface
/**
* @param iterable|ResourceCheckerInterface[] $resourceCheckers
*/
- public function __construct($resourceCheckers = [])
+ public function __construct(iterable $resourceCheckers = [])
{
$this->resourceCheckers = $resourceCheckers;
}
@@ -40,7 +40,7 @@ public function cache($file, $callback)
$cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers);
if (!$cache->isFresh()) {
- \call_user_func($callback, $cache);
+ $callback($cache);
}
return $cache;
diff --git a/vendor/symfony/config/ResourceCheckerInterface.php b/vendor/symfony/config/ResourceCheckerInterface.php
index 612d7778..ac0d4024 100644
--- a/vendor/symfony/config/ResourceCheckerInterface.php
+++ b/vendor/symfony/config/ResourceCheckerInterface.php
@@ -30,8 +30,6 @@ interface ResourceCheckerInterface
* Queries the ResourceChecker whether it can validate a given
* resource or not.
*
- * @param ResourceInterface $metadata The resource to be checked for freshness
- *
* @return bool True if the ResourceChecker can handle this resource type, false if not
*/
public function supports(ResourceInterface $metadata);
@@ -39,8 +37,7 @@ public function supports(ResourceInterface $metadata);
/**
* Validates the resource.
*
- * @param ResourceInterface $resource The resource to be validated
- * @param int $timestamp The timestamp at which the cache associated with this resource was created
+ * @param int $timestamp The timestamp at which the cache associated with this resource was created
*
* @return bool True if the resource has not changed since the given timestamp, false otherwise
*/
diff --git a/vendor/symfony/config/Tests/ConfigCacheFactoryTest.php b/vendor/symfony/config/Tests/ConfigCacheFactoryTest.php
deleted file mode 100644
index 6190b9b4..00000000
--- a/vendor/symfony/config/Tests/ConfigCacheFactoryTest.php
+++ /dev/null
@@ -1,27 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\ConfigCacheFactory;
-
-class ConfigCacheFactoryTest extends TestCase
-{
- public function testCacheWithInvalidCallback()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('Invalid type for callback argument. Expected callable, but got "object".');
- $cacheFactory = new ConfigCacheFactory(true);
-
- $cacheFactory->cache('file', new \stdClass());
- }
-}
diff --git a/vendor/symfony/config/Tests/ConfigCacheTest.php b/vendor/symfony/config/Tests/ConfigCacheTest.php
deleted file mode 100644
index 95a58817..00000000
--- a/vendor/symfony/config/Tests/ConfigCacheTest.php
+++ /dev/null
@@ -1,99 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\ConfigCache;
-use Symfony\Component\Config\Tests\Resource\ResourceStub;
-
-class ConfigCacheTest extends TestCase
-{
- private $cacheFile = null;
-
- protected function setUp()
- {
- $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_');
- }
-
- protected function tearDown()
- {
- $files = [$this->cacheFile, $this->cacheFile.'.meta'];
-
- foreach ($files as $file) {
- if (file_exists($file)) {
- @unlink($file);
- }
- }
- }
-
- /**
- * @dataProvider debugModes
- */
- public function testCacheIsNotValidIfNothingHasBeenCached($debug)
- {
- unlink($this->cacheFile); // remove tempnam() side effect
- $cache = new ConfigCache($this->cacheFile, $debug);
-
- $this->assertFalse($cache->isFresh());
- }
-
- public function testIsAlwaysFreshInProduction()
- {
- $staleResource = new ResourceStub();
- $staleResource->setFresh(false);
-
- $cache = new ConfigCache($this->cacheFile, false);
- $cache->write('', [$staleResource]);
-
- $this->assertTrue($cache->isFresh());
- }
-
- /**
- * @dataProvider debugModes
- */
- public function testIsFreshWhenNoResourceProvided($debug)
- {
- $cache = new ConfigCache($this->cacheFile, $debug);
- $cache->write('', []);
- $this->assertTrue($cache->isFresh());
- }
-
- public function testFreshResourceInDebug()
- {
- $freshResource = new ResourceStub();
- $freshResource->setFresh(true);
-
- $cache = new ConfigCache($this->cacheFile, true);
- $cache->write('', [$freshResource]);
-
- $this->assertTrue($cache->isFresh());
- }
-
- public function testStaleResourceInDebug()
- {
- $staleResource = new ResourceStub();
- $staleResource->setFresh(false);
-
- $cache = new ConfigCache($this->cacheFile, true);
- $cache->write('', [$staleResource]);
-
- $this->assertFalse($cache->isFresh());
- }
-
- public function debugModes()
- {
- return [
- [true],
- [false],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/ArrayNodeTest.php b/vendor/symfony/config/Tests/Definition/ArrayNodeTest.php
deleted file mode 100644
index f726e8dd..00000000
--- a/vendor/symfony/config/Tests/Definition/ArrayNodeTest.php
+++ /dev/null
@@ -1,237 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\ArrayNode;
-use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
-use Symfony\Component\Config\Definition\ScalarNode;
-
-class ArrayNodeTest extends TestCase
-{
- public function testNormalizeThrowsExceptionWhenFalseIsNotAllowed()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $node = new ArrayNode('root');
- $node->normalize(false);
- }
-
- public function testExceptionThrownOnUnrecognizedChild()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('Unrecognized option "foo" under "root"');
- $node = new ArrayNode('root');
- $node->normalize(['foo' => 'bar']);
- }
-
- public function ignoreAndRemoveMatrixProvider()
- {
- $unrecognizedOptionException = new InvalidConfigurationException('Unrecognized option "foo" under "root"');
-
- return [
- [true, true, [], 'no exception is thrown for an unrecognized child if the ignoreExtraKeys option is set to true'],
- [true, false, ['foo' => 'bar'], 'extra keys are not removed when ignoreExtraKeys second option is set to false'],
- [false, true, $unrecognizedOptionException],
- [false, false, $unrecognizedOptionException],
- ];
- }
-
- /**
- * @dataProvider ignoreAndRemoveMatrixProvider
- */
- public function testIgnoreAndRemoveBehaviors($ignore, $remove, $expected, $message = '')
- {
- if ($expected instanceof \Exception) {
- $this->expectException(\get_class($expected));
- $this->expectExceptionMessage($expected->getMessage());
- }
- $node = new ArrayNode('root');
- $node->setIgnoreExtraKeys($ignore, $remove);
- $result = $node->normalize(['foo' => 'bar']);
- $this->assertSame($expected, $result, $message);
- }
-
- /**
- * @dataProvider getPreNormalizationTests
- */
- public function testPreNormalize($denormalized, $normalized)
- {
- $node = new ArrayNode('foo');
-
- $r = new \ReflectionMethod($node, 'preNormalize');
- $r->setAccessible(true);
-
- $this->assertSame($normalized, $r->invoke($node, $denormalized));
- }
-
- public function getPreNormalizationTests()
- {
- return [
- [
- ['foo-bar' => 'foo'],
- ['foo_bar' => 'foo'],
- ],
- [
- ['foo-bar_moo' => 'foo'],
- ['foo-bar_moo' => 'foo'],
- ],
- [
- ['anything-with-dash-and-no-underscore' => 'first', 'no_dash' => 'second'],
- ['anything_with_dash_and_no_underscore' => 'first', 'no_dash' => 'second'],
- ],
- [
- ['foo-bar' => null, 'foo_bar' => 'foo'],
- ['foo-bar' => null, 'foo_bar' => 'foo'],
- ],
- ];
- }
-
- /**
- * @dataProvider getZeroNamedNodeExamplesData
- */
- public function testNodeNameCanBeZero($denormalized, $normalized)
- {
- $zeroNode = new ArrayNode(0);
- $zeroNode->addChild(new ScalarNode('name'));
- $fiveNode = new ArrayNode(5);
- $fiveNode->addChild(new ScalarNode(0));
- $fiveNode->addChild(new ScalarNode('new_key'));
- $rootNode = new ArrayNode('root');
- $rootNode->addChild($zeroNode);
- $rootNode->addChild($fiveNode);
- $rootNode->addChild(new ScalarNode('string_key'));
- $r = new \ReflectionMethod($rootNode, 'normalizeValue');
- $r->setAccessible(true);
-
- $this->assertSame($normalized, $r->invoke($rootNode, $denormalized));
- }
-
- public function getZeroNamedNodeExamplesData()
- {
- return [
- [
- [
- 0 => [
- 'name' => 'something',
- ],
- 5 => [
- 0 => 'this won\'t work too',
- 'new_key' => 'some other value',
- ],
- 'string_key' => 'just value',
- ],
- [
- 0 => [
- 'name' => 'something',
- ],
- 5 => [
- 0 => 'this won\'t work too',
- 'new_key' => 'some other value',
- ],
- 'string_key' => 'just value',
- ],
- ],
- ];
- }
-
- /**
- * @dataProvider getPreNormalizedNormalizedOrderedData
- */
- public function testChildrenOrderIsMaintainedOnNormalizeValue($prenormalized, $normalized)
- {
- $scalar1 = new ScalarNode('1');
- $scalar2 = new ScalarNode('2');
- $scalar3 = new ScalarNode('3');
- $node = new ArrayNode('foo');
- $node->addChild($scalar1);
- $node->addChild($scalar3);
- $node->addChild($scalar2);
-
- $r = new \ReflectionMethod($node, 'normalizeValue');
- $r->setAccessible(true);
-
- $this->assertSame($normalized, $r->invoke($node, $prenormalized));
- }
-
- public function getPreNormalizedNormalizedOrderedData()
- {
- return [
- [
- ['2' => 'two', '1' => 'one', '3' => 'three'],
- ['2' => 'two', '1' => 'one', '3' => 'three'],
- ],
- ];
- }
-
- public function testAddChildEmptyName()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('Child nodes must be named.');
- $node = new ArrayNode('root');
-
- $childNode = new ArrayNode('');
- $node->addChild($childNode);
- }
-
- public function testAddChildNameAlreadyExists()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('A child node named "foo" already exists.');
- $node = new ArrayNode('root');
-
- $childNode = new ArrayNode('foo');
- $node->addChild($childNode);
-
- $childNodeWithSameName = new ArrayNode('foo');
- $node->addChild($childNodeWithSameName);
- }
-
- public function testGetDefaultValueWithoutDefaultValue()
- {
- $this->expectException('RuntimeException');
- $this->expectExceptionMessage('The node at path "foo" has no default value.');
- $node = new ArrayNode('foo');
- $node->getDefaultValue();
- }
-
- public function testSetDeprecated()
- {
- $childNode = new ArrayNode('foo');
- $childNode->setDeprecated('"%node%" is deprecated');
-
- $this->assertTrue($childNode->isDeprecated());
- $this->assertSame('"foo" is deprecated', $childNode->getDeprecationMessage($childNode->getName(), $childNode->getPath()));
-
- $node = new ArrayNode('root');
- $node->addChild($childNode);
-
- $deprecationTriggered = false;
- $deprecationHandler = function ($level, $message, $file, $line) use (&$prevErrorHandler, &$deprecationTriggered) {
- if (\E_USER_DEPRECATED === $level) {
- return $deprecationTriggered = true;
- }
-
- return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
- };
-
- $prevErrorHandler = set_error_handler($deprecationHandler);
- $node->finalize([]);
- restore_error_handler();
-
- $this->assertFalse($deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set');
-
- $prevErrorHandler = set_error_handler($deprecationHandler);
- $node->finalize(['foo' => []]);
- restore_error_handler();
- $this->assertTrue($deprecationTriggered, '->finalize() should trigger if the deprecated node is set');
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/BooleanNodeTest.php b/vendor/symfony/config/Tests/Definition/BooleanNodeTest.php
deleted file mode 100644
index 8552eeba..00000000
--- a/vendor/symfony/config/Tests/Definition/BooleanNodeTest.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\BooleanNode;
-
-class BooleanNodeTest extends TestCase
-{
- /**
- * @dataProvider getValidValues
- */
- public function testNormalize($value)
- {
- $node = new BooleanNode('test');
- $this->assertSame($value, $node->normalize($value));
- }
-
- /**
- * @dataProvider getValidValues
- *
- * @param bool $value
- */
- public function testValidNonEmptyValues($value)
- {
- $node = new BooleanNode('test');
- $node->setAllowEmptyValue(false);
-
- $this->assertSame($value, $node->finalize($value));
- }
-
- public function getValidValues()
- {
- return [
- [false],
- [true],
- ];
- }
-
- /**
- * @dataProvider getInvalidValues
- */
- public function testNormalizeThrowsExceptionOnInvalidValues($value)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $node = new BooleanNode('test');
- $node->normalize($value);
- }
-
- public function getInvalidValues()
- {
- return [
- [null],
- [''],
- ['foo'],
- [0],
- [1],
- [0.0],
- [0.1],
- [[]],
- [['foo' => 'bar']],
- [new \stdClass()],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php b/vendor/symfony/config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php
deleted file mode 100644
index 1123b415..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php
+++ /dev/null
@@ -1,362 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
-use Symfony\Component\Config\Definition\Builder\ScalarNodeDefinition;
-use Symfony\Component\Config\Definition\Exception\InvalidDefinitionException;
-use Symfony\Component\Config\Definition\Processor;
-
-class ArrayNodeDefinitionTest extends TestCase
-{
- public function testAppendingSomeNode()
- {
- $parent = new ArrayNodeDefinition('root');
- $child = new ScalarNodeDefinition('child');
-
- $parent
- ->children()
- ->scalarNode('foo')->end()
- ->scalarNode('bar')->end()
- ->end()
- ->append($child);
-
- $this->assertCount(3, $this->getField($parent, 'children'));
- $this->assertContains($child, $this->getField($parent, 'children'));
- }
-
- /**
- * @dataProvider providePrototypeNodeSpecificCalls
- */
- public function testPrototypeNodeSpecificOption($method, $args)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidDefinitionException');
- $node = new ArrayNodeDefinition('root');
-
- \call_user_func_array([$node, $method], $args);
-
- $node->getNode();
- }
-
- public function providePrototypeNodeSpecificCalls()
- {
- return [
- ['defaultValue', [[]]],
- ['addDefaultChildrenIfNoneSet', []],
- ['requiresAtLeastOneElement', []],
- ['useAttributeAsKey', ['foo']],
- ];
- }
-
- public function testConcreteNodeSpecificOption()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidDefinitionException');
- $node = new ArrayNodeDefinition('root');
- $node
- ->addDefaultsIfNotSet()
- ->prototype('array')
- ;
- $node->getNode();
- }
-
- public function testPrototypeNodesCantHaveADefaultValueWhenUsingDefaultChildren()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidDefinitionException');
- $node = new ArrayNodeDefinition('root');
- $node
- ->defaultValue([])
- ->addDefaultChildrenIfNoneSet('foo')
- ->prototype('array')
- ;
- $node->getNode();
- }
-
- public function testPrototypedArrayNodeDefaultWhenUsingDefaultChildren()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->addDefaultChildrenIfNoneSet()
- ->prototype('array')
- ;
- $tree = $node->getNode();
- $this->assertEquals([[]], $tree->getDefaultValue());
- }
-
- /**
- * @dataProvider providePrototypedArrayNodeDefaults
- */
- public function testPrototypedArrayNodeDefault($args, $shouldThrowWhenUsingAttrAsKey, $shouldThrowWhenNotUsingAttrAsKey, $defaults)
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->addDefaultChildrenIfNoneSet($args)
- ->prototype('array')
- ;
-
- try {
- $tree = $node->getNode();
- $this->assertFalse($shouldThrowWhenNotUsingAttrAsKey);
- $this->assertEquals($defaults, $tree->getDefaultValue());
- } catch (InvalidDefinitionException $e) {
- $this->assertTrue($shouldThrowWhenNotUsingAttrAsKey);
- }
-
- $node = new ArrayNodeDefinition('root');
- $node
- ->useAttributeAsKey('attr')
- ->addDefaultChildrenIfNoneSet($args)
- ->prototype('array')
- ;
-
- try {
- $tree = $node->getNode();
- $this->assertFalse($shouldThrowWhenUsingAttrAsKey);
- $this->assertEquals($defaults, $tree->getDefaultValue());
- } catch (InvalidDefinitionException $e) {
- $this->assertTrue($shouldThrowWhenUsingAttrAsKey);
- }
- }
-
- public function providePrototypedArrayNodeDefaults()
- {
- return [
- [null, true, false, [[]]],
- [2, true, false, [[], []]],
- ['2', false, true, ['2' => []]],
- ['foo', false, true, ['foo' => []]],
- [['foo'], false, true, ['foo' => []]],
- [['foo', 'bar'], false, true, ['foo' => [], 'bar' => []]],
- ];
- }
-
- public function testNestedPrototypedArrayNodes()
- {
- $nodeDefinition = new ArrayNodeDefinition('root');
- $nodeDefinition
- ->addDefaultChildrenIfNoneSet()
- ->prototype('array')
- ->prototype('array')
- ;
- $node = $nodeDefinition->getNode();
-
- $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node);
- $this->assertInstanceOf('Symfony\Component\Config\Definition\PrototypedArrayNode', $node->getPrototype());
- }
-
- public function testEnabledNodeDefaults()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->canBeEnabled()
- ->children()
- ->scalarNode('foo')->defaultValue('bar')->end()
- ;
-
- $this->assertEquals(['enabled' => false, 'foo' => 'bar'], $node->getNode()->getDefaultValue());
- }
-
- /**
- * @dataProvider getEnableableNodeFixtures
- */
- public function testTrueEnableEnabledNode($expected, $config, $message)
- {
- $processor = new Processor();
- $node = new ArrayNodeDefinition('root');
- $node
- ->canBeEnabled()
- ->children()
- ->scalarNode('foo')->defaultValue('bar')->end()
- ;
-
- $this->assertEquals(
- $expected,
- $processor->process($node->getNode(), $config),
- $message
- );
- }
-
- public function testCanBeDisabled()
- {
- $node = new ArrayNodeDefinition('root');
- $node->canBeDisabled();
-
- $this->assertTrue($this->getField($node, 'addDefaults'));
- $this->assertEquals(['enabled' => false], $this->getField($node, 'falseEquivalent'));
- $this->assertEquals(['enabled' => true], $this->getField($node, 'trueEquivalent'));
- $this->assertEquals(['enabled' => true], $this->getField($node, 'nullEquivalent'));
-
- $nodeChildren = $this->getField($node, 'children');
- $this->assertArrayHasKey('enabled', $nodeChildren);
-
- $enabledNode = $nodeChildren['enabled'];
- $this->assertTrue($this->getField($enabledNode, 'default'));
- $this->assertTrue($this->getField($enabledNode, 'defaultValue'));
- }
-
- public function testIgnoreExtraKeys()
- {
- $node = new ArrayNodeDefinition('root');
-
- $this->assertFalse($this->getField($node, 'ignoreExtraKeys'));
-
- $result = $node->ignoreExtraKeys();
-
- $this->assertEquals($node, $result);
- $this->assertTrue($this->getField($node, 'ignoreExtraKeys'));
- }
-
- public function testNormalizeKeys()
- {
- $node = new ArrayNodeDefinition('root');
-
- $this->assertTrue($this->getField($node, 'normalizeKeys'));
-
- $result = $node->normalizeKeys(false);
-
- $this->assertEquals($node, $result);
- $this->assertFalse($this->getField($node, 'normalizeKeys'));
- }
-
- public function testUnsetChild()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->children()
- ->scalarNode('value')
- ->beforeNormalization()
- ->ifTrue(function ($value) {
- return empty($value);
- })
- ->thenUnset()
- ->end()
- ->end()
- ->end()
- ;
-
- $this->assertSame([], $node->getNode()->normalize(['value' => null]));
- }
-
- public function testPrototypeVariable()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('variable'), $node->variablePrototype());
- }
-
- public function testPrototypeScalar()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('scalar'), $node->scalarPrototype());
- }
-
- public function testPrototypeBoolean()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('boolean'), $node->booleanPrototype());
- }
-
- public function testPrototypeInteger()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('integer'), $node->integerPrototype());
- }
-
- public function testPrototypeFloat()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('float'), $node->floatPrototype());
- }
-
- public function testPrototypeArray()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('array'), $node->arrayPrototype());
- }
-
- public function testPrototypeEnum()
- {
- $node = new ArrayNodeDefinition('root');
- $this->assertEquals($node->prototype('enum'), $node->enumPrototype());
- }
-
- public function getEnableableNodeFixtures()
- {
- return [
- [['enabled' => true, 'foo' => 'bar'], [true], 'true enables an enableable node'],
- [['enabled' => true, 'foo' => 'bar'], [null], 'null enables an enableable node'],
- [['enabled' => true, 'foo' => 'bar'], [['enabled' => true]], 'An enableable node can be enabled'],
- [['enabled' => true, 'foo' => 'baz'], [['foo' => 'baz']], 'any configuration enables an enableable node'],
- [['enabled' => false, 'foo' => 'baz'], [['foo' => 'baz', 'enabled' => false]], 'An enableable node can be disabled'],
- [['enabled' => false, 'foo' => 'bar'], [false], 'false disables an enableable node'],
- ];
- }
-
- public function testRequiresAtLeastOneElement()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->requiresAtLeastOneElement()
- ->integerPrototype();
-
- $node->getNode()->finalize([1]);
-
- $this->addToAssertionCount(1);
- }
-
- /**
- * @group legacy
- * @expectedDeprecation Using Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition::cannotBeEmpty() at path "root" has no effect, consider requiresAtLeastOneElement() instead. In 4.0 both methods will behave the same.
- */
- public function testCannotBeEmpty()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->cannotBeEmpty()
- ->integerPrototype();
-
- $node->getNode()->finalize([]);
- }
-
- public function testSetDeprecated()
- {
- $node = new ArrayNodeDefinition('root');
- $node
- ->children()
- ->arrayNode('foo')->setDeprecated('The "%path%" node is deprecated.')->end()
- ->end()
- ;
- $deprecatedNode = $node->getNode()->getChildren()['foo'];
-
- $this->assertTrue($deprecatedNode->isDeprecated());
- $this->assertSame('The "root.foo" node is deprecated.', $deprecatedNode->getDeprecationMessage($deprecatedNode->getName(), $deprecatedNode->getPath()));
- }
-
- /**
- * @group legacy
- * @expectedDeprecation ->cannotBeEmpty() is not applicable to concrete nodes at path "root". In 4.0 it will throw an exception.
- */
- public function testCannotBeEmptyOnConcreteNode()
- {
- $node = new ArrayNodeDefinition('root');
- $node->cannotBeEmpty();
-
- $node->getNode()->finalize([]);
- }
-
- protected function getField($object, $field)
- {
- $reflection = new \ReflectionProperty($object, $field);
- $reflection->setAccessible(true);
-
- return $reflection->getValue($object);
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php b/vendor/symfony/config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php
deleted file mode 100644
index 6f568a2d..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php
+++ /dev/null
@@ -1,37 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition;
-
-class BooleanNodeDefinitionTest extends TestCase
-{
- public function testCannotBeEmptyThrowsAnException()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidDefinitionException');
- $this->expectExceptionMessage('->cannotBeEmpty() is not applicable to BooleanNodeDefinition.');
- $def = new BooleanNodeDefinition('foo');
- $def->cannotBeEmpty();
- }
-
- public function testSetDeprecated()
- {
- $def = new BooleanNodeDefinition('foo');
- $def->setDeprecated('The "%path%" node is deprecated.');
-
- $node = $def->getNode();
-
- $this->assertTrue($node->isDeprecated());
- $this->assertSame('The "foo" node is deprecated.', $node->getDeprecationMessage($node->getName(), $node->getPath()));
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/EnumNodeDefinitionTest.php b/vendor/symfony/config/Tests/Definition/Builder/EnumNodeDefinitionTest.php
deleted file mode 100644
index 2e43a135..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/EnumNodeDefinitionTest.php
+++ /dev/null
@@ -1,73 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\EnumNodeDefinition;
-
-class EnumNodeDefinitionTest extends TestCase
-{
- public function testWithOneValue()
- {
- $def = new EnumNodeDefinition('foo');
- $def->values(['foo']);
-
- $node = $def->getNode();
- $this->assertEquals(['foo'], $node->getValues());
- }
-
- public function testWithOneDistinctValue()
- {
- $def = new EnumNodeDefinition('foo');
- $def->values(['foo', 'foo']);
-
- $node = $def->getNode();
- $this->assertEquals(['foo'], $node->getValues());
- }
-
- public function testNoValuesPassed()
- {
- $this->expectException('RuntimeException');
- $this->expectExceptionMessage('You must call ->values() on enum nodes.');
- $def = new EnumNodeDefinition('foo');
- $def->getNode();
- }
-
- public function testWithNoValues()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('->values() must be called with at least one value.');
- $def = new EnumNodeDefinition('foo');
- $def->values([]);
- }
-
- public function testGetNode()
- {
- $def = new EnumNodeDefinition('foo');
- $def->values(['foo', 'bar']);
-
- $node = $def->getNode();
- $this->assertEquals(['foo', 'bar'], $node->getValues());
- }
-
- public function testSetDeprecated()
- {
- $def = new EnumNodeDefinition('foo');
- $def->values(['foo', 'bar']);
- $def->setDeprecated('The "%path%" node is deprecated.');
-
- $node = $def->getNode();
-
- $this->assertTrue($node->isDeprecated());
- $this->assertSame('The "foo" node is deprecated.', $def->getNode()->getDeprecationMessage($node->getName(), $node->getPath()));
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/ExprBuilderTest.php b/vendor/symfony/config/Tests/Definition/Builder/ExprBuilderTest.php
deleted file mode 100644
index 2dfb7a0a..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/ExprBuilderTest.php
+++ /dev/null
@@ -1,264 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-
-class ExprBuilderTest extends TestCase
-{
- public function testAlwaysExpression()
- {
- $test = $this->getTestBuilder()
- ->always($this->returnClosure('new_value'))
- ->end();
-
- $this->assertFinalizedValueIs('new_value', $test);
- }
-
- public function testIfTrueExpression()
- {
- $test = $this->getTestBuilder()
- ->ifTrue()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test, ['key' => true]);
-
- $test = $this->getTestBuilder()
- ->ifTrue(function ($v) { return true; })
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test);
-
- $test = $this->getTestBuilder()
- ->ifTrue(function ($v) { return false; })
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('value', $test);
- }
-
- public function testIfStringExpression()
- {
- $test = $this->getTestBuilder()
- ->ifString()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test);
-
- $test = $this->getTestBuilder()
- ->ifString()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs(45, $test, ['key' => 45]);
- }
-
- public function testIfNullExpression()
- {
- $test = $this->getTestBuilder()
- ->ifNull()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test, ['key' => null]);
-
- $test = $this->getTestBuilder()
- ->ifNull()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('value', $test);
- }
-
- public function testIfEmptyExpression()
- {
- $test = $this->getTestBuilder()
- ->ifEmpty()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test, ['key' => []]);
-
- $test = $this->getTestBuilder()
- ->ifEmpty()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('value', $test);
- }
-
- public function testIfArrayExpression()
- {
- $test = $this->getTestBuilder()
- ->ifArray()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test, ['key' => []]);
-
- $test = $this->getTestBuilder()
- ->ifArray()
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('value', $test);
- }
-
- public function testIfInArrayExpression()
- {
- $test = $this->getTestBuilder()
- ->ifInArray(['foo', 'bar', 'value'])
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test);
-
- $test = $this->getTestBuilder()
- ->ifInArray(['foo', 'bar'])
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('value', $test);
- }
-
- public function testIfNotInArrayExpression()
- {
- $test = $this->getTestBuilder()
- ->ifNotInArray(['foo', 'bar'])
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test);
-
- $test = $this->getTestBuilder()
- ->ifNotInArray(['foo', 'bar', 'value_from_config'])
- ->then($this->returnClosure('new_value'))
- ->end();
- $this->assertFinalizedValueIs('new_value', $test);
- }
-
- public function testThenEmptyArrayExpression()
- {
- $test = $this->getTestBuilder()
- ->ifString()
- ->thenEmptyArray()
- ->end();
- $this->assertFinalizedValueIs([], $test);
- }
-
- /**
- * @dataProvider castToArrayValues
- */
- public function testCastToArrayExpression($configValue, $expectedValue)
- {
- $test = $this->getTestBuilder()
- ->castToArray()
- ->end();
- $this->assertFinalizedValueIs($expectedValue, $test, ['key' => $configValue]);
- }
-
- public function castToArrayValues()
- {
- yield ['value', ['value']];
- yield [-3.14, [-3.14]];
- yield [null, [null]];
- yield [['value'], ['value']];
- }
-
- public function testThenInvalid()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $test = $this->getTestBuilder()
- ->ifString()
- ->thenInvalid('Invalid value')
- ->end();
- $this->finalizeTestBuilder($test);
- }
-
- public function testThenUnsetExpression()
- {
- $test = $this->getTestBuilder()
- ->ifString()
- ->thenUnset()
- ->end();
- $this->assertEquals([], $this->finalizeTestBuilder($test));
- }
-
- public function testEndIfPartNotSpecified()
- {
- $this->expectException('RuntimeException');
- $this->expectExceptionMessage('You must specify an if part.');
- $this->getTestBuilder()->end();
- }
-
- public function testEndThenPartNotSpecified()
- {
- $this->expectException('RuntimeException');
- $this->expectExceptionMessage('You must specify a then part.');
- $builder = $this->getTestBuilder();
- $builder->ifPart = 'test';
- $builder->end();
- }
-
- /**
- * Create a test treebuilder with a variable node, and init the validation.
- *
- * @return TreeBuilder
- */
- protected function getTestBuilder()
- {
- $builder = new TreeBuilder();
-
- return $builder
- ->root('test')
- ->children()
- ->variableNode('key')
- ->validate()
- ;
- }
-
- /**
- * Close the validation process and finalize with the given config.
- *
- * @param TreeBuilder $testBuilder The tree builder to finalize
- * @param array $config The config you want to use for the finalization, if nothing provided
- * a simple ['key'=>'value'] will be used
- *
- * @return array The finalized config values
- */
- protected function finalizeTestBuilder($testBuilder, $config = null)
- {
- return $testBuilder
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ->finalize(null === $config ? ['key' => 'value'] : $config)
- ;
- }
-
- /**
- * Return a closure that will return the given value.
- *
- * @param mixed $val The value that the closure must return
- *
- * @return \Closure
- */
- protected function returnClosure($val)
- {
- return function ($v) use ($val) {
- return $val;
- };
- }
-
- /**
- * Assert that the given test builder, will return the given value.
- *
- * @param mixed $value The value to test
- * @param TreeBuilder $treeBuilder The tree builder to finalize
- * @param mixed $config The config values that new to be finalized
- */
- protected function assertFinalizedValueIs($value, $treeBuilder, $config = null)
- {
- $this->assertEquals(['key' => $value], $this->finalizeTestBuilder($treeBuilder, $config));
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/NodeBuilderTest.php b/vendor/symfony/config/Tests/Definition/Builder/NodeBuilderTest.php
deleted file mode 100644
index 46518c65..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/NodeBuilderTest.php
+++ /dev/null
@@ -1,91 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;
-use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;
-
-class NodeBuilderTest extends TestCase
-{
- public function testThrowsAnExceptionWhenTryingToCreateANonRegisteredNodeType()
- {
- $this->expectException('RuntimeException');
- $builder = new BaseNodeBuilder();
- $builder->node('', 'foobar');
- }
-
- public function testThrowsAnExceptionWhenTheNodeClassIsNotFound()
- {
- $this->expectException('RuntimeException');
- $builder = new BaseNodeBuilder();
- $builder
- ->setNodeClass('noclasstype', '\\foo\\bar\\noclass')
- ->node('', 'noclasstype');
- }
-
- public function testAddingANewNodeType()
- {
- $class = SomeNodeDefinition::class;
-
- $builder = new BaseNodeBuilder();
- $node = $builder
- ->setNodeClass('newtype', $class)
- ->node('', 'newtype');
-
- $this->assertInstanceOf($class, $node);
- }
-
- public function testOverridingAnExistingNodeType()
- {
- $class = SomeNodeDefinition::class;
-
- $builder = new BaseNodeBuilder();
- $node = $builder
- ->setNodeClass('variable', $class)
- ->node('', 'variable');
-
- $this->assertInstanceOf($class, $node);
- }
-
- public function testNodeTypesAreNotCaseSensitive()
- {
- $builder = new BaseNodeBuilder();
-
- $node1 = $builder->node('', 'VaRiAbLe');
- $node2 = $builder->node('', 'variable');
-
- $this->assertInstanceOf(\get_class($node1), $node2);
-
- $builder->setNodeClass('CuStOm', SomeNodeDefinition::class);
-
- $node1 = $builder->node('', 'CUSTOM');
- $node2 = $builder->node('', 'custom');
-
- $this->assertInstanceOf(\get_class($node1), $node2);
- }
-
- public function testNumericNodeCreation()
- {
- $builder = new BaseNodeBuilder();
-
- $node = $builder->integerNode('foo')->min(3)->max(5);
- $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition', $node);
-
- $node = $builder->floatNode('bar')->min(3.0)->max(5.0);
- $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\FloatNodeDefinition', $node);
- }
-}
-
-class SomeNodeDefinition extends BaseVariableNodeDefinition
-{
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/NumericNodeDefinitionTest.php b/vendor/symfony/config/Tests/Definition/Builder/NumericNodeDefinitionTest.php
deleted file mode 100644
index aa938bba..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/NumericNodeDefinitionTest.php
+++ /dev/null
@@ -1,89 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\FloatNodeDefinition;
-use Symfony\Component\Config\Definition\Builder\IntegerNodeDefinition;
-
-class NumericNodeDefinitionTest extends TestCase
-{
- public function testIncoherentMinAssertion()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('You cannot define a min(4) as you already have a max(3)');
- $def = new IntegerNodeDefinition('foo');
- $def->max(3)->min(4);
- }
-
- public function testIncoherentMaxAssertion()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('You cannot define a max(2) as you already have a min(3)');
- $node = new IntegerNodeDefinition('foo');
- $node->min(3)->max(2);
- }
-
- public function testIntegerMinAssertion()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The value 4 is too small for path "foo". Should be greater than or equal to 5');
- $def = new IntegerNodeDefinition('foo');
- $def->min(5)->getNode()->finalize(4);
- }
-
- public function testIntegerMaxAssertion()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The value 4 is too big for path "foo". Should be less than or equal to 3');
- $def = new IntegerNodeDefinition('foo');
- $def->max(3)->getNode()->finalize(4);
- }
-
- public function testIntegerValidMinMaxAssertion()
- {
- $def = new IntegerNodeDefinition('foo');
- $node = $def->min(3)->max(7)->getNode();
- $this->assertEquals(4, $node->finalize(4));
- }
-
- public function testFloatMinAssertion()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The value 400 is too small for path "foo". Should be greater than or equal to 500');
- $def = new FloatNodeDefinition('foo');
- $def->min(5E2)->getNode()->finalize(4e2);
- }
-
- public function testFloatMaxAssertion()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The value 4.3 is too big for path "foo". Should be less than or equal to 0.3');
- $def = new FloatNodeDefinition('foo');
- $def->max(0.3)->getNode()->finalize(4.3);
- }
-
- public function testFloatValidMinMaxAssertion()
- {
- $def = new FloatNodeDefinition('foo');
- $node = $def->min(3.0)->max(7e2)->getNode();
- $this->assertEquals(4.5, $node->finalize(4.5));
- }
-
- public function testCannotBeEmptyThrowsAnException()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidDefinitionException');
- $this->expectExceptionMessage('->cannotBeEmpty() is not applicable to NumericNodeDefinition.');
- $def = new IntegerNodeDefinition('foo');
- $def->cannotBeEmpty();
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Builder/TreeBuilderTest.php b/vendor/symfony/config/Tests/Definition/Builder/TreeBuilderTest.php
deleted file mode 100644
index 53c9c256..00000000
--- a/vendor/symfony/config/Tests/Definition/Builder/TreeBuilderTest.php
+++ /dev/null
@@ -1,134 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Builder;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder as CustomNodeBuilder;
-
-class TreeBuilderTest extends TestCase
-{
- public function testUsingACustomNodeBuilder()
- {
- $builder = new TreeBuilder();
- $root = $builder->root('custom', 'array', new CustomNodeBuilder());
-
- $nodeBuilder = $root->children();
-
- $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder', $nodeBuilder);
-
- $nodeBuilder = $nodeBuilder->arrayNode('deeper')->children();
-
- $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\NodeBuilder', $nodeBuilder);
- }
-
- public function testOverrideABuiltInNodeType()
- {
- $builder = new TreeBuilder();
- $root = $builder->root('override', 'array', new CustomNodeBuilder());
-
- $definition = $root->children()->variableNode('variable');
-
- $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\VariableNodeDefinition', $definition);
- }
-
- public function testAddANodeType()
- {
- $builder = new TreeBuilder();
- $root = $builder->root('override', 'array', new CustomNodeBuilder());
-
- $definition = $root->children()->barNode('variable');
-
- $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\Builder\BarNodeDefinition', $definition);
- }
-
- public function testCreateABuiltInNodeTypeWithACustomNodeBuilder()
- {
- $builder = new TreeBuilder();
- $root = $builder->root('builtin', 'array', new CustomNodeBuilder());
-
- $definition = $root->children()->booleanNode('boolean');
-
- $this->assertInstanceOf('Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition', $definition);
- }
-
- public function testPrototypedArrayNodeUseTheCustomNodeBuilder()
- {
- $builder = new TreeBuilder();
- $root = $builder->root('override', 'array', new CustomNodeBuilder());
-
- $root->prototype('bar')->end();
-
- $this->assertInstanceOf('Symfony\Component\Config\Tests\Fixtures\BarNode', $root->getNode(true)->getPrototype());
- }
-
- public function testAnExtendedNodeBuilderGetsPropagatedToTheChildren()
- {
- $builder = new TreeBuilder();
-
- $builder->root('propagation')
- ->children()
- ->setNodeClass('extended', 'Symfony\Component\Config\Definition\Builder\BooleanNodeDefinition')
- ->node('foo', 'extended')->end()
- ->arrayNode('child')
- ->children()
- ->node('foo', 'extended')
- ->end()
- ->end()
- ->end()
- ->end();
-
- $node = $builder->buildTree();
- $children = $node->getChildren();
-
- $this->assertInstanceOf('Symfony\Component\Config\Definition\BooleanNode', $children['foo']);
-
- $childChildren = $children['child']->getChildren();
-
- $this->assertInstanceOf('Symfony\Component\Config\Definition\BooleanNode', $childChildren['foo']);
- }
-
- public function testDefinitionInfoGetsTransferredToNode()
- {
- $builder = new TreeBuilder();
-
- $builder->root('test')->info('root info')
- ->children()
- ->node('child', 'variable')->info('child info')->defaultValue('default')
- ->end()
- ->end();
-
- $tree = $builder->buildTree();
- $children = $tree->getChildren();
-
- $this->assertEquals('root info', $tree->getInfo());
- $this->assertEquals('child info', $children['child']->getInfo());
- }
-
- public function testDefinitionExampleGetsTransferredToNode()
- {
- $builder = new TreeBuilder();
-
- $builder->root('test')
- ->example(['key' => 'value'])
- ->children()
- ->node('child', 'variable')->info('child info')->defaultValue('default')->example('example')
- ->end()
- ->end();
-
- $tree = $builder->buildTree();
- $children = $tree->getChildren();
-
- $this->assertIsArray($tree->getExample());
- $this->assertEquals('example', $children['child']->getExample());
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Dumper/XmlReferenceDumperTest.php b/vendor/symfony/config/Tests/Definition/Dumper/XmlReferenceDumperTest.php
deleted file mode 100644
index 1bd60215..00000000
--- a/vendor/symfony/config/Tests/Definition/Dumper/XmlReferenceDumperTest.php
+++ /dev/null
@@ -1,114 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Dumper;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Dumper\XmlReferenceDumper;
-use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;
-
-class XmlReferenceDumperTest extends TestCase
-{
- public function testDumper()
- {
- $configuration = new ExampleConfiguration();
-
- $dumper = new XmlReferenceDumper();
- $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
- }
-
- public function testNamespaceDumper()
- {
- $configuration = new ExampleConfiguration();
-
- $dumper = new XmlReferenceDumper();
- $this->assertEquals(str_replace('http://example.org/schema/dic/acme_root', 'http://symfony.com/schema/dic/symfony', $this->getConfigurationAsString()), $dumper->dump($configuration, 'http://symfony.com/schema/dic/symfony'));
- }
-
- private function getConfigurationAsString()
- {
- return str_replace("\n", \PHP_EOL, <<<'EOL'
-
-
-
-
-
-
-
-
-
-
-
-
-
- scalar value
-
-
- scalar value
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-EOL
- );
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/Dumper/YamlReferenceDumperTest.php b/vendor/symfony/config/Tests/Definition/Dumper/YamlReferenceDumperTest.php
deleted file mode 100644
index 3cb9121b..00000000
--- a/vendor/symfony/config/Tests/Definition/Dumper/YamlReferenceDumperTest.php
+++ /dev/null
@@ -1,143 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition\Dumper;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Dumper\YamlReferenceDumper;
-use Symfony\Component\Config\Tests\Fixtures\Configuration\ExampleConfiguration;
-
-class YamlReferenceDumperTest extends TestCase
-{
- public function testDumper()
- {
- $configuration = new ExampleConfiguration();
-
- $dumper = new YamlReferenceDumper();
-
- $this->assertEquals($this->getConfigurationAsString(), $dumper->dump($configuration));
- }
-
- public function provideDumpAtPath()
- {
- return [
- 'Regular node' => ['scalar_true', << ['array', << ['array.child2', << ['cms_pages.page', << ['cms_pages.page.locale', <<assertSame(trim($expected), trim($dumper->dumpAtPath($configuration, $path)));
- }
-
- private function getConfigurationAsString()
- {
- return <<<'EOL'
-acme_root:
- boolean: true
- scalar_empty: ~
- scalar_null: null
- scalar_true: true
- scalar_false: false
- scalar_default: default
- scalar_array_empty: []
- scalar_array_defaults:
-
- # Defaults:
- - elem1
- - elem2
- scalar_required: ~ # Required
- scalar_deprecated: ~ # Deprecated (The child node "scalar_deprecated" at path "acme_root" is deprecated.)
- scalar_deprecated_with_message: ~ # Deprecated (Deprecation custom message for "scalar_deprecated_with_message" at "acme_root")
- node_with_a_looong_name: ~
- enum_with_default: this # One of "this"; "that"
- enum: ~ # One of "this"; "that"
-
- # some info
- array:
- child1: ~
- child2: ~
-
- # this is a long
- # multi-line info text
- # which should be indented
- child3: ~ # Example: example setting
- scalar_prototyped: []
- parameters:
-
- # Prototype: Parameter name
- name: ~
- connections:
-
- # Prototype
- -
- user: ~
- pass: ~
- cms_pages:
-
- # Prototype
- page:
-
- # Prototype
- locale:
- title: ~ # Required
- path: ~ # Required
- pipou:
-
- # Prototype
- name: []
-
-EOL;
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/EnumNodeTest.php b/vendor/symfony/config/Tests/Definition/EnumNodeTest.php
deleted file mode 100644
index fa89eea2..00000000
--- a/vendor/symfony/config/Tests/Definition/EnumNodeTest.php
+++ /dev/null
@@ -1,51 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\EnumNode;
-
-class EnumNodeTest extends TestCase
-{
- public function testFinalizeValue()
- {
- $node = new EnumNode('foo', null, ['foo', 'bar']);
- $this->assertSame('foo', $node->finalize('foo'));
- }
-
- public function testConstructionWithNoValues()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('$values must contain at least one element.');
- new EnumNode('foo', null, []);
- }
-
- public function testConstructionWithOneValue()
- {
- $node = new EnumNode('foo', null, ['foo']);
- $this->assertSame('foo', $node->finalize('foo'));
- }
-
- public function testConstructionWithOneDistinctValue()
- {
- $node = new EnumNode('foo', null, ['foo', 'foo']);
- $this->assertSame('foo', $node->finalize('foo'));
- }
-
- public function testFinalizeWithInvalidValue()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The value "foobar" is not allowed for path "foo". Permissible values: "foo", "bar"');
- $node = new EnumNode('foo', null, ['foo', 'bar']);
- $node->finalize('foobar');
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/FinalizationTest.php b/vendor/symfony/config/Tests/Definition/FinalizationTest.php
deleted file mode 100644
index be68a27c..00000000
--- a/vendor/symfony/config/Tests/Definition/FinalizationTest.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\NodeInterface;
-use Symfony\Component\Config\Definition\Processor;
-
-class FinalizationTest extends TestCase
-{
- public function testUnsetKeyWithDeepHierarchy()
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('config', 'array')
- ->children()
- ->node('level1', 'array')
- ->canBeUnset()
- ->children()
- ->node('level2', 'array')
- ->canBeUnset()
- ->children()
- ->node('somevalue', 'scalar')->end()
- ->node('anothervalue', 'scalar')->end()
- ->end()
- ->end()
- ->node('level1_scalar', 'scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $a = [
- 'level1' => [
- 'level2' => [
- 'somevalue' => 'foo',
- 'anothervalue' => 'bar',
- ],
- 'level1_scalar' => 'foo',
- ],
- ];
-
- $b = [
- 'level1' => [
- 'level2' => false,
- ],
- ];
-
- $this->assertEquals([
- 'level1' => [
- 'level1_scalar' => 'foo',
- ],
- ], $this->process($tree, [$a, $b]));
- }
-
- protected function process(NodeInterface $tree, array $configs)
- {
- $processor = new Processor();
-
- return $processor->process($tree, $configs);
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/FloatNodeTest.php b/vendor/symfony/config/Tests/Definition/FloatNodeTest.php
deleted file mode 100644
index fed9f013..00000000
--- a/vendor/symfony/config/Tests/Definition/FloatNodeTest.php
+++ /dev/null
@@ -1,78 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\FloatNode;
-
-class FloatNodeTest extends TestCase
-{
- /**
- * @dataProvider getValidValues
- */
- public function testNormalize($value)
- {
- $node = new FloatNode('test');
- $this->assertSame($value, $node->normalize($value));
- }
-
- /**
- * @dataProvider getValidValues
- *
- * @param int $value
- */
- public function testValidNonEmptyValues($value)
- {
- $node = new FloatNode('test');
- $node->setAllowEmptyValue(false);
-
- $this->assertSame($value, $node->finalize($value));
- }
-
- public function getValidValues()
- {
- return [
- [1798.0],
- [-678.987],
- [12.56E45],
- [0.0],
- // Integer are accepted too, they will be cast
- [17],
- [-10],
- [0],
- ];
- }
-
- /**
- * @dataProvider getInvalidValues
- */
- public function testNormalizeThrowsExceptionOnInvalidValues($value)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $node = new FloatNode('test');
- $node->normalize($value);
- }
-
- public function getInvalidValues()
- {
- return [
- [null],
- [''],
- ['foo'],
- [true],
- [false],
- [[]],
- [['foo' => 'bar']],
- [new \stdClass()],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/IntegerNodeTest.php b/vendor/symfony/config/Tests/Definition/IntegerNodeTest.php
deleted file mode 100644
index 3fb1b771..00000000
--- a/vendor/symfony/config/Tests/Definition/IntegerNodeTest.php
+++ /dev/null
@@ -1,75 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\IntegerNode;
-
-class IntegerNodeTest extends TestCase
-{
- /**
- * @dataProvider getValidValues
- */
- public function testNormalize($value)
- {
- $node = new IntegerNode('test');
- $this->assertSame($value, $node->normalize($value));
- }
-
- /**
- * @dataProvider getValidValues
- *
- * @param int $value
- */
- public function testValidNonEmptyValues($value)
- {
- $node = new IntegerNode('test');
- $node->setAllowEmptyValue(false);
-
- $this->assertSame($value, $node->finalize($value));
- }
-
- public function getValidValues()
- {
- return [
- [1798],
- [-678],
- [0],
- ];
- }
-
- /**
- * @dataProvider getInvalidValues
- */
- public function testNormalizeThrowsExceptionOnInvalidValues($value)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $node = new IntegerNode('test');
- $node->normalize($value);
- }
-
- public function getInvalidValues()
- {
- return [
- [null],
- [''],
- ['foo'],
- [true],
- [false],
- [0.0],
- [0.1],
- [[]],
- [['foo' => 'bar']],
- [new \stdClass()],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/MergeTest.php b/vendor/symfony/config/Tests/Definition/MergeTest.php
deleted file mode 100644
index 8fee2635..00000000
--- a/vendor/symfony/config/Tests/Definition/MergeTest.php
+++ /dev/null
@@ -1,192 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-
-class MergeTest extends TestCase
-{
- public function testForbiddenOverwrite()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\ForbiddenOverwriteException');
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root', 'array')
- ->children()
- ->node('foo', 'scalar')
- ->cannotBeOverwritten()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $a = [
- 'foo' => 'bar',
- ];
-
- $b = [
- 'foo' => 'moo',
- ];
-
- $tree->merge($a, $b);
- }
-
- public function testUnsetKey()
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root', 'array')
- ->children()
- ->node('foo', 'scalar')->end()
- ->node('bar', 'scalar')->end()
- ->node('unsettable', 'array')
- ->canBeUnset()
- ->children()
- ->node('foo', 'scalar')->end()
- ->node('bar', 'scalar')->end()
- ->end()
- ->end()
- ->node('unsetted', 'array')
- ->canBeUnset()
- ->prototype('scalar')->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $a = [
- 'foo' => 'bar',
- 'unsettable' => [
- 'foo' => 'a',
- 'bar' => 'b',
- ],
- 'unsetted' => false,
- ];
-
- $b = [
- 'foo' => 'moo',
- 'bar' => 'b',
- 'unsettable' => false,
- 'unsetted' => ['a', 'b'],
- ];
-
- $this->assertEquals([
- 'foo' => 'moo',
- 'bar' => 'b',
- 'unsettable' => false,
- 'unsetted' => ['a', 'b'],
- ], $tree->merge($a, $b));
- }
-
- public function testDoesNotAllowNewKeysInSubsequentConfigs()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('config', 'array')
- ->children()
- ->node('test', 'array')
- ->disallowNewKeysInSubsequentConfigs()
- ->useAttributeAsKey('key')
- ->prototype('array')
- ->children()
- ->node('value', 'scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree();
-
- $a = [
- 'test' => [
- 'a' => ['value' => 'foo'],
- ],
- ];
-
- $b = [
- 'test' => [
- 'b' => ['value' => 'foo'],
- ],
- ];
-
- $tree->merge($a, $b);
- }
-
- public function testPerformsNoDeepMerging()
- {
- $tb = new TreeBuilder();
-
- $tree = $tb
- ->root('config', 'array')
- ->children()
- ->node('no_deep_merging', 'array')
- ->performNoDeepMerging()
- ->children()
- ->node('foo', 'scalar')->end()
- ->node('bar', 'scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $a = [
- 'no_deep_merging' => [
- 'foo' => 'a',
- 'bar' => 'b',
- ],
- ];
-
- $b = [
- 'no_deep_merging' => [
- 'c' => 'd',
- ],
- ];
-
- $this->assertEquals([
- 'no_deep_merging' => [
- 'c' => 'd',
- ],
- ], $tree->merge($a, $b));
- }
-
- public function testPrototypeWithoutAKeyAttribute()
- {
- $tb = new TreeBuilder();
-
- $tree = $tb
- ->root('config', 'array')
- ->children()
- ->arrayNode('append_elements')
- ->prototype('scalar')->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $a = [
- 'append_elements' => ['a', 'b'],
- ];
-
- $b = [
- 'append_elements' => ['c', 'd'],
- ];
-
- $this->assertEquals(['append_elements' => ['a', 'b', 'c', 'd']], $tree->merge($a, $b));
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/NormalizationTest.php b/vendor/symfony/config/Tests/Definition/NormalizationTest.php
deleted file mode 100644
index 200a9859..00000000
--- a/vendor/symfony/config/Tests/Definition/NormalizationTest.php
+++ /dev/null
@@ -1,228 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\NodeInterface;
-
-class NormalizationTest extends TestCase
-{
- /**
- * @dataProvider getEncoderTests
- */
- public function testNormalizeEncoders($denormalized)
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root_name', 'array')
- ->fixXmlConfig('encoder')
- ->children()
- ->node('encoders', 'array')
- ->useAttributeAsKey('class')
- ->prototype('array')
- ->beforeNormalization()->ifString()->then(function ($v) { return ['algorithm' => $v]; })->end()
- ->children()
- ->node('algorithm', 'scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $normalized = [
- 'encoders' => [
- 'foo' => ['algorithm' => 'plaintext'],
- ],
- ];
-
- $this->assertNormalized($tree, $denormalized, $normalized);
- }
-
- public function getEncoderTests()
- {
- $configs = [];
-
- // XML
- $configs[] = [
- 'encoder' => [
- ['class' => 'foo', 'algorithm' => 'plaintext'],
- ],
- ];
-
- // XML when only one element of this type
- $configs[] = [
- 'encoder' => ['class' => 'foo', 'algorithm' => 'plaintext'],
- ];
-
- // YAML/PHP
- $configs[] = [
- 'encoders' => [
- ['class' => 'foo', 'algorithm' => 'plaintext'],
- ],
- ];
-
- // YAML/PHP
- $configs[] = [
- 'encoders' => [
- 'foo' => 'plaintext',
- ],
- ];
-
- // YAML/PHP
- $configs[] = [
- 'encoders' => [
- 'foo' => ['algorithm' => 'plaintext'],
- ],
- ];
-
- return array_map(function ($v) {
- return [$v];
- }, $configs);
- }
-
- /**
- * @dataProvider getAnonymousKeysTests
- */
- public function testAnonymousKeysArray($denormalized)
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root', 'array')
- ->children()
- ->node('logout', 'array')
- ->fixXmlConfig('handler')
- ->children()
- ->node('handlers', 'array')
- ->prototype('scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $normalized = ['logout' => ['handlers' => ['a', 'b', 'c']]];
-
- $this->assertNormalized($tree, $denormalized, $normalized);
- }
-
- public function getAnonymousKeysTests()
- {
- $configs = [];
-
- $configs[] = [
- 'logout' => [
- 'handlers' => ['a', 'b', 'c'],
- ],
- ];
-
- $configs[] = [
- 'logout' => [
- 'handler' => ['a', 'b', 'c'],
- ],
- ];
-
- return array_map(function ($v) { return [$v]; }, $configs);
- }
-
- /**
- * @dataProvider getNumericKeysTests
- */
- public function testNumericKeysAsAttributes($denormalized)
- {
- $normalized = [
- 'thing' => [42 => ['foo', 'bar'], 1337 => ['baz', 'qux']],
- ];
-
- $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, $normalized);
- }
-
- public function getNumericKeysTests()
- {
- $configs = [];
-
- $configs[] = [
- 'thing' => [
- 42 => ['foo', 'bar'], 1337 => ['baz', 'qux'],
- ],
- ];
-
- $configs[] = [
- 'thing' => [
- ['foo', 'bar', 'id' => 42], ['baz', 'qux', 'id' => 1337],
- ],
- ];
-
- return array_map(function ($v) { return [$v]; }, $configs);
- }
-
- public function testNonAssociativeArrayThrowsExceptionIfAttributeNotSet()
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $this->expectExceptionMessage('The attribute "id" must be set for path "root.thing".');
- $denormalized = [
- 'thing' => [
- ['foo', 'bar'], ['baz', 'qux'],
- ],
- ];
-
- $this->assertNormalized($this->getNumericKeysTestTree(), $denormalized, []);
- }
-
- public function testAssociativeArrayPreserveKeys()
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root', 'array')
- ->prototype('array')
- ->children()
- ->node('foo', 'scalar')->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- $data = ['first' => ['foo' => 'bar']];
-
- $this->assertNormalized($tree, $data, $data);
- }
-
- public static function assertNormalized(NodeInterface $tree, $denormalized, $normalized)
- {
- self::assertSame($normalized, $tree->normalize($denormalized));
- }
-
- private function getNumericKeysTestTree()
- {
- $tb = new TreeBuilder();
- $tree = $tb
- ->root('root', 'array')
- ->children()
- ->node('thing', 'array')
- ->useAttributeAsKey('id')
- ->prototype('array')
- ->prototype('scalar')->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->buildTree()
- ;
-
- return $tree;
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/PrototypedArrayNodeTest.php b/vendor/symfony/config/Tests/Definition/PrototypedArrayNodeTest.php
deleted file mode 100644
index 7a58ead8..00000000
--- a/vendor/symfony/config/Tests/Definition/PrototypedArrayNodeTest.php
+++ /dev/null
@@ -1,341 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\ArrayNode;
-use Symfony\Component\Config\Definition\PrototypedArrayNode;
-use Symfony\Component\Config\Definition\ScalarNode;
-use Symfony\Component\Config\Definition\VariableNode;
-
-class PrototypedArrayNodeTest extends TestCase
-{
- public function testGetDefaultValueReturnsAnEmptyArrayForPrototypes()
- {
- $node = new PrototypedArrayNode('root');
- $prototype = new ArrayNode(null, $node);
- $node->setPrototype($prototype);
- $this->assertEmpty($node->getDefaultValue());
- }
-
- public function testGetDefaultValueReturnsDefaultValueForPrototypes()
- {
- $node = new PrototypedArrayNode('root');
- $prototype = new ArrayNode(null, $node);
- $node->setPrototype($prototype);
- $node->setDefaultValue(['test']);
- $this->assertEquals(['test'], $node->getDefaultValue());
- }
-
- // a remapped key (e.g. "mapping" -> "mappings") should be unset after being used
- public function testRemappedKeysAreUnset()
- {
- $node = new ArrayNode('root');
- $mappingsNode = new PrototypedArrayNode('mappings');
- $node->addChild($mappingsNode);
-
- // each item under mappings is just a scalar
- $prototype = new ScalarNode(null, $mappingsNode);
- $mappingsNode->setPrototype($prototype);
-
- $remappings = [];
- $remappings[] = ['mapping', 'mappings'];
- $node->setXmlRemappings($remappings);
-
- $normalized = $node->normalize(['mapping' => ['foo', 'bar']]);
- $this->assertEquals(['mappings' => ['foo', 'bar']], $normalized);
- }
-
- /**
- * Tests that when a key attribute is mapped, that key is removed from the array.
- *
- *
- *
- *
- * The above should finally be mapped to an array that looks like this
- * (because "id" is the key attribute).
- *
- * [
- * 'things' => [
- * 'option1' => 'foo',
- * 'option2' => 'bar',
- * ]
- * ]
- */
- public function testMappedAttributeKeyIsRemoved()
- {
- $node = new PrototypedArrayNode('root');
- $node->setKeyAttribute('id', true);
-
- // each item under the root is an array, with one scalar item
- $prototype = new ArrayNode(null, $node);
- $prototype->addChild(new ScalarNode('foo'));
- $node->setPrototype($prototype);
-
- $children = [];
- $children[] = ['id' => 'item_name', 'foo' => 'bar'];
- $normalized = $node->normalize($children);
-
- $expected = [];
- $expected['item_name'] = ['foo' => 'bar'];
- $this->assertEquals($expected, $normalized);
- }
-
- /**
- * Tests the opposite of the testMappedAttributeKeyIsRemoved because
- * the removal can be toggled with an option.
- */
- public function testMappedAttributeKeyNotRemoved()
- {
- $node = new PrototypedArrayNode('root');
- $node->setKeyAttribute('id', false);
-
- // each item under the root is an array, with two scalar items
- $prototype = new ArrayNode(null, $node);
- $prototype->addChild(new ScalarNode('foo'));
- $prototype->addChild(new ScalarNode('id')); // the key attribute will remain
- $node->setPrototype($prototype);
-
- $children = [];
- $children[] = ['id' => 'item_name', 'foo' => 'bar'];
- $normalized = $node->normalize($children);
-
- $expected = [];
- $expected['item_name'] = ['id' => 'item_name', 'foo' => 'bar'];
- $this->assertEquals($expected, $normalized);
- }
-
- public function testAddDefaultChildren()
- {
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setAddChildrenIfNoneSet();
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals([['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setKeyAttribute('foobar');
- $node->setAddChildrenIfNoneSet();
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals(['defaults' => ['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setKeyAttribute('foobar');
- $node->setAddChildrenIfNoneSet('defaultkey');
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals(['defaultkey' => ['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setKeyAttribute('foobar');
- $node->setAddChildrenIfNoneSet(['defaultkey']);
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals(['defaultkey' => ['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setKeyAttribute('foobar');
- $node->setAddChildrenIfNoneSet(['dk1', 'dk2']);
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals(['dk1' => ['foo' => 'bar'], 'dk2' => ['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setAddChildrenIfNoneSet([5, 6]);
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals([0 => ['foo' => 'bar'], 1 => ['foo' => 'bar']], $node->getDefaultValue());
-
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setAddChildrenIfNoneSet(2);
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals([['foo' => 'bar'], ['foo' => 'bar']], $node->getDefaultValue());
- }
-
- public function testDefaultChildrenWinsOverDefaultValue()
- {
- $node = $this->getPrototypeNodeWithDefaultChildren();
- $node->setAddChildrenIfNoneSet();
- $node->setDefaultValue(['bar' => 'foo']);
- $this->assertTrue($node->hasDefaultValue());
- $this->assertEquals([['foo' => 'bar']], $node->getDefaultValue());
- }
-
- protected function getPrototypeNodeWithDefaultChildren()
- {
- $node = new PrototypedArrayNode('root');
- $prototype = new ArrayNode(null, $node);
- $child = new ScalarNode('foo');
- $child->setDefaultValue('bar');
- $prototype->addChild($child);
- $prototype->setAddIfNotSet(true);
- $node->setPrototype($prototype);
-
- return $node;
- }
-
- /**
- * Tests that when a key attribute is mapped, that key is removed from the array.
- * And if only 'value' element is left in the array, it will replace its wrapper array.
- *
- *
- *
- *
- * The above should finally be mapped to an array that looks like this
- * (because "id" is the key attribute).
- *
- * [
- * 'things' => [
- * 'option1' => 'value1'
- * ]
- * ]
- *
- * It's also possible to mix 'value-only' and 'non-value-only' elements in the array.
- *
- *
- *
- *
- * The above should finally be mapped to an array as follows
- *
- * [
- * 'things' => [
- * 'option1' => 'value1',
- * 'option2' => [
- * 'value' => 'value2',
- * 'foo' => 'foo2'
- * ]
- * ]
- * ]
- *
- * The 'value' element can also be ArrayNode:
- *
- *
- *
- *
- *
- * The above should be finally be mapped to an array as follows
- *
- * [
- * 'things' => [
- * 'option1' => [
- * 'foo' => 'foo1',
- * 'bar' => 'bar1'
- * ]
- * ]
- * ]
- *
- * If using VariableNode for value node, it's also possible to mix different types of value nodes:
- *
- *
- *
- *
- *
- * The above should be finally mapped to an array as follows
- *
- * [
- * 'things' => [
- * 'option1' => [
- * 'foo' => 'foo1',
- * 'bar' => 'bar1'
- * ],
- * 'option2' => 'value2'
- * ]
- * ]
- *
- * @dataProvider getDataForKeyRemovedLeftValueOnly
- */
- public function testMappedAttributeKeyIsRemovedLeftValueOnly($value, $children, $expected)
- {
- $node = new PrototypedArrayNode('root');
- $node->setKeyAttribute('id', true);
-
- // each item under the root is an array, with one scalar item
- $prototype = new ArrayNode(null, $node);
- $prototype->addChild(new ScalarNode('id'));
- $prototype->addChild(new ScalarNode('foo'));
- $prototype->addChild($value);
- $node->setPrototype($prototype);
-
- $normalized = $node->normalize($children);
- $this->assertEquals($expected, $normalized);
- }
-
- public function getDataForKeyRemovedLeftValueOnly()
- {
- $scalarValue = new ScalarNode('value');
-
- $arrayValue = new ArrayNode('value');
- $arrayValue->addChild(new ScalarNode('foo'));
- $arrayValue->addChild(new ScalarNode('bar'));
-
- $variableValue = new VariableNode('value');
-
- return [
- [
- $scalarValue,
- [
- ['id' => 'option1', 'value' => 'value1'],
- ],
- ['option1' => 'value1'],
- ],
-
- [
- $scalarValue,
- [
- ['id' => 'option1', 'value' => 'value1'],
- ['id' => 'option2', 'value' => 'value2', 'foo' => 'foo2'],
- ],
- [
- 'option1' => 'value1',
- 'option2' => ['value' => 'value2', 'foo' => 'foo2'],
- ],
- ],
-
- [
- $arrayValue,
- [
- [
- 'id' => 'option1',
- 'value' => ['foo' => 'foo1', 'bar' => 'bar1'],
- ],
- ],
- [
- 'option1' => ['foo' => 'foo1', 'bar' => 'bar1'],
- ],
- ],
-
- [$variableValue,
- [
- [
- 'id' => 'option1', 'value' => ['foo' => 'foo1', 'bar' => 'bar1'],
- ],
- ['id' => 'option2', 'value' => 'value2'],
- ],
- [
- 'option1' => ['foo' => 'foo1', 'bar' => 'bar1'],
- 'option2' => 'value2',
- ],
- ],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/Definition/ScalarNodeTest.php b/vendor/symfony/config/Tests/Definition/ScalarNodeTest.php
deleted file mode 100644
index ac2d9376..00000000
--- a/vendor/symfony/config/Tests/Definition/ScalarNodeTest.php
+++ /dev/null
@@ -1,161 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Definition;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Definition\ArrayNode;
-use Symfony\Component\Config\Definition\ScalarNode;
-
-class ScalarNodeTest extends TestCase
-{
- /**
- * @dataProvider getValidValues
- */
- public function testNormalize($value)
- {
- $node = new ScalarNode('test');
- $this->assertSame($value, $node->normalize($value));
- }
-
- public function getValidValues()
- {
- return [
- [false],
- [true],
- [null],
- [''],
- ['foo'],
- [0],
- [1],
- [0.0],
- [0.1],
- ];
- }
-
- public function testSetDeprecated()
- {
- $childNode = new ScalarNode('foo');
- $childNode->setDeprecated('"%node%" is deprecated');
-
- $this->assertTrue($childNode->isDeprecated());
- $this->assertSame('"foo" is deprecated', $childNode->getDeprecationMessage($childNode->getName(), $childNode->getPath()));
-
- $node = new ArrayNode('root');
- $node->addChild($childNode);
-
- $deprecationTriggered = 0;
- $deprecationHandler = function ($level, $message, $file, $line) use (&$prevErrorHandler, &$deprecationTriggered) {
- if (\E_USER_DEPRECATED === $level) {
- return ++$deprecationTriggered;
- }
-
- return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false;
- };
-
- $prevErrorHandler = set_error_handler($deprecationHandler);
- $node->finalize([]);
- restore_error_handler();
- $this->assertSame(0, $deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set');
-
- $prevErrorHandler = set_error_handler($deprecationHandler);
- $node->finalize(['foo' => '']);
- restore_error_handler();
- $this->assertSame(1, $deprecationTriggered, '->finalize() should trigger if the deprecated node is set');
- }
-
- /**
- * @dataProvider getInvalidValues
- */
- public function testNormalizeThrowsExceptionOnInvalidValues($value)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $node = new ScalarNode('test');
- $node->normalize($value);
- }
-
- public function getInvalidValues()
- {
- return [
- [[]],
- [['foo' => 'bar']],
- [new \stdClass()],
- ];
- }
-
- public function testNormalizeThrowsExceptionWithoutHint()
- {
- $node = new ScalarNode('test');
-
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $this->expectExceptionMessage('Invalid type for path "test". Expected scalar, but got array.');
-
- $node->normalize([]);
- }
-
- public function testNormalizeThrowsExceptionWithErrorMessage()
- {
- $node = new ScalarNode('test');
- $node->setInfo('"the test value"');
-
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidTypeException');
- $this->expectExceptionMessage("Invalid type for path \"test\". Expected scalar, but got array.\nHint: \"the test value\"");
-
- $node->normalize([]);
- }
-
- /**
- * @dataProvider getValidNonEmptyValues
- *
- * @param mixed $value
- */
- public function testValidNonEmptyValues($value)
- {
- $node = new ScalarNode('test');
- $node->setAllowEmptyValue(false);
-
- $this->assertSame($value, $node->finalize($value));
- }
-
- public function getValidNonEmptyValues()
- {
- return [
- [false],
- [true],
- ['foo'],
- [0],
- [1],
- [0.0],
- [0.1],
- ];
- }
-
- /**
- * @dataProvider getEmptyValues
- *
- * @param mixed $value
- */
- public function testNotAllowedEmptyValuesThrowException($value)
- {
- $this->expectException('Symfony\Component\Config\Definition\Exception\InvalidConfigurationException');
- $node = new ScalarNode('test');
- $node->setAllowEmptyValue(false);
- $node->finalize($value);
- }
-
- public function getEmptyValues()
- {
- return [
- [null],
- [''],
- ];
- }
-}
diff --git a/vendor/symfony/config/Tests/DependencyInjection/ConfigCachePassTest.php b/vendor/symfony/config/Tests/DependencyInjection/ConfigCachePassTest.php
deleted file mode 100644
index c2b95195..00000000
--- a/vendor/symfony/config/Tests/DependencyInjection/ConfigCachePassTest.php
+++ /dev/null
@@ -1,59 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\DependencyInjection;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\DependencyInjection\ConfigCachePass;
-use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Reference;
-
-/**
- * @group legacy
- */
-class ConfigCachePassTest extends TestCase
-{
- public function testThatCheckersAreProcessedInPriorityOrder()
- {
- $container = new ContainerBuilder();
-
- $definition = $container->register('config_cache_factory')->addArgument(null);
- $container->register('checker_2')->addTag('config_cache.resource_checker', ['priority' => 100]);
- $container->register('checker_1')->addTag('config_cache.resource_checker', ['priority' => 200]);
- $container->register('checker_3')->addTag('config_cache.resource_checker');
-
- $pass = new ConfigCachePass();
- $pass->process($container);
-
- $expected = new IteratorArgument([
- new Reference('checker_1'),
- new Reference('checker_2'),
- new Reference('checker_3'),
- ]);
- $this->assertEquals($expected, $definition->getArgument(0));
- }
-
- public function testThatCheckersCanBeMissing()
- {
- $container = new ContainerBuilder();
-
- $definitionsBefore = \count($container->getDefinitions());
- $aliasesBefore = \count($container->getAliases());
-
- $pass = new ConfigCachePass();
- $pass->process($container);
-
- // the container is untouched (i.e. no new definitions or aliases)
- $this->assertCount($definitionsBefore, $container->getDefinitions());
- $this->assertCount($aliasesBefore, $container->getAliases());
- }
-}
diff --git a/vendor/symfony/config/Tests/Exception/FileLoaderLoadExceptionTest.php b/vendor/symfony/config/Tests/Exception/FileLoaderLoadExceptionTest.php
deleted file mode 100644
index 8363084c..00000000
--- a/vendor/symfony/config/Tests/Exception/FileLoaderLoadExceptionTest.php
+++ /dev/null
@@ -1,98 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Exception;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Exception\FileLoaderLoadException;
-
-class FileLoaderLoadExceptionTest extends TestCase
-{
- public function testMessageCannotLoadResource()
- {
- $exception = new FileLoaderLoadException('resource', null);
- $this->assertEquals('Cannot load resource "resource".', $exception->getMessage());
- }
-
- public function testMessageCannotLoadResourceWithType()
- {
- $exception = new FileLoaderLoadException('resource', null, null, null, 'foobar');
- $this->assertEquals('Cannot load resource "resource". Make sure there is a loader supporting the "foobar" type.', $exception->getMessage());
- }
-
- public function testMessageCannotLoadResourceWithAnnotationType()
- {
- $exception = new FileLoaderLoadException('resource', null, null, null, 'annotation');
- $this->assertEquals('Cannot load resource "resource". Make sure annotations are installed and enabled.', $exception->getMessage());
- }
-
- public function testMessageCannotImportResourceFromSource()
- {
- $exception = new FileLoaderLoadException('resource', 'sourceResource');
- $this->assertEquals('Cannot import resource "resource" from "sourceResource".', $exception->getMessage());
- }
-
- public function testMessageCannotImportBundleResource()
- {
- $exception = new FileLoaderLoadException('@resource', 'sourceResource');
- $this->assertEquals(
- 'Cannot import resource "@resource" from "sourceResource". '.
- 'Make sure the "resource" bundle is correctly registered and loaded in the application kernel class. '.
- 'If the bundle is registered, make sure the bundle path "@resource" is not empty.',
- $exception->getMessage()
- );
- }
-
- public function testMessageHasPreviousErrorWithDotAndUnableToLoad()
- {
- $exception = new FileLoaderLoadException(
- 'resource',
- null,
- null,
- new \Exception('There was a previous error with an ending dot.')
- );
- $this->assertEquals(
- 'There was a previous error with an ending dot in resource (which is loaded in resource "resource").',
- $exception->getMessage()
- );
- }
-
- public function testMessageHasPreviousErrorWithoutDotAndUnableToLoad()
- {
- $exception = new FileLoaderLoadException(
- 'resource',
- null,
- null,
- new \Exception('There was a previous error with no ending dot')
- );
- $this->assertEquals(
- 'There was a previous error with no ending dot in resource (which is loaded in resource "resource").',
- $exception->getMessage()
- );
- }
-
- public function testMessageHasPreviousErrorAndUnableToLoadBundle()
- {
- $exception = new FileLoaderLoadException(
- '@resource',
- null,
- null,
- new \Exception('There was a previous error with an ending dot.')
- );
- $this->assertEquals(
- 'There was a previous error with an ending dot in @resource '.
- '(which is loaded in resource "@resource"). '.
- 'Make sure the "resource" bundle is correctly registered and loaded in the application kernel class. '.
- 'If the bundle is registered, make sure the bundle path "@resource" is not empty.',
- $exception->getMessage()
- );
- }
-}
diff --git a/vendor/symfony/config/Tests/FileLocatorTest.php b/vendor/symfony/config/Tests/FileLocatorTest.php
deleted file mode 100644
index e931916a..00000000
--- a/vendor/symfony/config/Tests/FileLocatorTest.php
+++ /dev/null
@@ -1,114 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\FileLocator;
-
-class FileLocatorTest extends TestCase
-{
- /**
- * @dataProvider getIsAbsolutePathTests
- */
- public function testIsAbsolutePath($path)
- {
- $loader = new FileLocator([]);
- $r = new \ReflectionObject($loader);
- $m = $r->getMethod('isAbsolutePath');
- $m->setAccessible(true);
-
- $this->assertTrue($m->invoke($loader, $path), '->isAbsolutePath() returns true for an absolute path');
- }
-
- public function getIsAbsolutePathTests()
- {
- return [
- ['/foo.xml'],
- ['c:\\\\foo.xml'],
- ['c:/foo.xml'],
- ['\\server\\foo.xml'],
- ['https://server/foo.xml'],
- ['phar://server/foo.xml'],
- ];
- }
-
- public function testLocate()
- {
- $loader = new FileLocator(__DIR__.'/Fixtures');
-
- $this->assertEquals(
- __DIR__.\DIRECTORY_SEPARATOR.'FileLocatorTest.php',
- $loader->locate('FileLocatorTest.php', __DIR__),
- '->locate() returns the absolute filename if the file exists in the given path'
- );
-
- $this->assertEquals(
- __DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml',
- $loader->locate('foo.xml', __DIR__),
- '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
- );
-
- $this->assertEquals(
- __DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml',
- $loader->locate(__DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml', __DIR__),
- '->locate() returns the absolute filename if the file exists in one of the paths given in the constructor'
- );
-
- $loader = new FileLocator([__DIR__.'/Fixtures', __DIR__.'/Fixtures/Again']);
-
- $this->assertEquals(
- [__DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.\DIRECTORY_SEPARATOR.'foo.xml'],
- $loader->locate('foo.xml', __DIR__, false),
- '->locate() returns an array of absolute filenames'
- );
-
- $this->assertEquals(
- [__DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.\DIRECTORY_SEPARATOR.'foo.xml'],
- $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
- '->locate() returns an array of absolute filenames'
- );
-
- $loader = new FileLocator(__DIR__.'/Fixtures/Again');
-
- $this->assertEquals(
- [__DIR__.'/Fixtures'.\DIRECTORY_SEPARATOR.'foo.xml', __DIR__.'/Fixtures/Again'.\DIRECTORY_SEPARATOR.'foo.xml'],
- $loader->locate('foo.xml', __DIR__.'/Fixtures', false),
- '->locate() returns an array of absolute filenames'
- );
- }
-
- public function testLocateThrowsAnExceptionIfTheFileDoesNotExists()
- {
- $this->expectException('Symfony\Component\Config\Exception\FileLocatorFileNotFoundException');
- $this->expectExceptionMessage('The file "foobar.xml" does not exist');
- $loader = new FileLocator([__DIR__.'/Fixtures']);
-
- $loader->locate('foobar.xml', __DIR__);
- }
-
- public function testLocateThrowsAnExceptionIfTheFileDoesNotExistsInAbsolutePath()
- {
- $this->expectException('Symfony\Component\Config\Exception\FileLocatorFileNotFoundException');
- $loader = new FileLocator([__DIR__.'/Fixtures']);
-
- $loader->locate(__DIR__.'/Fixtures/foobar.xml', __DIR__);
- }
-
- public function testLocateEmpty()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage('An empty file name is not valid to be located.');
- $loader = new FileLocator([__DIR__.'/Fixtures']);
-
- $loader->locate(null, __DIR__);
- }
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/Again/foo.xml b/vendor/symfony/config/Tests/Fixtures/Again/foo.xml
deleted file mode 100644
index e69de29b..00000000
diff --git a/vendor/symfony/config/Tests/Fixtures/BadFileName.php b/vendor/symfony/config/Tests/Fixtures/BadFileName.php
deleted file mode 100644
index 0f79bdd5..00000000
--- a/vendor/symfony/config/Tests/Fixtures/BadFileName.php
+++ /dev/null
@@ -1,9 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Fixtures;
-
-use Symfony\Component\Config\Definition\ArrayNode;
-
-class BarNode extends ArrayNode
-{
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/Builder/BarNodeDefinition.php b/vendor/symfony/config/Tests/Fixtures/Builder/BarNodeDefinition.php
deleted file mode 100644
index b9c62e53..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Builder/BarNodeDefinition.php
+++ /dev/null
@@ -1,23 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Fixtures\Builder;
-
-use Symfony\Component\Config\Definition\Builder\NodeDefinition;
-use Symfony\Component\Config\Tests\Fixtures\BarNode;
-
-class BarNodeDefinition extends NodeDefinition
-{
- protected function createNode()
- {
- return new BarNode($this->name);
- }
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/Builder/NodeBuilder.php b/vendor/symfony/config/Tests/Fixtures/Builder/NodeBuilder.php
deleted file mode 100644
index 22b8b32f..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Builder/NodeBuilder.php
+++ /dev/null
@@ -1,34 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Fixtures\Builder;
-
-use Symfony\Component\Config\Definition\Builder\NodeBuilder as BaseNodeBuilder;
-
-class NodeBuilder extends BaseNodeBuilder
-{
- public function barNode($name)
- {
- return $this->node($name, 'bar');
- }
-
- protected function getNodeClass($type)
- {
- switch ($type) {
- case 'variable':
- return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
- case 'bar':
- return __NAMESPACE__.'\\'.ucfirst($type).'NodeDefinition';
- default:
- return parent::getNodeClass($type);
- }
- }
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/Builder/VariableNodeDefinition.php b/vendor/symfony/config/Tests/Fixtures/Builder/VariableNodeDefinition.php
deleted file mode 100644
index 6126ed43..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Builder/VariableNodeDefinition.php
+++ /dev/null
@@ -1,18 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Fixtures\Builder;
-
-use Symfony\Component\Config\Definition\Builder\VariableNodeDefinition as BaseVariableNodeDefinition;
-
-class VariableNodeDefinition extends BaseVariableNodeDefinition
-{
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/Configuration/ExampleConfiguration.php b/vendor/symfony/config/Tests/Fixtures/Configuration/ExampleConfiguration.php
deleted file mode 100644
index 3f02700a..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Configuration/ExampleConfiguration.php
+++ /dev/null
@@ -1,102 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Fixtures\Configuration;
-
-use Symfony\Component\Config\Definition\Builder\TreeBuilder;
-use Symfony\Component\Config\Definition\ConfigurationInterface;
-
-class ExampleConfiguration implements ConfigurationInterface
-{
- public function getConfigTreeBuilder()
- {
- $treeBuilder = new TreeBuilder();
- $rootNode = $treeBuilder->root('acme_root');
-
- $rootNode
- ->fixXmlConfig('parameter')
- ->fixXmlConfig('connection')
- ->fixXmlConfig('cms_page')
- ->children()
- ->booleanNode('boolean')->defaultTrue()->end()
- ->scalarNode('scalar_empty')->end()
- ->scalarNode('scalar_null')->defaultNull()->end()
- ->scalarNode('scalar_true')->defaultTrue()->end()
- ->scalarNode('scalar_false')->defaultFalse()->end()
- ->scalarNode('scalar_default')->defaultValue('default')->end()
- ->scalarNode('scalar_array_empty')->defaultValue([])->end()
- ->scalarNode('scalar_array_defaults')->defaultValue(['elem1', 'elem2'])->end()
- ->scalarNode('scalar_required')->isRequired()->end()
- ->scalarNode('scalar_deprecated')->setDeprecated()->end()
- ->scalarNode('scalar_deprecated_with_message')->setDeprecated('Deprecation custom message for "%node%" at "%path%"')->end()
- ->scalarNode('node_with_a_looong_name')->end()
- ->enumNode('enum_with_default')->values(['this', 'that'])->defaultValue('this')->end()
- ->enumNode('enum')->values(['this', 'that'])->end()
- ->arrayNode('array')
- ->info('some info')
- ->canBeUnset()
- ->children()
- ->scalarNode('child1')->end()
- ->scalarNode('child2')->end()
- ->scalarNode('child3')
- ->info(
- "this is a long\n".
- "multi-line info text\n".
- 'which should be indented'
- )
- ->example('example setting')
- ->end()
- ->end()
- ->end()
- ->arrayNode('scalar_prototyped')
- ->prototype('scalar')->end()
- ->end()
- ->arrayNode('parameters')
- ->useAttributeAsKey('name')
- ->prototype('scalar')->info('Parameter name')->end()
- ->end()
- ->arrayNode('connections')
- ->prototype('array')
- ->children()
- ->scalarNode('user')->end()
- ->scalarNode('pass')->end()
- ->end()
- ->end()
- ->end()
- ->arrayNode('cms_pages')
- ->useAttributeAsKey('page')
- ->prototype('array')
- ->useAttributeAsKey('locale')
- ->prototype('array')
- ->children()
- ->scalarNode('title')->isRequired()->end()
- ->scalarNode('path')->isRequired()->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->arrayNode('pipou')
- ->useAttributeAsKey('name')
- ->prototype('array')
- ->prototype('array')
- ->children()
- ->scalarNode('didou')
- ->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ->end()
- ;
-
- return $treeBuilder;
- }
-}
diff --git a/vendor/symfony/config/Tests/Fixtures/ParseError.php b/vendor/symfony/config/Tests/Fixtures/ParseError.php
deleted file mode 100644
index 6bb22138..00000000
--- a/vendor/symfony/config/Tests/Fixtures/ParseError.php
+++ /dev/null
@@ -1,7 +0,0 @@
-
-]>
-
diff --git a/vendor/symfony/config/Tests/Fixtures/Util/invalid.xml b/vendor/symfony/config/Tests/Fixtures/Util/invalid.xml
deleted file mode 100644
index a07af9fd..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Util/invalid.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/vendor/symfony/config/Tests/Fixtures/Util/invalid_schema.xml b/vendor/symfony/config/Tests/Fixtures/Util/invalid_schema.xml
deleted file mode 100644
index e2725a2c..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Util/invalid_schema.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/vendor/symfony/config/Tests/Fixtures/Util/not_readable.xml b/vendor/symfony/config/Tests/Fixtures/Util/not_readable.xml
deleted file mode 100644
index e69de29b..00000000
diff --git a/vendor/symfony/config/Tests/Fixtures/Util/schema.xsd b/vendor/symfony/config/Tests/Fixtures/Util/schema.xsd
deleted file mode 100644
index e56820f6..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Util/schema.xsd
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
diff --git a/vendor/symfony/config/Tests/Fixtures/Util/valid.xml b/vendor/symfony/config/Tests/Fixtures/Util/valid.xml
deleted file mode 100644
index a96bb382..00000000
--- a/vendor/symfony/config/Tests/Fixtures/Util/valid.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-
-
-
diff --git a/vendor/symfony/config/Tests/Fixtures/foo.xml b/vendor/symfony/config/Tests/Fixtures/foo.xml
deleted file mode 100644
index e69de29b..00000000
diff --git a/vendor/symfony/config/Tests/Loader/DelegatingLoaderTest.php b/vendor/symfony/config/Tests/Loader/DelegatingLoaderTest.php
deleted file mode 100644
index 38ae6ff7..00000000
--- a/vendor/symfony/config/Tests/Loader/DelegatingLoaderTest.php
+++ /dev/null
@@ -1,69 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Loader;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Loader\DelegatingLoader;
-use Symfony\Component\Config\Loader\LoaderResolver;
-
-class DelegatingLoaderTest extends TestCase
-{
- public function testConstructor()
- {
- new DelegatingLoader($resolver = new LoaderResolver());
- $this->assertTrue(true, '__construct() takes a loader resolver as its first argument');
- }
-
- public function testGetSetResolver()
- {
- $resolver = new LoaderResolver();
- $loader = new DelegatingLoader($resolver);
- $this->assertSame($resolver, $loader->getResolver(), '->getResolver() gets the resolver loader');
- $loader->setResolver($resolver = new LoaderResolver());
- $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
- }
-
- public function testSupports()
- {
- $loader1 = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $loader1->expects($this->once())->method('supports')->willReturn(true);
- $loader = new DelegatingLoader(new LoaderResolver([$loader1]));
- $this->assertTrue($loader->supports('foo.xml'), '->supports() returns true if the resource is loadable');
-
- $loader1 = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $loader1->expects($this->once())->method('supports')->willReturn(false);
- $loader = new DelegatingLoader(new LoaderResolver([$loader1]));
- $this->assertFalse($loader->supports('foo.foo'), '->supports() returns false if the resource is not loadable');
- }
-
- public function testLoad()
- {
- $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $loader->expects($this->once())->method('supports')->willReturn(true);
- $loader->expects($this->once())->method('load');
- $resolver = new LoaderResolver([$loader]);
- $loader = new DelegatingLoader($resolver);
-
- $loader->load('foo');
- }
-
- public function testLoadThrowsAnExceptionIfTheResourceCannotBeLoaded()
- {
- $this->expectException('Symfony\Component\Config\Exception\FileLoaderLoadException');
- $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $loader->expects($this->once())->method('supports')->willReturn(false);
- $resolver = new LoaderResolver([$loader]);
- $loader = new DelegatingLoader($resolver);
-
- $loader->load('foo');
- }
-}
diff --git a/vendor/symfony/config/Tests/Loader/FileLoaderTest.php b/vendor/symfony/config/Tests/Loader/FileLoaderTest.php
deleted file mode 100644
index b59ace46..00000000
--- a/vendor/symfony/config/Tests/Loader/FileLoaderTest.php
+++ /dev/null
@@ -1,128 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Loader;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\FileLocator;
-use Symfony\Component\Config\Loader\FileLoader;
-use Symfony\Component\Config\Loader\LoaderResolver;
-
-class FileLoaderTest extends TestCase
-{
- public function testImportWithFileLocatorDelegation()
- {
- $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
-
- $locatorMockForAdditionalLoader = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
- $locatorMockForAdditionalLoader->expects($this->any())->method('locate')->will($this->onConsecutiveCalls(
- ['path/to/file1'], // Default
- ['path/to/file1', 'path/to/file2'], // First is imported
- ['path/to/file1', 'path/to/file2'], // Second is imported
- ['path/to/file1'], // Exception
- ['path/to/file1', 'path/to/file2'] // Exception
- ));
-
- $fileLoader = new TestFileLoader($locatorMock);
- $fileLoader->setSupports(false);
- $fileLoader->setCurrentDir('.');
-
- $additionalLoader = new TestFileLoader($locatorMockForAdditionalLoader);
- $additionalLoader->setCurrentDir('.');
-
- $fileLoader->setResolver($loaderResolver = new LoaderResolver([$fileLoader, $additionalLoader]));
-
- // Default case
- $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));
-
- // Check first file is imported if not already loading
- $this->assertSame('path/to/file1', $fileLoader->import('my_resource'));
-
- // Check second file is imported if first is already loading
- $fileLoader->addLoading('path/to/file1');
- $this->assertSame('path/to/file2', $fileLoader->import('my_resource'));
-
- // Check exception throws if first (and only available) file is already loading
- try {
- $fileLoader->import('my_resource');
- $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
- } catch (\Exception $e) {
- $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
- }
-
- // Check exception throws if all files are already loading
- try {
- $fileLoader->addLoading('path/to/file2');
- $fileLoader->import('my_resource');
- $this->fail('->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
- } catch (\Exception $e) {
- $this->assertInstanceOf('Symfony\Component\Config\Exception\FileLoaderImportCircularReferenceException', $e, '->import() throws a FileLoaderImportCircularReferenceException if the resource is already loading');
- }
- }
-
- public function testImportWithGlobLikeResource()
- {
- $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
- $loader = new TestFileLoader($locatorMock);
-
- $this->assertSame('[foo]', $loader->import('[foo]'));
- }
-
- public function testImportWithNoGlobMatch()
- {
- $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
- $loader = new TestFileLoader($locatorMock);
-
- $this->assertNull($loader->import('./*.abc'));
- }
-
- public function testImportWithSimpleGlob()
- {
- $loader = new TestFileLoader(new FileLocator(__DIR__));
-
- $this->assertSame(__FILE__, strtr($loader->import('FileLoaderTest.*'), '/', \DIRECTORY_SEPARATOR));
- }
-}
-
-class TestFileLoader extends FileLoader
-{
- private $supports = true;
-
- public function load($resource, $type = null)
- {
- return $resource;
- }
-
- public function supports($resource, $type = null)
- {
- return $this->supports;
- }
-
- public function addLoading($resource)
- {
- self::$loading[$resource] = true;
- }
-
- public function removeLoading($resource)
- {
- unset(self::$loading[$resource]);
- }
-
- public function clearLoading()
- {
- self::$loading = [];
- }
-
- public function setSupports($supports)
- {
- $this->supports = $supports;
- }
-}
diff --git a/vendor/symfony/config/Tests/Loader/LoaderResolverTest.php b/vendor/symfony/config/Tests/Loader/LoaderResolverTest.php
deleted file mode 100644
index aabc2a60..00000000
--- a/vendor/symfony/config/Tests/Loader/LoaderResolverTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Loader;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Loader\LoaderResolver;
-
-class LoaderResolverTest extends TestCase
-{
- public function testConstructor()
- {
- $resolver = new LoaderResolver([
- $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock(),
- ]);
-
- $this->assertEquals([$loader], $resolver->getLoaders(), '__construct() takes an array of loaders as its first argument');
- }
-
- public function testResolve()
- {
- $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $resolver = new LoaderResolver([$loader]);
- $this->assertFalse($resolver->resolve('foo.foo'), '->resolve() returns false if no loader is able to load the resource');
-
- $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $loader->expects($this->once())->method('supports')->willReturn(true);
- $resolver = new LoaderResolver([$loader]);
- $this->assertEquals($loader, $resolver->resolve(function () {}), '->resolve() returns the loader for the given resource');
- }
-
- public function testLoaders()
- {
- $resolver = new LoaderResolver();
- $resolver->addLoader($loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock());
-
- $this->assertEquals([$loader], $resolver->getLoaders(), 'addLoader() adds a loader');
- }
-}
diff --git a/vendor/symfony/config/Tests/Loader/LoaderTest.php b/vendor/symfony/config/Tests/Loader/LoaderTest.php
deleted file mode 100644
index 79ddf00f..00000000
--- a/vendor/symfony/config/Tests/Loader/LoaderTest.php
+++ /dev/null
@@ -1,116 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Loader;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Loader\Loader;
-
-class LoaderTest extends TestCase
-{
- public function testGetSetResolver()
- {
- $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
-
- $loader = new ProjectLoader1();
- $loader->setResolver($resolver);
-
- $this->assertSame($resolver, $loader->getResolver(), '->setResolver() sets the resolver loader');
- }
-
- public function testResolve()
- {
- $resolvedLoader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
-
- $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
- $resolver->expects($this->once())
- ->method('resolve')
- ->with('foo.xml')
- ->willReturn($resolvedLoader);
-
- $loader = new ProjectLoader1();
- $loader->setResolver($resolver);
-
- $this->assertSame($loader, $loader->resolve('foo.foo'), '->resolve() finds a loader');
- $this->assertSame($resolvedLoader, $loader->resolve('foo.xml'), '->resolve() finds a loader');
- }
-
- public function testResolveWhenResolverCannotFindLoader()
- {
- $this->expectException('Symfony\Component\Config\Exception\FileLoaderLoadException');
- $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
- $resolver->expects($this->once())
- ->method('resolve')
- ->with('FOOBAR')
- ->willReturn(false);
-
- $loader = new ProjectLoader1();
- $loader->setResolver($resolver);
-
- $loader->resolve('FOOBAR');
- }
-
- public function testImport()
- {
- $resolvedLoader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $resolvedLoader->expects($this->once())
- ->method('load')
- ->with('foo')
- ->willReturn('yes');
-
- $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
- $resolver->expects($this->once())
- ->method('resolve')
- ->with('foo')
- ->willReturn($resolvedLoader);
-
- $loader = new ProjectLoader1();
- $loader->setResolver($resolver);
-
- $this->assertEquals('yes', $loader->import('foo'));
- }
-
- public function testImportWithType()
- {
- $resolvedLoader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock();
- $resolvedLoader->expects($this->once())
- ->method('load')
- ->with('foo', 'bar')
- ->willReturn('yes');
-
- $resolver = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderResolverInterface')->getMock();
- $resolver->expects($this->once())
- ->method('resolve')
- ->with('foo', 'bar')
- ->willReturn($resolvedLoader);
-
- $loader = new ProjectLoader1();
- $loader->setResolver($resolver);
-
- $this->assertEquals('yes', $loader->import('foo', 'bar'));
- }
-}
-
-class ProjectLoader1 extends Loader
-{
- public function load($resource, $type = null)
- {
- }
-
- public function supports($resource, $type = null)
- {
- return \is_string($resource) && 'foo' === pathinfo($resource, \PATHINFO_EXTENSION);
- }
-
- public function getType()
- {
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/ClassExistenceResourceTest.php b/vendor/symfony/config/Tests/Resource/ClassExistenceResourceTest.php
deleted file mode 100644
index 8020a578..00000000
--- a/vendor/symfony/config/Tests/Resource/ClassExistenceResourceTest.php
+++ /dev/null
@@ -1,130 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\ClassExistenceResource;
-use Symfony\Component\Config\Tests\Fixtures\BadFileName;
-use Symfony\Component\Config\Tests\Fixtures\BadParent;
-use Symfony\Component\Config\Tests\Fixtures\ParseError;
-use Symfony\Component\Config\Tests\Fixtures\Resource\ConditionalClass;
-
-class ClassExistenceResourceTest extends TestCase
-{
- public function testToString()
- {
- $res = new ClassExistenceResource('BarClass');
- $this->assertSame('BarClass', (string) $res);
- }
-
- public function testGetResource()
- {
- $res = new ClassExistenceResource('BarClass');
- $this->assertSame('BarClass', $res->getResource());
- }
-
- public function testIsFreshWhenClassDoesNotExist()
- {
- $res = new ClassExistenceResource('Symfony\Component\Config\Tests\Fixtures\BarClass');
-
- $this->assertTrue($res->isFresh(time()));
-
- eval(<<assertFalse($res->isFresh(time()));
- }
-
- public function testIsFreshWhenClassExists()
- {
- $res = new ClassExistenceResource('Symfony\Component\Config\Tests\Resource\ClassExistenceResourceTest');
-
- $this->assertTrue($res->isFresh(time()));
- }
-
- public function testExistsKo()
- {
- spl_autoload_register($autoloader = function ($class) use (&$loadedClass) { $loadedClass = $class; });
-
- try {
- $res = new ClassExistenceResource('MissingFooClass');
- $this->assertTrue($res->isFresh(0));
-
- $this->assertSame('MissingFooClass', $loadedClass);
-
- $loadedClass = 123;
-
- new ClassExistenceResource('MissingFooClass', false);
-
- $this->assertSame(123, $loadedClass);
- } finally {
- spl_autoload_unregister($autoloader);
- }
- }
-
- public function testBadParentWithTimestamp()
- {
- $res = new ClassExistenceResource(BadParent::class, false);
- $this->assertTrue($res->isFresh(time()));
- }
-
- public function testBadParentWithNoTimestamp()
- {
- $this->expectException('ReflectionException');
- $this->expectExceptionMessage('Class "Symfony\Component\Config\Tests\Fixtures\MissingParent" not found while loading "Symfony\Component\Config\Tests\Fixtures\BadParent".');
-
- $res = new ClassExistenceResource(BadParent::class, false);
- $res->isFresh(0);
- }
-
- public function testBadFileName()
- {
- $this->expectException('ReflectionException');
- $this->expectExceptionMessage('Mismatch between file name and class name.');
-
- $res = new ClassExistenceResource(BadFileName::class, false);
- $res->isFresh(0);
- }
-
- public function testBadFileNameBis()
- {
- $this->expectException('ReflectionException');
- $this->expectExceptionMessage('Mismatch between file name and class name.');
-
- $res = new ClassExistenceResource(BadFileName::class, false);
- $res->isFresh(0);
- }
-
- public function testConditionalClass()
- {
- $res = new ClassExistenceResource(ConditionalClass::class, false);
-
- $this->assertFalse($res->isFresh(0));
- }
-
- /**
- * @requires PHP 7
- */
- public function testParseError()
- {
- $this->expectException('ParseError');
-
- $res = new ClassExistenceResource(ParseError::class, false);
- $res->isFresh(0);
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/ComposerResourceTest.php b/vendor/symfony/config/Tests/Resource/ComposerResourceTest.php
deleted file mode 100644
index 6857c766..00000000
--- a/vendor/symfony/config/Tests/Resource/ComposerResourceTest.php
+++ /dev/null
@@ -1,47 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use Composer\Autoload\ClassLoader;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\ComposerResource;
-
-class ComposerResourceTest extends TestCase
-{
- public function testGetVendor()
- {
- $res = new ComposerResource();
-
- $r = new \ReflectionClass(ClassLoader::class);
- $found = false;
-
- foreach ($res->getVendors() as $vendor) {
- if ($vendor && 0 === strpos($r->getFileName(), $vendor)) {
- $found = true;
- break;
- }
- }
-
- $this->assertTrue($found);
- }
-
- public function testSerializeUnserialize()
- {
- $res = new ComposerResource();
- $ser = unserialize(serialize($res));
-
- $this->assertTrue($res->isFresh(0));
- $this->assertTrue($ser->isFresh(0));
-
- $this->assertEquals($res, $ser);
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/DirectoryResourceTest.php b/vendor/symfony/config/Tests/Resource/DirectoryResourceTest.php
deleted file mode 100644
index 700df456..00000000
--- a/vendor/symfony/config/Tests/Resource/DirectoryResourceTest.php
+++ /dev/null
@@ -1,181 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\DirectoryResource;
-
-class DirectoryResourceTest extends TestCase
-{
- protected $directory;
-
- protected function setUp()
- {
- $this->directory = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'symfonyDirectoryIterator';
- if (!file_exists($this->directory)) {
- mkdir($this->directory);
- }
- touch($this->directory.'/tmp.xml');
- }
-
- protected function tearDown()
- {
- if (!is_dir($this->directory)) {
- return;
- }
- $this->removeDirectory($this->directory);
- }
-
- protected function removeDirectory($directory)
- {
- $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory), \RecursiveIteratorIterator::CHILD_FIRST);
- foreach ($iterator as $path) {
- if (preg_match('#[/\\\\]\.\.?$#', $path->__toString())) {
- continue;
- }
- if ($path->isDir()) {
- rmdir($path->__toString());
- } else {
- unlink($path->__toString());
- }
- }
- rmdir($directory);
- }
-
- public function testGetResource()
- {
- $resource = new DirectoryResource($this->directory);
- $this->assertSame(realpath($this->directory), $resource->getResource(), '->getResource() returns the path to the resource');
- }
-
- public function testGetPattern()
- {
- $resource = new DirectoryResource($this->directory, 'bar');
- $this->assertEquals('bar', $resource->getPattern());
- }
-
- public function testResourceDoesNotExist()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessageMatches('/The directory ".*" does not exist./');
- new DirectoryResource('/____foo/foobar'.mt_rand(1, 999999));
- }
-
- public function testIsFresh()
- {
- $resource = new DirectoryResource($this->directory);
- $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if the resource has not changed');
- $this->assertFalse($resource->isFresh(time() - 86400), '->isFresh() returns false if the resource has been updated');
- }
-
- public function testIsFreshForDeletedResources()
- {
- $resource = new DirectoryResource($this->directory);
- $this->removeDirectory($this->directory);
-
- $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the resource does not exist');
- }
-
- public function testIsFreshUpdateFile()
- {
- $resource = new DirectoryResource($this->directory);
- touch($this->directory.'/tmp.xml', time() + 20);
- $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an existing file is modified');
- }
-
- public function testIsFreshNewFile()
- {
- $resource = new DirectoryResource($this->directory);
- touch($this->directory.'/new.xml', time() + 20);
- $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file is added');
- }
-
- public function testIsFreshNewFileWithDifferentPattern()
- {
- $resource = new DirectoryResource($this->directory, '/.xml$/');
- touch($this->directory.'/new.yaml', time() + 20);
- $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if a new file with a non-matching pattern is added');
- }
-
- public function testIsFreshDeleteFile()
- {
- $resource = new DirectoryResource($this->directory);
- $time = time();
- sleep(1);
- unlink($this->directory.'/tmp.xml');
- $this->assertFalse($resource->isFresh($time), '->isFresh() returns false if an existing file is removed');
- }
-
- public function testIsFreshDeleteDirectory()
- {
- $resource = new DirectoryResource($this->directory);
- $this->removeDirectory($this->directory);
- $this->assertFalse($resource->isFresh(time()), '->isFresh() returns false if the whole resource is removed');
- }
-
- public function testIsFreshCreateFileInSubdirectory()
- {
- $subdirectory = $this->directory.'/subdirectory';
- mkdir($subdirectory);
-
- $resource = new DirectoryResource($this->directory);
- $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if an unmodified subdirectory exists');
-
- touch($subdirectory.'/newfile.xml', time() + 20);
- $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a new file in a subdirectory is added');
- }
-
- public function testIsFreshModifySubdirectory()
- {
- $resource = new DirectoryResource($this->directory);
-
- $subdirectory = $this->directory.'/subdirectory';
- mkdir($subdirectory);
- touch($subdirectory, time() + 20);
-
- $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if a subdirectory is modified (e.g. a file gets deleted)');
- }
-
- public function testFilterRegexListNoMatch()
- {
- $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');
-
- touch($this->directory.'/new.bar', time() + 20);
- $this->assertTrue($resource->isFresh(time() + 10), '->isFresh() returns true if a new file not matching the filter regex is created');
- }
-
- public function testFilterRegexListMatch()
- {
- $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');
-
- touch($this->directory.'/new.xml', time() + 20);
- $this->assertFalse($resource->isFresh(time() + 10), '->isFresh() returns false if an new file matching the filter regex is created ');
- }
-
- public function testSerializeUnserialize()
- {
- $resource = new DirectoryResource($this->directory, '/\.(foo|xml)$/');
-
- unserialize(serialize($resource));
-
- $this->assertSame(realpath($this->directory), $resource->getResource());
- $this->assertSame('/\.(foo|xml)$/', $resource->getPattern());
- }
-
- public function testResourcesWithDifferentPatternsAreDifferent()
- {
- $resourceA = new DirectoryResource($this->directory, '/.xml$/');
- $resourceB = new DirectoryResource($this->directory, '/.yaml$/');
-
- $this->assertCount(2, array_unique([$resourceA, $resourceB]));
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/FileExistenceResourceTest.php b/vendor/symfony/config/Tests/Resource/FileExistenceResourceTest.php
deleted file mode 100644
index ff7fc7b5..00000000
--- a/vendor/symfony/config/Tests/Resource/FileExistenceResourceTest.php
+++ /dev/null
@@ -1,71 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\FileExistenceResource;
-
-class FileExistenceResourceTest extends TestCase
-{
- protected $resource;
- protected $file;
- protected $time;
-
- protected function setUp()
- {
- $this->file = realpath(sys_get_temp_dir()).'/tmp.xml';
- $this->time = time();
- $this->resource = new FileExistenceResource($this->file);
- }
-
- protected function tearDown()
- {
- if (file_exists($this->file)) {
- @unlink($this->file);
- }
- }
-
- public function testToString()
- {
- $this->assertSame($this->file, (string) $this->resource);
- }
-
- public function testGetResource()
- {
- $this->assertSame($this->file, $this->resource->getResource(), '->getResource() returns the path to the resource');
- }
-
- public function testIsFreshWithExistingResource()
- {
- touch($this->file, $this->time);
- $serialized = serialize(new FileExistenceResource($this->file));
-
- $resource = unserialize($serialized);
- $this->assertTrue($resource->isFresh($this->time), '->isFresh() returns true if the resource is still present');
-
- unlink($this->file);
- $resource = unserialize($serialized);
- $this->assertFalse($resource->isFresh($this->time), '->isFresh() returns false if the resource has been deleted');
- }
-
- public function testIsFreshWithAbsentResource()
- {
- $serialized = serialize(new FileExistenceResource($this->file));
-
- $resource = unserialize($serialized);
- $this->assertTrue($resource->isFresh($this->time), '->isFresh() returns true if the resource is still absent');
-
- touch($this->file, $this->time);
- $resource = unserialize($serialized);
- $this->assertFalse($resource->isFresh($this->time), '->isFresh() returns false if the resource has been created');
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/FileResourceTest.php b/vendor/symfony/config/Tests/Resource/FileResourceTest.php
deleted file mode 100644
index a84faa95..00000000
--- a/vendor/symfony/config/Tests/Resource/FileResourceTest.php
+++ /dev/null
@@ -1,81 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\FileResource;
-
-class FileResourceTest extends TestCase
-{
- protected $resource;
- protected $file;
- protected $time;
-
- protected function setUp()
- {
- $this->file = sys_get_temp_dir().'/tmp.xml';
- $this->time = time();
- touch($this->file, $this->time);
- $this->resource = new FileResource($this->file);
- }
-
- protected function tearDown()
- {
- if (file_exists($this->file)) {
- @unlink($this->file);
- }
- }
-
- public function testGetResource()
- {
- $this->assertSame(realpath($this->file), $this->resource->getResource(), '->getResource() returns the path to the resource');
- }
-
- public function testGetResourceWithScheme()
- {
- $resource = new FileResource('file://'.$this->file);
- $this->assertSame('file://'.$this->file, $resource->getResource(), '->getResource() returns the path to the schemed resource');
- }
-
- public function testToString()
- {
- $this->assertSame(realpath($this->file), (string) $this->resource);
- }
-
- public function testResourceDoesNotExist()
- {
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessageMatches('/The file ".*" does not exist./');
- new FileResource('/____foo/foobar'.mt_rand(1, 999999));
- }
-
- public function testIsFresh()
- {
- $this->assertTrue($this->resource->isFresh($this->time), '->isFresh() returns true if the resource has not changed in same second');
- $this->assertTrue($this->resource->isFresh($this->time + 10), '->isFresh() returns true if the resource has not changed');
- $this->assertFalse($this->resource->isFresh($this->time - 86400), '->isFresh() returns false if the resource has been updated');
- }
-
- public function testIsFreshForDeletedResources()
- {
- unlink($this->file);
-
- $this->assertFalse($this->resource->isFresh($this->time), '->isFresh() returns false if the resource does not exist');
- }
-
- public function testSerializeUnserialize()
- {
- unserialize(serialize($this->resource));
-
- $this->assertSame(realpath($this->file), $this->resource->getResource());
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/GlobResourceTest.php b/vendor/symfony/config/Tests/Resource/GlobResourceTest.php
deleted file mode 100644
index cfbfd2b4..00000000
--- a/vendor/symfony/config/Tests/Resource/GlobResourceTest.php
+++ /dev/null
@@ -1,114 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\GlobResource;
-
-class GlobResourceTest extends TestCase
-{
- protected function tearDown()
- {
- $dir = \dirname(__DIR__).'/Fixtures';
- @rmdir($dir.'/TmpGlob');
- @unlink($dir.'/TmpGlob');
- @unlink($dir.'/Resource/TmpGlob');
- touch($dir.'/Resource/.hiddenFile');
- }
-
- public function testIterator()
- {
- $dir = \dirname(__DIR__).\DIRECTORY_SEPARATOR.'Fixtures';
- $resource = new GlobResource($dir, '/Resource', true);
-
- $paths = iterator_to_array($resource);
-
- $file = $dir.'/Resource'.\DIRECTORY_SEPARATOR.'ConditionalClass.php';
- $this->assertEquals([$file => new \SplFileInfo($file)], $paths);
- $this->assertInstanceOf('SplFileInfo', current($paths));
- $this->assertSame($dir, $resource->getPrefix());
-
- $resource = new GlobResource($dir, '/**/Resource', true);
-
- $paths = iterator_to_array($resource);
-
- $file = $dir.\DIRECTORY_SEPARATOR.'Resource'.\DIRECTORY_SEPARATOR.'ConditionalClass.php';
- $this->assertEquals([$file => $file], $paths);
- $this->assertInstanceOf('SplFileInfo', current($paths));
- $this->assertSame($dir, $resource->getPrefix());
- }
-
- public function testIsFreshNonRecursiveDetectsNewFile()
- {
- $dir = \dirname(__DIR__).'/Fixtures';
- $resource = new GlobResource($dir, '/*', false);
-
- $this->assertTrue($resource->isFresh(0));
-
- mkdir($dir.'/TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- rmdir($dir.'/TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- touch($dir.'/TmpGlob');
- $this->assertFalse($resource->isFresh(0));
-
- unlink($dir.'/TmpGlob');
- $this->assertTrue($resource->isFresh(0));
- }
-
- public function testIsFreshNonRecursiveDetectsRemovedFile()
- {
- $dir = \dirname(__DIR__).'/Fixtures';
- $resource = new GlobResource($dir, '/*', false);
-
- touch($dir.'/TmpGlob');
- touch($dir.'/.TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- unlink($dir.'/.TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- unlink($dir.'/TmpGlob');
- $this->assertFalse($resource->isFresh(0));
- }
-
- public function testIsFreshRecursiveDetectsRemovedFile()
- {
- $dir = \dirname(__DIR__).'/Fixtures';
- $resource = new GlobResource($dir, '/*', true);
-
- touch($dir.'/Resource/TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- unlink($dir.'/Resource/TmpGlob');
- $this->assertFalse($resource->isFresh(0));
-
- touch($dir.'/Resource/TmpGlob');
- $this->assertTrue($resource->isFresh(0));
-
- unlink($dir.'/Resource/.hiddenFile');
- $this->assertTrue($resource->isFresh(0));
- }
-
- public function testIsFreshRecursiveDetectsNewFile()
- {
- $dir = \dirname(__DIR__).'/Fixtures';
- $resource = new GlobResource($dir, '/*', true);
-
- $this->assertTrue($resource->isFresh(0));
-
- touch($dir.'/Resource/TmpGlob');
- $this->assertFalse($resource->isFresh(0));
- }
-}
diff --git a/vendor/symfony/config/Tests/Resource/ReflectionClassResourceTest.php b/vendor/symfony/config/Tests/Resource/ReflectionClassResourceTest.php
deleted file mode 100644
index 74ed6b3e..00000000
--- a/vendor/symfony/config/Tests/Resource/ReflectionClassResourceTest.php
+++ /dev/null
@@ -1,223 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\ReflectionClassResource;
-use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
-
-class ReflectionClassResourceTest extends TestCase
-{
- public function testToString()
- {
- $res = new ReflectionClassResource(new \ReflectionClass('ErrorException'));
-
- $this->assertSame('reflection.ErrorException', (string) $res);
- }
-
- public function testSerializeUnserialize()
- {
- $res = new ReflectionClassResource(new \ReflectionClass(DummyInterface::class));
- $ser = unserialize(serialize($res));
-
- $this->assertTrue($res->isFresh(0));
- $this->assertTrue($ser->isFresh(0));
-
- $this->assertSame((string) $res, (string) $ser);
- }
-
- public function testIsFresh()
- {
- $res = new ReflectionClassResource(new \ReflectionClass(__CLASS__));
- $mtime = filemtime(__FILE__);
-
- $this->assertTrue($res->isFresh($mtime), '->isFresh() returns true if the resource has not changed in same second');
- $this->assertTrue($res->isFresh($mtime + 10), '->isFresh() returns true if the resource has not changed');
- $this->assertTrue($res->isFresh($mtime - 86400), '->isFresh() returns true if the resource has not changed');
- }
-
- public function testIsFreshForDeletedResources()
- {
- $now = time();
- $tmp = sys_get_temp_dir().'/tmp.php';
- file_put_contents($tmp, 'assertTrue($res->isFresh($now));
-
- unlink($tmp);
- $this->assertFalse($res->isFresh($now), '->isFresh() returns false if the resource does not exist');
- }
-
- /**
- * @dataProvider provideHashedSignature
- */
- public function testHashedSignature($changeExpected, $changedLine, $changedCode, $setContext = null)
- {
- if ($setContext) {
- $setContext();
- }
-
- $code = <<<'EOPHP'
-/* 0*/
-/* 1*/ class %s extends ErrorException
-/* 2*/ {
-/* 3*/ const FOO = 123;
-/* 4*/
-/* 5*/ public $pub = [];
-/* 6*/
-/* 7*/ protected $prot;
-/* 8*/
-/* 9*/ private $priv;
-/*10*/
-/*11*/ public function pub($arg = null) {}
-/*12*/
-/*13*/ protected function prot($a = []) {}
-/*14*/
-/*15*/ private function priv() {}
-/*16*/
-/*17*/ public function ccc($bar = A_CONSTANT_THAT_FOR_SURE_WILL_NEVER_BE_DEFINED_CCCCCC) {}
-/*18*/ }
-EOPHP;
-
- static $expectedSignature, $generateSignature;
-
- if (null === $expectedSignature) {
- eval(sprintf($code, $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
- $r = new \ReflectionClass(ReflectionClassResource::class);
- $generateSignature = $r->getMethod('generateSignature');
- $generateSignature->setAccessible(true);
- $generateSignature = $generateSignature->getClosure($r->newInstanceWithoutConstructor());
- $expectedSignature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
- }
-
- $code = explode("\n", $code);
- if (null !== $changedCode) {
- $code[$changedLine] = $changedCode;
- }
- eval(sprintf(implode("\n", $code), $class = 'Foo'.str_replace('.', '_', uniqid('', true))));
- $signature = implode("\n", iterator_to_array($generateSignature(new \ReflectionClass($class))));
-
- if ($changeExpected) {
- $this->assertNotSame($expectedSignature, $signature);
- } else {
- $this->assertSame($expectedSignature, $signature);
- }
- }
-
- public function provideHashedSignature()
- {
- yield [0, 0, "// line change\n\n"];
- yield [1, 0, '/** class docblock */'];
- yield [1, 1, 'abstract class %s'];
- yield [1, 1, 'final class %s'];
- yield [1, 1, 'class %s extends Exception'];
- yield [1, 1, 'class %s implements '.DummyInterface::class];
- yield [1, 3, 'const FOO = 456;'];
- yield [1, 3, 'const BAR = 123;'];
- yield [1, 4, '/** pub docblock */'];
- yield [1, 5, 'protected $pub = [];'];
- yield [1, 5, 'public $pub = [123];'];
- yield [1, 6, '/** prot docblock */'];
- yield [1, 7, 'private $prot;'];
- yield [0, 8, '/** priv docblock */'];
- yield [0, 9, 'private $priv = 123;'];
- yield [1, 10, '/** pub docblock */'];
- if (\PHP_VERSION_ID >= 50600) {
- yield [1, 11, 'public function pub(...$arg) {}'];
- }
- if (\PHP_VERSION_ID >= 70000) {
- yield [1, 11, 'public function pub($arg = null): Foo {}'];
- }
- yield [0, 11, "public function pub(\$arg = null) {\nreturn 123;\n}"];
- yield [1, 12, '/** prot docblock */'];
- yield [1, 13, 'protected function prot($a = [123]) {}'];
- yield [0, 14, '/** priv docblock */'];
- yield [0, 15, ''];
-
- if (\PHP_VERSION_ID >= 70400) {
- // PHP7.4 typed properties without default value are
- // undefined, make sure this doesn't throw an error
- yield [1, 5, 'public array $pub;'];
- yield [0, 7, 'protected int $prot;'];
- yield [0, 9, 'private string $priv;'];
- }
-
- yield [1, 17, 'public function ccc($bar = 187) {}'];
- yield [1, 17, 'public function ccc($bar = ANOTHER_ONE_THAT_WILL_NEVER_BE_DEFINED_CCCCCCCCC) {}'];
- yield [1, 17, null, static function () { \define('A_CONSTANT_THAT_FOR_SURE_WILL_NEVER_BE_DEFINED_CCCCCC', 'foo'); }];
- }
-
- public function testEventSubscriber()
- {
- $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
- $this->assertTrue($res->isFresh(0));
-
- TestEventSubscriber::$subscribedEvents = [123];
- $this->assertFalse($res->isFresh(0));
-
- $res = new ReflectionClassResource(new \ReflectionClass(TestEventSubscriber::class));
- $this->assertTrue($res->isFresh(0));
- }
-
- public function testServiceSubscriber()
- {
- $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
- $this->assertTrue($res->isFresh(0));
-
- TestServiceSubscriber::$subscribedServices = [123];
- $this->assertFalse($res->isFresh(0));
-
- $res = new ReflectionClassResource(new \ReflectionClass(TestServiceSubscriber::class));
- $this->assertTrue($res->isFresh(0));
- }
-
- public function testIgnoresObjectsInSignature()
- {
- $res = new ReflectionClassResource(new \ReflectionClass(TestServiceWithStaticProperty::class));
- $this->assertTrue($res->isFresh(0));
-
- TestServiceWithStaticProperty::$initializedObject = new TestServiceWithStaticProperty();
- $this->assertTrue($res->isFresh(0));
- }
-}
-
-interface DummyInterface
-{
-}
-
-class TestEventSubscriber implements EventSubscriberInterface
-{
- public static $subscribedEvents = [];
-
- public static function getSubscribedEvents()
- {
- return self::$subscribedEvents;
- }
-}
-
-class TestServiceSubscriber implements ServiceSubscriberInterface
-{
- public static $subscribedServices = [];
-
- public static function getSubscribedServices()
- {
- return self::$subscribedServices;
- }
-}
-
-class TestServiceWithStaticProperty
-{
- public static $initializedObject;
-}
diff --git a/vendor/symfony/config/Tests/Resource/ResourceStub.php b/vendor/symfony/config/Tests/Resource/ResourceStub.php
deleted file mode 100644
index b01729cb..00000000
--- a/vendor/symfony/config/Tests/Resource/ResourceStub.php
+++ /dev/null
@@ -1,34 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Resource;
-
-use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
-
-class ResourceStub implements SelfCheckingResourceInterface
-{
- private $fresh = true;
-
- public function setFresh($isFresh)
- {
- $this->fresh = $isFresh;
- }
-
- public function __toString()
- {
- return 'stub';
- }
-
- public function isFresh($timestamp)
- {
- return $this->fresh;
- }
-}
diff --git a/vendor/symfony/config/Tests/ResourceCheckerConfigCacheTest.php b/vendor/symfony/config/Tests/ResourceCheckerConfigCacheTest.php
deleted file mode 100644
index 9be53196..00000000
--- a/vendor/symfony/config/Tests/ResourceCheckerConfigCacheTest.php
+++ /dev/null
@@ -1,150 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Resource\FileResource;
-use Symfony\Component\Config\ResourceCheckerConfigCache;
-use Symfony\Component\Config\Tests\Resource\ResourceStub;
-
-class ResourceCheckerConfigCacheTest extends TestCase
-{
- private $cacheFile = null;
-
- protected function setUp()
- {
- $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_');
- }
-
- protected function tearDown()
- {
- $files = [$this->cacheFile, "{$this->cacheFile}.meta"];
-
- foreach ($files as $file) {
- if (file_exists($file)) {
- @unlink($file);
- }
- }
- }
-
- public function testGetPath()
- {
- $cache = new ResourceCheckerConfigCache($this->cacheFile);
-
- $this->assertSame($this->cacheFile, $cache->getPath());
- }
-
- public function testCacheIsNotFreshIfEmpty()
- {
- $checker = $this->getMockBuilder('\Symfony\Component\Config\ResourceCheckerInterface')->getMock()
- ->expects($this->never())->method('supports');
-
- /* If there is nothing in the cache, it needs to be filled (and thus it's not fresh).
- It does not matter if you provide checkers or not. */
-
- unlink($this->cacheFile); // remove tempnam() side effect
- $cache = new ResourceCheckerConfigCache($this->cacheFile, [$checker]);
-
- $this->assertFalse($cache->isFresh());
- }
-
- public function testCacheIsFreshIfNoCheckerProvided()
- {
- /* For example in prod mode, you may choose not to run any checkers
- at all. In that case, the cache should always be considered fresh. */
- $cache = new ResourceCheckerConfigCache($this->cacheFile);
- $this->assertTrue($cache->isFresh());
- }
-
- public function testCacheIsFreshIfEmptyCheckerIteratorProvided()
- {
- $cache = new ResourceCheckerConfigCache($this->cacheFile, new \ArrayIterator([]));
- $this->assertTrue($cache->isFresh());
- }
-
- public function testResourcesWithoutcheckersAreIgnoredAndConsideredFresh()
- {
- /* As in the previous test, but this time we have a resource. */
- $cache = new ResourceCheckerConfigCache($this->cacheFile);
- $cache->write('', [new ResourceStub()]);
-
- $this->assertTrue($cache->isFresh()); // no (matching) ResourceChecker passed
- }
-
- public function testIsFreshWithchecker()
- {
- $checker = $this->getMockBuilder('\Symfony\Component\Config\ResourceCheckerInterface')->getMock();
-
- $checker->expects($this->once())
- ->method('supports')
- ->willReturn(true);
-
- $checker->expects($this->once())
- ->method('isFresh')
- ->willReturn(true);
-
- $cache = new ResourceCheckerConfigCache($this->cacheFile, [$checker]);
- $cache->write('', [new ResourceStub()]);
-
- $this->assertTrue($cache->isFresh());
- }
-
- public function testIsNotFreshWithchecker()
- {
- $checker = $this->getMockBuilder('\Symfony\Component\Config\ResourceCheckerInterface')->getMock();
-
- $checker->expects($this->once())
- ->method('supports')
- ->willReturn(true);
-
- $checker->expects($this->once())
- ->method('isFresh')
- ->willReturn(false);
-
- $cache = new ResourceCheckerConfigCache($this->cacheFile, [$checker]);
- $cache->write('', [new ResourceStub()]);
-
- $this->assertFalse($cache->isFresh());
- }
-
- public function testCacheIsNotFreshWhenUnserializeFails()
- {
- $checker = $this->getMockBuilder('\Symfony\Component\Config\ResourceCheckerInterface')->getMock();
- $cache = new ResourceCheckerConfigCache($this->cacheFile, [$checker]);
- $cache->write('foo', [new FileResource(__FILE__)]);
-
- $metaFile = "{$this->cacheFile}.meta";
- file_put_contents($metaFile, str_replace('FileResource', 'ClassNotHere', file_get_contents($metaFile)));
-
- $this->assertFalse($cache->isFresh());
- }
-
- public function testCacheKeepsContent()
- {
- $cache = new ResourceCheckerConfigCache($this->cacheFile);
- $cache->write('FOOBAR');
-
- $this->assertSame('FOOBAR', file_get_contents($cache->getPath()));
- }
-
- public function testCacheIsNotFreshIfNotExistsMetaFile()
- {
- $checker = $this->getMockBuilder('\Symfony\Component\Config\ResourceCheckerInterface')->getMock();
- $cache = new ResourceCheckerConfigCache($this->cacheFile, [$checker]);
- $cache->write('foo', [new FileResource(__FILE__)]);
-
- $metaFile = "{$this->cacheFile}.meta";
- unlink($metaFile);
-
- $this->assertFalse($cache->isFresh());
- }
-}
diff --git a/vendor/symfony/config/Tests/Util/XmlUtilsTest.php b/vendor/symfony/config/Tests/Util/XmlUtilsTest.php
deleted file mode 100644
index f0b77ae6..00000000
--- a/vendor/symfony/config/Tests/Util/XmlUtilsTest.php
+++ /dev/null
@@ -1,240 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Config\Tests\Util;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Config\Util\XmlUtils;
-
-class XmlUtilsTest extends TestCase
-{
- public function testLoadFile()
- {
- $fixtures = __DIR__.'/../Fixtures/Util/';
-
- try {
- XmlUtils::loadFile($fixtures);
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('is not a file', $e->getMessage());
- }
-
- try {
- XmlUtils::loadFile($fixtures.'non_existing.xml');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('is not a file', $e->getMessage());
- }
-
- try {
- if ('\\' === \DIRECTORY_SEPARATOR) {
- $this->markTestSkipped('chmod is not supported on Windows');
- }
- chmod($fixtures.'not_readable.xml', 000);
- XmlUtils::loadFile($fixtures.'not_readable.xml');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- chmod($fixtures.'not_readable.xml', 0644);
- $this->assertStringContainsString('is not readable', $e->getMessage());
- }
-
- try {
- XmlUtils::loadFile($fixtures.'invalid.xml');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('ERROR ', $e->getMessage());
- }
-
- try {
- XmlUtils::loadFile($fixtures.'document_type.xml');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('Document types are not allowed', $e->getMessage());
- }
-
- try {
- XmlUtils::loadFile($fixtures.'invalid_schema.xml', $fixtures.'schema.xsd');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('ERROR 1845', $e->getMessage());
- }
-
- try {
- XmlUtils::loadFile($fixtures.'invalid_schema.xml', 'invalid_callback_or_file');
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertStringContainsString('XSD file or callable', $e->getMessage());
- }
-
- $mock = $this->getMockBuilder(Validator::class)->getMock();
- $mock->expects($this->exactly(2))->method('validate')->will($this->onConsecutiveCalls(false, true));
-
- try {
- XmlUtils::loadFile($fixtures.'valid.xml', [$mock, 'validate']);
- $this->fail();
- } catch (\InvalidArgumentException $e) {
- $this->assertMatchesRegularExpression('/The XML file ".+" is not valid\./', $e->getMessage());
- }
-
- $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', [$mock, 'validate']));
- $this->assertSame([], libxml_get_errors());
- }
-
- public function testParseWithInvalidValidatorCallable()
- {
- $this->expectException('Symfony\Component\Config\Util\Exception\InvalidXmlException');
- $this->expectExceptionMessage('The XML is not valid');
- $fixtures = __DIR__.'/../Fixtures/Util/';
-
- $mock = $this->getMockBuilder(Validator::class)->getMock();
- $mock->expects($this->once())->method('validate')->willReturn(false);
-
- XmlUtils::parse(file_get_contents($fixtures.'valid.xml'), [$mock, 'validate']);
- }
-
- public function testLoadFileWithInternalErrorsEnabled()
- {
- $internalErrors = libxml_use_internal_errors(true);
-
- $this->assertSame([], libxml_get_errors());
- $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile(__DIR__.'/../Fixtures/Util/invalid_schema.xml'));
- $this->assertSame([], libxml_get_errors());
-
- libxml_clear_errors();
- libxml_use_internal_errors($internalErrors);
- }
-
- /**
- * @dataProvider getDataForConvertDomToArray
- */
- public function testConvertDomToArray($expected, $xml, $root = false, $checkPrefix = true)
- {
- $dom = new \DOMDocument();
- $dom->loadXML($root ? $xml : ''.$xml.'');
-
- $this->assertSame($expected, XmlUtils::convertDomElementToArray($dom->documentElement, $checkPrefix));
- }
-
- public function getDataForConvertDomToArray()
- {
- return [
- [null, ''],
- ['bar', 'bar'],
- [['bar' => 'foobar'], '', true],
- [['foo' => null], ''],
- [['foo' => 'bar'], 'bar'],
- [['foo' => ['foo' => 'bar']], ''],
- [['foo' => ['foo' => 0]], '0'],
- [['foo' => ['foo' => 'bar']], 'bar'],
- [['foo' => ['foo' => 'bar', 'value' => 'text']], 'text'],
- [['foo' => ['attr' => 'bar', 'foo' => 'text']], 'text'],
- [['foo' => ['bar', 'text']], 'bartext'],
- [['foo' => [['foo' => 'bar'], ['foo' => 'text']]], ''],
- [['foo' => ['foo' => ['bar', 'text']]], 'text'],
- [['foo' => 'bar'], 'bar'],
- [['foo' => 'text'], 'text'],
- [['foo' => ['bar' => 'bar', 'value' => 'text']], 'text', false, false],
- [['attr' => 1, 'b' => 'hello'], 'hello2', true],
- ];
- }
-
- /**
- * @dataProvider getDataForPhpize
- */
- public function testPhpize($expected, $value)
- {
- $this->assertSame($expected, XmlUtils::phpize($value));
- }
-
- public function getDataForPhpize()
- {
- return [
- ['', ''],
- [null, 'null'],
- [true, 'true'],
- [false, 'false'],
- [null, 'Null'],
- [true, 'True'],
- [false, 'False'],
- [0, '0'],
- [1, '1'],
- [-1, '-1'],
- [0777, '0777'],
- [255, '0xFF'],
- [100.0, '1e2'],
- [-120.0, '-1.2E2'],
- [-10100.1, '-10100.1'],
- ['-10,100.1', '-10,100.1'],
- ['1234 5678 9101 1121 3141', '1234 5678 9101 1121 3141'],
- ['1,2,3,4', '1,2,3,4'],
- ['11,22,33,44', '11,22,33,44'],
- ['11,222,333,4', '11,222,333,4'],
- ['1,222,333,444', '1,222,333,444'],
- ['11,222,333,444', '11,222,333,444'],
- ['111,222,333,444', '111,222,333,444'],
- ['1111,2222,3333,4444,5555', '1111,2222,3333,4444,5555'],
- ['foo', 'foo'],
- [6, '0b0110'],
- ];
- }
-
- public function testLoadEmptyXmlFile()
- {
- $file = __DIR__.'/../Fixtures/foo.xml';
-
- $this->expectException('InvalidArgumentException');
- $this->expectExceptionMessage(sprintf('File "%s" does not contain valid XML, it is empty.', $file));
-
- XmlUtils::loadFile($file);
- }
-
- // test for issue https://github.com/symfony/symfony/issues/9731
- public function testLoadWrongEmptyXMLWithErrorHandler()
- {
- if (\LIBXML_VERSION < 20900) {
- $originalDisableEntities = libxml_disable_entity_loader(false);
- }
- $errorReporting = error_reporting(-1);
-
- set_error_handler(function ($errno, $errstr) {
- throw new \Exception($errstr, $errno);
- });
-
- $file = __DIR__.'/../Fixtures/foo.xml';
- try {
- try {
- XmlUtils::loadFile($file);
- $this->fail('An exception should have been raised');
- } catch (\InvalidArgumentException $e) {
- $this->assertEquals(sprintf('File "%s" does not contain valid XML, it is empty.', $file), $e->getMessage());
- }
- } finally {
- restore_error_handler();
- error_reporting($errorReporting);
- }
-
- if (\LIBXML_VERSION < 20900) {
- $disableEntities = libxml_disable_entity_loader(true);
- libxml_disable_entity_loader($disableEntities);
-
- libxml_disable_entity_loader($originalDisableEntities);
- $this->assertFalse($disableEntities);
- }
-
- // should not throw an exception
- XmlUtils::loadFile(__DIR__.'/../Fixtures/Util/valid.xml', __DIR__.'/../Fixtures/Util/schema.xsd');
- }
-}
-
-interface Validator
-{
- public function validate();
-}
diff --git a/vendor/symfony/config/Util/Exception/InvalidXmlException.php b/vendor/symfony/config/Util/Exception/InvalidXmlException.php
index a335bbd2..155571ce 100644
--- a/vendor/symfony/config/Util/Exception/InvalidXmlException.php
+++ b/vendor/symfony/config/Util/Exception/InvalidXmlException.php
@@ -1,4 +1,5 @@
=7.0.8",
- "symfony/filesystem": "~2.8|~3.0|~4.0",
- "symfony/polyfill-ctype": "~1.8"
+ "php": ">=7.1.3",
+ "symfony/filesystem": "^3.4|^4.0|^5.0",
+ "symfony/polyfill-ctype": "~1.8",
+ "symfony/polyfill-php80": "^1.16",
+ "symfony/polyfill-php81": "^1.22"
},
"require-dev": {
- "symfony/finder": "~3.3|~4.0",
- "symfony/yaml": "~3.0|~4.0",
- "symfony/dependency-injection": "~3.3|~4.0",
- "symfony/event-dispatcher": "~3.3|~4.0"
+ "symfony/event-dispatcher": "^3.4|^4.0|^5.0",
+ "symfony/finder": "^3.4|^4.0|^5.0",
+ "symfony/messenger": "^4.1|^5.0",
+ "symfony/service-contracts": "^1.1|^2",
+ "symfony/yaml": "^3.4|^4.0|^5.0"
},
"conflict": {
- "symfony/finder": "<3.3",
- "symfony/dependency-injection": "<3.3"
+ "symfony/finder": "<3.4"
},
"suggest": {
"symfony/yaml": "To use the yaml reference dumper"
diff --git a/vendor/symfony/config/phpunit.xml.dist b/vendor/symfony/config/phpunit.xml.dist
deleted file mode 100644
index 1cfdb3cd..00000000
--- a/vendor/symfony/config/phpunit.xml.dist
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
- ./Tests/
-
-
-
-
-
- ./
-
- ./Resources
- ./Tests
- ./vendor
-
-
-
-
diff --git a/vendor/symfony/debug/BufferingLogger.php b/vendor/symfony/debug/BufferingLogger.php
index e7db3a4c..5280c33b 100644
--- a/vendor/symfony/debug/BufferingLogger.php
+++ b/vendor/symfony/debug/BufferingLogger.php
@@ -13,15 +13,22 @@
use Psr\Log\AbstractLogger;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', BufferingLogger::class, \Symfony\Component\ErrorHandler\BufferingLogger::class), \E_USER_DEPRECATED);
+
/**
* A buffering logger that stacks logs for later.
*
* @author Nicolas Grekas
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\BufferingLogger instead.
*/
class BufferingLogger extends AbstractLogger
{
private $logs = [];
+ /**
+ * @return void
+ */
public function log($level, $message, array $context = [])
{
$this->logs[] = [$level, $message, $context];
diff --git a/vendor/symfony/debug/CHANGELOG.md b/vendor/symfony/debug/CHANGELOG.md
index 31c67eb6..d49a82df 100644
--- a/vendor/symfony/debug/CHANGELOG.md
+++ b/vendor/symfony/debug/CHANGELOG.md
@@ -1,56 +1,75 @@
CHANGELOG
=========
+4.4.0
+-----
+
+ * deprecated `FlattenException`, use the `FlattenException` of the `ErrorHandler` component
+ * deprecated the whole component in favor of the `ErrorHandler` component
+
+4.3.0
+-----
+
+ * made the `ErrorHandler` and `ExceptionHandler` classes final
+ * added `Exception\FlattenException::getAsString` and
+ `Exception\FlattenException::getTraceAsString` to increase compatibility to php
+ exception objects
+
+4.0.0
+-----
+
+ * removed the symfony_debug extension
+ * removed `ContextErrorException`
+
3.4.0
-----
-* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
+ * deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()`
3.3.0
-----
-* deprecated the `ContextErrorException` class: use \ErrorException directly now
+ * deprecated the `ContextErrorException` class: use \ErrorException directly now
3.2.0
-----
-* `FlattenException::getTrace()` now returns additional type descriptions
- `integer` and `float`.
-
+ * `FlattenException::getTrace()` now returns additional type descriptions
+ `integer` and `float`.
3.0.0
-----
-* removed classes, methods and interfaces deprecated in 2.x
+ * removed classes, methods and interfaces deprecated in 2.x
2.8.0
-----
-* added BufferingLogger for errors that happen before a proper logger is configured
-* allow throwing from `__toString()` with `return trigger_error($e, E_USER_ERROR);`
-* deprecate ExceptionHandler::createResponse
+ * added BufferingLogger for errors that happen before a proper logger is configured
+ * allow throwing from `__toString()` with `return trigger_error($e, E_USER_ERROR);`
+ * deprecate ExceptionHandler::createResponse
2.7.0
-----
-* added deprecations checking for parent interfaces/classes to DebugClassLoader
-* added ZTS support to symfony_debug extension
-* added symfony_debug_backtrace() to symfony_debug extension
- to track the backtrace of fatal errors
+ * added deprecations checking for parent interfaces/classes to DebugClassLoader
+ * added ZTS support to symfony_debug extension
+ * added symfony_debug_backtrace() to symfony_debug extension
+ to track the backtrace of fatal errors
2.6.0
-----
-* generalized ErrorHandler and ExceptionHandler,
- with some new methods and others deprecated
-* enhanced error messages for uncaught exceptions
+ * generalized ErrorHandler and ExceptionHandler,
+ with some new methods and others deprecated
+ * enhanced error messages for uncaught exceptions
2.5.0
-----
-* added ExceptionHandler::setHandler()
-* added UndefinedMethodFatalErrorHandler
-* deprecated DummyException
+ * added ExceptionHandler::setHandler()
+ * added UndefinedMethodFatalErrorHandler
+ * deprecated DummyException
2.4.0
-----
diff --git a/vendor/symfony/debug/Debug.php b/vendor/symfony/debug/Debug.php
index 746f3290..99215cf3 100644
--- a/vendor/symfony/debug/Debug.php
+++ b/vendor/symfony/debug/Debug.php
@@ -11,10 +11,14 @@
namespace Symfony\Component\Debug;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', Debug::class, \Symfony\Component\ErrorHandler\Debug::class), \E_USER_DEPRECATED);
+
/**
* Registers all the debug tools.
*
* @author Fabien Potencier
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Debug instead.
*/
class Debug
{
@@ -23,7 +27,7 @@ class Debug
/**
* Enables the debug tools.
*
- * This method registers an error handler, an exception handler and a special class loader.
+ * This method registers an error handler and an exception handler.
*
* @param int $errorReportingLevel The level of error reporting you want
* @param bool $displayErrors Whether to display errors (for development) or just log them (for production)
@@ -45,7 +49,7 @@ public static function enable($errorReportingLevel = \E_ALL, $displayErrors = tr
if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) {
ini_set('display_errors', 0);
ExceptionHandler::register();
- } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), \FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) {
+ } elseif ($displayErrors && (!filter_var(\ini_get('log_errors'), \FILTER_VALIDATE_BOOLEAN) || \ini_get('error_log'))) {
// CLI - display errors only if they're not already logged to STDERR
ini_set('display_errors', 1);
}
diff --git a/vendor/symfony/debug/DebugClassLoader.php b/vendor/symfony/debug/DebugClassLoader.php
index f54d07af..6081c525 100644
--- a/vendor/symfony/debug/DebugClassLoader.php
+++ b/vendor/symfony/debug/DebugClassLoader.php
@@ -11,6 +11,10 @@
namespace Symfony\Component\Debug;
+use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation;
+
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', DebugClassLoader::class, \Symfony\Component\ErrorHandler\DebugClassLoader::class), \E_USER_DEPRECATED);
+
/**
* Autoloader checking if the class is really defined in the file found.
*
@@ -21,6 +25,9 @@
* @author Fabien Potencier
* @author Christophe Coevoet
* @author Nicolas Grekas
+ * @author Guilhem Niot
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\DebugClassLoader instead.
*/
class DebugClassLoader
{
@@ -34,8 +41,9 @@ class DebugClassLoader
private static $deprecated = [];
private static $internal = [];
private static $internalMethods = [];
- private static $php7Reserved = ['int' => 1, 'float' => 1, 'bool' => 1, 'string' => 1, 'true' => 1, 'false' => 1, 'null' => 1];
+ private static $annotatedParameters = [];
private static $darwinCache = ['/' => ['/', []]];
+ private static $method = [];
public function __construct(callable $classLoader)
{
@@ -82,8 +90,8 @@ public function getClassLoader()
public static function enable()
{
// Ensures we don't hit https://bugs.php.net/42098
- class_exists('Symfony\Component\Debug\ErrorHandler');
- class_exists('Psr\Log\LogLevel');
+ class_exists(\Symfony\Component\Debug\ErrorHandler::class);
+ class_exists(\Psr\Log\LogLevel::class);
if (!\is_array($functions = spl_autoload_functions())) {
return;
@@ -156,7 +164,7 @@ public function loadClass($class)
return;
}
} else {
- \call_user_func($this->classLoader, $class);
+ ($this->classLoader)($class);
$file = false;
}
} finally {
@@ -166,7 +174,7 @@ public function loadClass($class)
$this->checkClass($class, $file);
}
- private function checkClass($class, $file = null)
+ private function checkClass(string $class, string $file = null)
{
$exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false);
@@ -192,10 +200,6 @@ private function checkClass($class, $file = null)
$deprecations = $this->checkAnnotations($refl, $name);
- if (isset(self::$php7Reserved[strtolower($refl->getShortName())])) {
- $deprecations[] = sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName());
- }
-
foreach ($deprecations as $message) {
@trigger_error($message, \E_USER_DEPRECATED);
}
@@ -237,10 +241,28 @@ public function checkAnnotations(\ReflectionClass $refl, $class)
self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
}
}
+
+ if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, \PREG_SET_ORDER)) {
+ foreach ($notice as $method) {
+ $static = '' !== $method[1];
+ $name = $method[2];
+ $description = $method[3] ?? null;
+ if (false === strpos($name, '(')) {
+ $name .= '()';
+ }
+ if (null !== $description) {
+ $description = trim($description);
+ if (!isset($method[4])) {
+ $description .= '.';
+ }
+ }
+ self::$method[$class][] = [$class, $name, $static, $description];
+ }
+ }
}
$parent = get_parent_class($class);
- $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent);
+ $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent ?: null);
if ($parent) {
$parentAndOwnInterfaces[$parent] = $parent;
@@ -267,17 +289,40 @@ public function checkAnnotations(\ReflectionClass $refl, $class)
if (isset(self::$internal[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len)) {
$deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class);
}
+ if (isset(self::$method[$use])) {
+ if ($refl->isAbstract()) {
+ if (isset(self::$method[$class])) {
+ self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]);
+ } else {
+ self::$method[$class] = self::$method[$use];
+ }
+ } elseif (!$refl->isInterface()) {
+ $hasCall = $refl->hasMethod('__call');
+ $hasStaticCall = $refl->hasMethod('__callStatic');
+ foreach (self::$method[$use] as $method) {
+ [$interface, $name, $static, $description] = $method;
+ if ($static ? $hasStaticCall : $hasCall) {
+ continue;
+ }
+ $realName = substr($name, 0, strpos($name, '('));
+ if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) {
+ $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $class, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description);
+ }
+ }
+ }
+ }
}
if (trait_exists($class)) {
return $deprecations;
}
- // Inherit @final and @internal annotations for methods
+ // Inherit @final, @internal and @param annotations for methods
self::$finalMethods[$class] = [];
self::$internalMethods[$class] = [];
+ self::$annotatedParameters[$class] = [];
foreach ($parentAndOwnInterfaces as $use) {
- foreach (['finalMethods', 'internalMethods'] as $property) {
+ foreach (['finalMethods', 'internalMethods', 'annotatedParameters'] as $property) {
if (isset(self::${$property}[$use])) {
self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use];
}
@@ -290,26 +335,63 @@ public function checkAnnotations(\ReflectionClass $refl, $class)
}
if ($parent && isset(self::$finalMethods[$parent][$method->name])) {
- list($declaringClass, $message) = self::$finalMethods[$parent][$method->name];
+ [$declaringClass, $message] = self::$finalMethods[$parent][$method->name];
$deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
}
if (isset(self::$internalMethods[$class][$method->name])) {
- list($declaringClass, $message) = self::$internalMethods[$class][$method->name];
+ [$declaringClass, $message] = self::$internalMethods[$class][$method->name];
if (strncmp($ns, $declaringClass, $len)) {
$deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class);
}
}
- // Detect method annotations
- if (false === $doc = $method->getDocComment()) {
+ // To read method annotations
+ $doc = $method->getDocComment();
+
+ if (isset(self::$annotatedParameters[$class][$method->name])) {
+ $definedParameters = [];
+ foreach ($method->getParameters() as $parameter) {
+ $definedParameters[$parameter->name] = true;
+ }
+
+ foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) {
+ if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) {
+ $deprecations[] = sprintf($deprecation, $class);
+ }
+ }
+ }
+
+ if (!$doc) {
continue;
}
+ $finalOrInternal = false;
+
foreach (['final', 'internal'] as $annotation) {
if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) {
$message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : '';
self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message];
+ $finalOrInternal = true;
+ }
+ }
+
+ if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) {
+ continue;
+ }
+ if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, \PREG_SET_ORDER)) {
+ continue;
+ }
+ if (!isset(self::$annotatedParameters[$class][$method->name])) {
+ $definedParameters = [];
+ foreach ($method->getParameters() as $parameter) {
+ $definedParameters[$parameter->name] = true;
+ }
+ }
+ foreach ($matches as [, $parameterType, $parameterName]) {
+ if (!isset($definedParameters[$parameterName])) {
+ $parameterType = trim($parameterType);
+ self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its %s "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, interface_exists($class) ? 'interface' : 'parent class', $method->class);
}
}
}
@@ -362,7 +444,7 @@ public function checkCase(\ReflectionClass $refl, $file, $class)
/**
* `realpath` on MacOSX doesn't normalize the case of characters.
*/
- private function darwinRealpath($real)
+ private function darwinRealpath(string $real): string
{
$i = 1 + strrpos($real, '/');
$file = substr($real, $i);
@@ -377,7 +459,11 @@ private function darwinRealpath($real)
$real = self::$darwinCache[$kDir][0];
} else {
$dir = getcwd();
- chdir($real);
+
+ if (!@chdir($real)) {
+ return $real.$file;
+ }
+
$real = getcwd().'/';
chdir($dir);
@@ -429,12 +515,9 @@ private function darwinRealpath($real)
/**
* `class_implements` includes interfaces from the parents so we have to manually exclude them.
*
- * @param string $class
- * @param string|false $parent
- *
* @return string[]
*/
- private function getOwnInterfaces($class, $parent)
+ private function getOwnInterfaces(string $class, ?string $parent): array
{
$ownInterfaces = class_implements($class, false);
diff --git a/vendor/symfony/debug/ErrorHandler.php b/vendor/symfony/debug/ErrorHandler.php
index b8ec09e8..fe425e05 100644
--- a/vendor/symfony/debug/ErrorHandler.php
+++ b/vendor/symfony/debug/ErrorHandler.php
@@ -13,9 +13,9 @@
use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
-use Symfony\Component\Debug\Exception\ContextErrorException;
use Symfony\Component\Debug\Exception\FatalErrorException;
use Symfony\Component\Debug\Exception\FatalThrowableError;
+use Symfony\Component\Debug\Exception\FlattenException;
use Symfony\Component\Debug\Exception\OutOfMemoryException;
use Symfony\Component\Debug\Exception\SilencedErrorContext;
use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
@@ -23,6 +23,8 @@
use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ErrorHandler::class, \Symfony\Component\ErrorHandler\ErrorHandler::class), \E_USER_DEPRECATED);
+
/**
* A generic ErrorHandler for the PHP engine.
*
@@ -45,6 +47,10 @@
*
* @author Nicolas Grekas
* @author Grégoire Pineau
+ *
+ * @final since Symfony 4.3
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\ErrorHandler instead.
*/
class ErrorHandler
{
@@ -97,8 +103,6 @@ class ErrorHandler
private $bootstrappingLogger;
private static $reservedMemory;
- private static $stackedErrors = [];
- private static $stackedErrorLevels = [];
private static $toStringException = null;
private static $silencedErrorCache = [];
private static $silencedErrorCount = 0;
@@ -115,7 +119,7 @@ class ErrorHandler
public static function register(self $handler = null, $replace = true)
{
if (null === self::$reservedMemory) {
- self::$reservedMemory = str_repeat('x', 10240);
+ self::$reservedMemory = str_repeat('x', 32768);
register_shutdown_function(__CLASS__.'::handleFatalError');
}
@@ -165,16 +169,15 @@ public function __construct(BufferingLogger $bootstrappingLogger = null)
$this->bootstrappingLogger = $bootstrappingLogger;
$this->setDefaultLogger($bootstrappingLogger);
}
- $this->traceReflector = new \ReflectionProperty('Exception', 'trace');
+ $this->traceReflector = new \ReflectionProperty(\Exception::class, 'trace');
$this->traceReflector->setAccessible(true);
}
/**
* Sets a logger to non assigned errors levels.
*
- * @param LoggerInterface $logger A PSR-3 logger to put as default for the given levels
- * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
- * @param bool $replace Whether to replace or not any existing logger
+ * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants
+ * @param bool $replace Whether to replace or not any existing logger
*/
public function setDefaultLogger(LoggerInterface $logger, $levels = \E_ALL, $replace = false)
{
@@ -349,10 +352,10 @@ public function screamAt($levels, $replace = false)
/**
* Re-registers as a PHP error handler if levels changed.
*/
- private function reRegister($prev)
+ private function reRegister(int $prev)
{
- if ($prev !== $this->thrownErrors | $this->loggedErrors) {
- $handler = set_error_handler('var_dump');
+ if ($prev !== ($this->thrownErrors | $this->loggedErrors)) {
+ $handler = set_error_handler('is_int');
$handler = \is_array($handler) ? $handler[0] : null;
restore_error_handler();
if ($handler === $this) {
@@ -400,38 +403,19 @@ public function handleError($type, $message, $file, $line)
}
$scope = $this->scopedErrors & $type;
- if (4 < $numArgs = \func_num_args()) {
- $context = func_get_arg(4) ?: [];
- $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM
+ if (false !== strpos($message, "@anonymous\0")) {
+ $logMessage = $this->levels[$type].': '.(new FlattenException())->setMessage($message)->getMessage();
} else {
- $context = [];
- $backtrace = null;
- }
-
- if (isset($context['GLOBALS']) && $scope) {
- $e = $context; // Whatever the signature of the method,
- unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
- $context = $e;
- }
-
- if (null !== $backtrace && $type & \E_ERROR) {
- // E_ERROR fatal errors are triggered on HHVM when
- // hhvm.error_handling.call_user_handler_on_fatals=1
- // which is the way to get their backtrace.
- $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace'));
-
- return true;
+ $logMessage = $this->levels[$type].': '.$message;
}
- $logMessage = $this->levels[$type].': '.$message;
-
if (null !== self::$toStringException) {
$errorAsException = self::$toStringException;
self::$toStringException = null;
} elseif (!$throw && !($type & $level)) {
if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) {
- $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : [];
- $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace);
+ $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : [];
+ $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace);
} elseif (isset(self::$silencedErrorCache[$id][$message])) {
$lightTrace = null;
$errorAsException = self::$silencedErrorCache[$id][$message];
@@ -452,19 +436,15 @@ public function handleError($type, $message, $file, $line)
return true;
}
} else {
- if ($scope) {
- $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context);
- } else {
- $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
- }
+ $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line);
- // Clean the trace by removing function arguments and the first frames added by the error handler itself.
if ($throw || $this->tracedErrors & $type) {
- $backtrace = $backtrace ?: $errorAsException->getTrace();
+ $backtrace = $errorAsException->getTrace();
$lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw);
$this->traceReflector->setValue($errorAsException, $lightTrace);
} else {
$this->traceReflector->setValue($errorAsException, []);
+ $backtrace = [];
}
}
@@ -478,32 +458,27 @@ public function handleError($type, $message, $file, $line)
&& ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function'])
) {
// Here, we know trigger_error() has been called from __toString().
- // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead.
+ // PHP triggers a fatal error when throwing from __toString().
// A small convention allows working around the limitation:
// given a caught $e exception in __toString(), quitting the method with
// `return trigger_error($e, E_USER_ERROR);` allows this error handler
// to make $e get through the __toString() barrier.
+ $context = 4 < \func_num_args() ? (func_get_arg(4) ?: []) : [];
+
foreach ($context as $e) {
- if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
- if (1 === $i) {
- // On HHVM
- $errorAsException = $e;
- break;
- }
+ if ($e instanceof \Throwable && $e->__toString() === $message) {
self::$toStringException = $e;
return true;
}
}
- if (1 < $i) {
- // On PHP (not on HHVM), display the original error message instead of the default one.
- $this->handleException($errorAsException);
+ // Display the original error message instead of the default one.
+ $this->handleException($errorAsException);
- // Stop the process by giving back the error to the native handler.
- return false;
- }
+ // Stop the process by giving back the error to the native handler.
+ return false;
}
}
}
@@ -513,16 +488,9 @@ public function handleError($type, $message, $file, $line)
if ($this->isRecursive) {
$log = 0;
- } elseif (self::$stackedErrorLevels) {
- self::$stackedErrors[] = [
- $this->loggers[$type][0],
- ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG,
- $logMessage,
- $errorAsException ? ['exception' => $errorAsException] : [],
- ];
} else {
- if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404) && !\defined('HHVM_VERSION')) {
- $currentErrorHandler = set_error_handler('var_dump');
+ if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) {
+ $currentErrorHandler = set_error_handler('is_int');
restore_error_handler();
}
@@ -533,7 +501,7 @@ public function handleError($type, $message, $file, $line)
} finally {
$this->isRecursive = false;
- if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404) && !\defined('HHVM_VERSION')) {
+ if (\PHP_VERSION_ID < (\PHP_VERSION_ID < 70400 ? 70316 : 70404)) {
set_error_handler($currentErrorHandler);
}
}
@@ -562,27 +530,29 @@ public function handleException($exception, array $error = null)
$handlerException = null;
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
+ if (false !== strpos($message = $exception->getMessage(), "@anonymous\0")) {
+ $message = (new FlattenException())->setMessage($message)->getMessage();
+ }
if ($exception instanceof FatalErrorException) {
if ($exception instanceof FatalThrowableError) {
$error = [
'type' => $type,
- 'message' => $message = $exception->getMessage(),
+ 'message' => $message,
'file' => $exception->getFile(),
'line' => $exception->getLine(),
];
} else {
- $message = 'Fatal '.$exception->getMessage();
+ $message = 'Fatal '.$message;
}
} elseif ($exception instanceof \ErrorException) {
- $message = 'Uncaught '.$exception->getMessage();
+ $message = 'Uncaught '.$message;
} else {
- $message = 'Uncaught Exception: '.$exception->getMessage();
+ $message = 'Uncaught Exception: '.$message;
}
}
if ($this->loggedErrors & $type) {
try {
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]);
- } catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) {
}
}
@@ -603,7 +573,6 @@ public function handleException($exception, array $error = null)
return;
}
$handlerException = $handlerException ?: $exception;
- } catch (\Exception $handlerException) {
} catch (\Throwable $handlerException) {
}
if ($exception === $handlerException) {
@@ -632,7 +601,7 @@ public static function handleFatalError(array $error = null)
$sameHandlerLimit = 10;
while (!\is_array($handler) || !$handler[0] instanceof self) {
- $handler = set_exception_handler('var_dump');
+ $handler = set_exception_handler('is_int');
restore_exception_handler();
if (!$handler) {
@@ -664,30 +633,22 @@ public static function handleFatalError(array $error = null)
$error = error_get_last();
}
- try {
- while (self::$stackedErrorLevels) {
- static::unstackErrors();
- }
- } catch (\Exception $exception) {
- // Handled below
- } catch (\Throwable $exception) {
- // Handled below
- }
-
if ($error && $error['type'] &= \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR) {
// Let's not throw anymore but keep logging
$handler->throwAt(0, true);
- $trace = isset($error['backtrace']) ? $error['backtrace'] : null;
+ $trace = $error['backtrace'] ?? null;
if (0 === strpos($error['message'], 'Allowed memory') || 0 === strpos($error['message'], 'Out of memory')) {
$exception = new OutOfMemoryException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, false, $trace);
} else {
$exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace);
}
+ } else {
+ $exception = null;
}
try {
- if (isset($exception)) {
+ if (null !== $exception) {
self::$exitCode = 255;
$handler->handleException($exception, $error);
}
@@ -701,55 +662,6 @@ public static function handleFatalError(array $error = null)
}
}
- /**
- * Configures the error handler for delayed handling.
- * Ensures also that non-catchable fatal errors are never silenced.
- *
- * As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724
- * PHP has a compile stage where it behaves unusually. To workaround it,
- * we plug an error handler that only stacks errors for later.
- *
- * The most important feature of this is to prevent
- * autoloading until unstackErrors() is called.
- *
- * @deprecated since version 3.4, to be removed in 4.0.
- */
- public static function stackErrors()
- {
- @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', \E_USER_DEPRECATED);
-
- self::$stackedErrorLevels[] = error_reporting(error_reporting() | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR);
- }
-
- /**
- * Unstacks stacked errors and forwards to the logger.
- *
- * @deprecated since version 3.4, to be removed in 4.0.
- */
- public static function unstackErrors()
- {
- @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', \E_USER_DEPRECATED);
-
- $level = array_pop(self::$stackedErrorLevels);
-
- if (null !== $level) {
- $errorReportingLevel = error_reporting($level);
- if ($errorReportingLevel !== ($level | \E_PARSE | \E_ERROR | \E_CORE_ERROR | \E_COMPILE_ERROR)) {
- // If the user changed the error level, do not overwrite it
- error_reporting($errorReportingLevel);
- }
- }
-
- if (empty(self::$stackedErrorLevels)) {
- $errors = self::$stackedErrors;
- self::$stackedErrors = [];
-
- foreach ($errors as $error) {
- $error[0]->log($error[1], $error[2], $error[3]);
- }
- }
- }
-
/**
* Gets the fatal error handlers.
*
@@ -766,7 +678,10 @@ protected function getFatalErrorHandlers()
];
}
- private function cleanTrace($backtrace, $type, $file, $line, $throw)
+ /**
+ * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader.
+ */
+ private function cleanTrace(array $backtrace, int $type, string $file, int $line, bool $throw): array
{
$lightTrace = $backtrace;
@@ -776,6 +691,13 @@ private function cleanTrace($backtrace, $type, $file, $line, $throw)
break;
}
}
+ if (class_exists(DebugClassLoader::class, false)) {
+ for ($i = \count($lightTrace) - 2; 0 < $i; --$i) {
+ if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) {
+ array_splice($lightTrace, --$i, 2);
+ }
+ }
+ }
if (!($throw || $this->scopedErrors & $type)) {
for ($i = 0; isset($lightTrace[$i]); ++$i) {
unset($lightTrace[$i]['args'], $lightTrace[$i]['object']);
diff --git a/vendor/symfony/debug/Exception/ClassNotFoundException.php b/vendor/symfony/debug/Exception/ClassNotFoundException.php
index de5c4564..998e4a98 100644
--- a/vendor/symfony/debug/Exception/ClassNotFoundException.php
+++ b/vendor/symfony/debug/Exception/ClassNotFoundException.php
@@ -11,14 +11,18 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ClassNotFoundException::class, \Symfony\Component\ErrorHandler\Error\ClassNotFoundError::class), \E_USER_DEPRECATED);
+
/**
* Class (or Trait or Interface) Not Found Exception.
*
* @author Konstanton Myakshin
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\ClassNotFoundError instead.
*/
class ClassNotFoundException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
diff --git a/vendor/symfony/debug/Exception/ContextErrorException.php b/vendor/symfony/debug/Exception/ContextErrorException.php
deleted file mode 100644
index 4b49f0af..00000000
--- a/vendor/symfony/debug/Exception/ContextErrorException.php
+++ /dev/null
@@ -1,40 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug\Exception;
-
-/**
- * Error Exception with Variable Context.
- *
- * @author Christian Sciberras
- *
- * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0.
- */
-class ContextErrorException extends \ErrorException
-{
- private $context = [];
-
- public function __construct($message, $code, $severity, $filename, $lineno, $context = [])
- {
- parent::__construct($message, $code, $severity, $filename, $lineno);
- $this->context = $context;
- }
-
- /**
- * @return array Array of variables that existed when the exception occurred
- */
- public function getContext()
- {
- @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), \E_USER_DEPRECATED);
-
- return $this->context;
- }
-}
diff --git a/vendor/symfony/debug/Exception/FatalErrorException.php b/vendor/symfony/debug/Exception/FatalErrorException.php
index 0f70ef92..fbdad4c5 100644
--- a/vendor/symfony/debug/Exception/FatalErrorException.php
+++ b/vendor/symfony/debug/Exception/FatalErrorException.php
@@ -11,14 +11,18 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', FatalErrorException::class, \Symfony\Component\ErrorHandler\Error\FatalError::class), \E_USER_DEPRECATED);
+
/**
* Fatal Error Exception.
*
* @author Konstanton Myakshin
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\FatalError instead.
*/
class FatalErrorException extends \ErrorException
{
- public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null, $previous = null)
+ public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null, \Throwable $previous = null)
{
parent::__construct($message, $code, $severity, $filename, $lineno, $previous);
@@ -31,8 +35,7 @@ public function __construct($message, $code, $severity, $filename, $lineno, $tra
$this->setTrace($trace);
} elseif (null !== $traceOffset) {
- if (\function_exists('xdebug_get_function_stack')) {
- $trace = xdebug_get_function_stack();
+ if (\function_exists('xdebug_get_function_stack') && $trace = @xdebug_get_function_stack()) {
if (0 < $traceOffset) {
array_splice($trace, -$traceOffset);
}
@@ -60,11 +63,6 @@ public function __construct($message, $code, $severity, $filename, $lineno, $tra
unset($frame);
$trace = array_reverse($trace);
- } elseif (\function_exists('symfony_debug_backtrace')) {
- $trace = symfony_debug_backtrace();
- if (0 < $traceOffset) {
- array_splice($trace, 0, $traceOffset);
- }
} else {
$trace = [];
}
@@ -75,7 +73,7 @@ public function __construct($message, $code, $severity, $filename, $lineno, $tra
protected function setTrace($trace)
{
- $traceReflector = new \ReflectionProperty('Exception', 'trace');
+ $traceReflector = new \ReflectionProperty(\Exception::class, 'trace');
$traceReflector->setAccessible(true);
$traceReflector->setValue($this, $trace);
}
diff --git a/vendor/symfony/debug/Exception/FatalThrowableError.php b/vendor/symfony/debug/Exception/FatalThrowableError.php
index a44f65f0..6c9ecb85 100644
--- a/vendor/symfony/debug/Exception/FatalThrowableError.php
+++ b/vendor/symfony/debug/Exception/FatalThrowableError.php
@@ -11,28 +11,33 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4.', FatalThrowableError::class), \E_USER_DEPRECATED);
+
/**
* Fatal Throwable Error.
*
* @author Nicolas Grekas
+ *
+ * @deprecated since Symfony 4.4
*/
class FatalThrowableError extends FatalErrorException
{
+ private $originalClassName;
+
public function __construct(\Throwable $e)
{
+ $this->originalClassName = \get_class($e);
+
if ($e instanceof \ParseError) {
- $message = 'Parse error: '.$e->getMessage();
$severity = \E_PARSE;
} elseif ($e instanceof \TypeError) {
- $message = 'Type error: '.$e->getMessage();
$severity = \E_RECOVERABLE_ERROR;
} else {
- $message = $e->getMessage();
$severity = \E_ERROR;
}
\ErrorException::__construct(
- $message,
+ $e->getMessage(),
$e->getCode(),
$severity,
$e->getFile(),
@@ -42,4 +47,9 @@ public function __construct(\Throwable $e)
$this->setTrace($e->getTrace());
}
+
+ public function getOriginalClassName(): string
+ {
+ return $this->originalClassName;
+ }
}
diff --git a/vendor/symfony/debug/Exception/FlattenException.php b/vendor/symfony/debug/Exception/FlattenException.php
index 9514bdc5..dbf0ed8f 100644
--- a/vendor/symfony/debug/Exception/FlattenException.php
+++ b/vendor/symfony/debug/Exception/FlattenException.php
@@ -15,11 +15,13 @@
use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
/**
- * FlattenException wraps a PHP Exception to be able to serialize it.
+ * FlattenException wraps a PHP Error or Exception to be able to serialize it.
*
* Basically, this class removes all objects from the trace.
*
* @author Fabien Potencier
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\FlattenException instead.
*/
class FlattenException
{
@@ -27,13 +29,25 @@ class FlattenException
private $code;
private $previous;
private $trace;
+ private $traceAsString;
private $class;
private $statusCode;
private $headers;
private $file;
private $line;
+ /**
+ * @return static
+ */
public static function create(\Exception $exception, $statusCode = null, array $headers = [])
+ {
+ return static::createFromThrowable($exception, $statusCode, $headers);
+ }
+
+ /**
+ * @return static
+ */
+ public static function createFromThrowable(\Throwable $exception, int $statusCode = null, array $headers = [])
{
$e = new static();
$e->setMessage($exception->getMessage());
@@ -52,17 +66,15 @@ public static function create(\Exception $exception, $statusCode = null, array $
$e->setStatusCode($statusCode);
$e->setHeaders($headers);
- $e->setTraceFromException($exception);
- $e->setClass(\get_class($exception));
+ $e->setTraceFromThrowable($exception);
+ $e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception));
$e->setFile($exception->getFile());
$e->setLine($exception->getLine());
$previous = $exception->getPrevious();
- if ($previous instanceof \Exception) {
- $e->setPrevious(static::create($previous));
- } elseif ($previous instanceof \Throwable) {
- $e->setPrevious(static::create(new FatalThrowableError($previous)));
+ if ($previous instanceof \Throwable) {
+ $e->setPrevious(static::createFromThrowable($previous));
}
return $e;
@@ -87,9 +99,14 @@ public function getStatusCode()
return $this->statusCode;
}
+ /**
+ * @return $this
+ */
public function setStatusCode($code)
{
$this->statusCode = $code;
+
+ return $this;
}
public function getHeaders()
@@ -97,9 +114,14 @@ public function getHeaders()
return $this->headers;
}
+ /**
+ * @return $this
+ */
public function setHeaders(array $headers)
{
$this->headers = $headers;
+
+ return $this;
}
public function getClass()
@@ -107,9 +129,14 @@ public function getClass()
return $this->class;
}
+ /**
+ * @return $this
+ */
public function setClass($class)
{
- $this->class = $class;
+ $this->class = false !== strpos($class, "@anonymous\0") ? (get_parent_class($class) ?: key(class_implements($class)) ?: 'class').'@anonymous' : $class;
+
+ return $this;
}
public function getFile()
@@ -117,9 +144,14 @@ public function getFile()
return $this->file;
}
+ /**
+ * @return $this
+ */
public function setFile($file)
{
$this->file = $file;
+
+ return $this;
}
public function getLine()
@@ -127,9 +159,14 @@ public function getLine()
return $this->line;
}
+ /**
+ * @return $this
+ */
public function setLine($line)
{
$this->line = $line;
+
+ return $this;
}
public function getMessage()
@@ -137,9 +174,20 @@ public function getMessage()
return $this->message;
}
+ /**
+ * @return $this
+ */
public function setMessage($message)
{
+ if (false !== strpos($message, "@anonymous\0")) {
+ $message = preg_replace_callback('/[a-zA-Z_\x7f-\xff][\\\\a-zA-Z0-9_\x7f-\xff]*+@anonymous\x00.*?\.php(?:0x?|:[0-9]++\$)[0-9a-fA-F]++/', function ($m) {
+ return class_exists($m[0], false) ? (get_parent_class($m[0]) ?: key(class_implements($m[0])) ?: 'class').'@anonymous' : $m[0];
+ }, $message);
+ }
+
$this->message = $message;
+
+ return $this;
}
public function getCode()
@@ -147,9 +195,14 @@ public function getCode()
return $this->code;
}
+ /**
+ * @return $this
+ */
public function setCode($code)
{
$this->code = $code;
+
+ return $this;
}
public function getPrevious()
@@ -157,9 +210,14 @@ public function getPrevious()
return $this->previous;
}
+ /**
+ * @return $this
+ */
public function setPrevious(self $previous)
{
$this->previous = $previous;
+
+ return $this;
}
public function getAllPrevious()
@@ -178,11 +236,26 @@ public function getTrace()
return $this->trace;
}
+ /**
+ * @deprecated since 4.1, use {@see setTraceFromThrowable()} instead.
+ */
public function setTraceFromException(\Exception $exception)
{
- $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine());
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.', __METHOD__), \E_USER_DEPRECATED);
+
+ $this->setTraceFromThrowable($exception);
+ }
+
+ public function setTraceFromThrowable(\Throwable $throwable)
+ {
+ $this->traceAsString = $throwable->getTraceAsString();
+
+ return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine());
}
+ /**
+ * @return $this
+ */
public function setTrace($trace, $file, $line)
{
$this->trace = [];
@@ -208,17 +281,19 @@ public function setTrace($trace, $file, $line)
$this->trace[] = [
'namespace' => $namespace,
'short_class' => $class,
- 'class' => isset($entry['class']) ? $entry['class'] : '',
- 'type' => isset($entry['type']) ? $entry['type'] : '',
- 'function' => isset($entry['function']) ? $entry['function'] : null,
- 'file' => isset($entry['file']) ? $entry['file'] : null,
- 'line' => isset($entry['line']) ? $entry['line'] : null,
+ 'class' => $entry['class'] ?? '',
+ 'type' => $entry['type'] ?? '',
+ 'function' => $entry['function'] ?? null,
+ 'file' => $entry['file'] ?? null,
+ 'line' => $entry['line'] ?? null,
'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [],
];
}
+
+ return $this;
}
- private function flattenArgs($args, $level = 0, &$count = 0)
+ private function flattenArgs(array $args, int $level = 0, int &$count = 0): array
{
$result = [];
foreach ($args as $key => $value) {
@@ -254,10 +329,39 @@ private function flattenArgs($args, $level = 0, &$count = 0)
return $result;
}
- private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value)
+ private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value): string
{
$array = new \ArrayObject($value);
return $array['__PHP_Incomplete_Class_Name'];
}
+
+ public function getTraceAsString()
+ {
+ return $this->traceAsString;
+ }
+
+ public function getAsString()
+ {
+ $message = '';
+ $next = false;
+
+ foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) {
+ if ($next) {
+ $message .= 'Next ';
+ } else {
+ $next = true;
+ }
+ $message .= $exception->getClass();
+
+ if ('' != $exception->getMessage()) {
+ $message .= ': '.$exception->getMessage();
+ }
+
+ $message .= ' in '.$exception->getFile().':'.$exception->getLine().
+ "\nStack trace:\n".$exception->getTraceAsString()."\n\n";
+ }
+
+ return rtrim($message);
+ }
}
diff --git a/vendor/symfony/debug/Exception/OutOfMemoryException.php b/vendor/symfony/debug/Exception/OutOfMemoryException.php
index fec19798..b1dc0ef4 100644
--- a/vendor/symfony/debug/Exception/OutOfMemoryException.php
+++ b/vendor/symfony/debug/Exception/OutOfMemoryException.php
@@ -11,10 +11,14 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', OutOfMemoryException::class, \Symfony\Component\ErrorHandler\Error\OutOfMemoryError::class), \E_USER_DEPRECATED);
+
/**
* Out of memory exception.
*
* @author Nicolas Grekas
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\OutOfMemoryError instead.
*/
class OutOfMemoryException extends FatalErrorException
{
diff --git a/vendor/symfony/debug/Exception/SilencedErrorContext.php b/vendor/symfony/debug/Exception/SilencedErrorContext.php
index 2bacfd5c..03e2fb30 100644
--- a/vendor/symfony/debug/Exception/SilencedErrorContext.php
+++ b/vendor/symfony/debug/Exception/SilencedErrorContext.php
@@ -11,10 +11,14 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', SilencedErrorContext::class, \Symfony\Component\ErrorHandler\Exception\SilencedErrorContext::class), \E_USER_DEPRECATED);
+
/**
* Data Object that represents a Silenced Error.
*
* @author Grégoire Pineau
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Exception\SilencedErrorContext instead.
*/
class SilencedErrorContext implements \JsonSerializable
{
@@ -25,7 +29,7 @@ class SilencedErrorContext implements \JsonSerializable
private $line;
private $trace;
- public function __construct($severity, $file, $line, array $trace = [], $count = 1)
+ public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1)
{
$this->severity = $severity;
$this->file = $file;
diff --git a/vendor/symfony/debug/Exception/UndefinedFunctionException.php b/vendor/symfony/debug/Exception/UndefinedFunctionException.php
index 8f5f454e..42ab2ec9 100644
--- a/vendor/symfony/debug/Exception/UndefinedFunctionException.php
+++ b/vendor/symfony/debug/Exception/UndefinedFunctionException.php
@@ -11,14 +11,18 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedFunctionException::class, \Symfony\Component\ErrorHandler\Error\UndefinedFunctionError::class), \E_USER_DEPRECATED);
+
/**
* Undefined Function Exception.
*
* @author Konstanton Myakshin
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\UndefinedFunctionError instead.
*/
class UndefinedFunctionException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
diff --git a/vendor/symfony/debug/Exception/UndefinedMethodException.php b/vendor/symfony/debug/Exception/UndefinedMethodException.php
index f7e340ba..d72046f3 100644
--- a/vendor/symfony/debug/Exception/UndefinedMethodException.php
+++ b/vendor/symfony/debug/Exception/UndefinedMethodException.php
@@ -11,14 +11,18 @@
namespace Symfony\Component\Debug\Exception;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', UndefinedMethodException::class, \Symfony\Component\ErrorHandler\Error\UndefinedMethodError::class), \E_USER_DEPRECATED);
+
/**
* Undefined Method Exception.
*
* @author Grégoire Pineau
+ *
+ * @deprecated since Symfony 4.4, use Symfony\Component\ErrorHandler\Error\UndefinedMethodError instead.
*/
class UndefinedMethodException extends FatalErrorException
{
- public function __construct($message, \ErrorException $previous)
+ public function __construct(string $message, \ErrorException $previous)
{
parent::__construct(
$message,
diff --git a/vendor/symfony/debug/ExceptionHandler.php b/vendor/symfony/debug/ExceptionHandler.php
index 7cf3f2a6..fd8a7fd5 100644
--- a/vendor/symfony/debug/ExceptionHandler.php
+++ b/vendor/symfony/debug/ExceptionHandler.php
@@ -15,6 +15,8 @@
use Symfony\Component\Debug\Exception\OutOfMemoryException;
use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4, use "%s" instead.', ExceptionHandler::class, \Symfony\Component\ErrorHandler\ErrorHandler::class), \E_USER_DEPRECATED);
+
/**
* ExceptionHandler converts an exception to a Response object.
*
@@ -26,9 +28,23 @@
*
* @author Fabien Potencier
* @author Nicolas Grekas
', $response);
-
- $handler = new ExceptionHandler(true);
-
- ob_start();
- $handler->sendPhpResponse(new \RuntimeException('Foo'));
- $response = ob_get_clean();
-
- $this->assertStringContainsString('Whoops, looks like something went wrong.', $response);
- $this->assertStringContainsString('
', $response);
- }
-
- public function testStatusCode()
- {
- $handler = new ExceptionHandler(false, 'iso8859-1');
-
- ob_start();
- $handler->sendPhpResponse(new NotFoundHttpException('Foo'));
- $response = ob_get_clean();
-
- $this->assertStringContainsString('Sorry, the page you are looking for could not be found.', $response);
-
- $expectedHeaders = [
- ['HTTP/1.0 404', true, null],
- ['Content-Type: text/html; charset=iso8859-1', true, null],
- ];
-
- $this->assertSame($expectedHeaders, testHeader());
- }
-
- public function testHeaders()
- {
- $handler = new ExceptionHandler(false, 'iso8859-1');
-
- ob_start();
- $handler->sendPhpResponse(new MethodNotAllowedHttpException(['POST']));
- ob_get_clean();
-
- $expectedHeaders = [
- ['HTTP/1.0 405', true, null],
- ['Allow: POST', false, null],
- ['Content-Type: text/html; charset=iso8859-1', true, null],
- ];
-
- $this->assertSame($expectedHeaders, testHeader());
- }
-
- public function testNestedExceptions()
- {
- $handler = new ExceptionHandler(true);
- ob_start();
- $handler->sendPhpResponse(new \RuntimeException('Foo', 0, new \RuntimeException('Bar')));
- $response = ob_get_clean();
-
- $this->assertStringMatchesFormat('%A
Foo
%A
Bar
%A', $response);
- }
-
- public function testHandle()
- {
- $handler = new ExceptionHandler(true);
- ob_start();
-
- $handler->handle(new \Exception('foo'));
-
- $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'foo');
- }
-
- public function testHandleWithACustomHandlerThatOutputsSomething()
- {
- $handler = new ExceptionHandler(true);
- ob_start();
- $handler->setHandler(function () {
- echo 'ccc';
- });
-
- $handler->handle(new \Exception());
- ob_end_flush(); // Necessary because of this PHP bug : https://bugs.php.net/76563
- $this->assertSame('ccc', ob_get_clean());
- }
-
- public function testHandleWithACustomHandlerThatOutputsNothing()
- {
- $handler = new ExceptionHandler(true);
- $handler->setHandler(function () {});
-
- $handler->handle(new \Exception('ccc'));
-
- $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc');
- }
-
- public function testHandleWithACustomHandlerThatFails()
- {
- $handler = new ExceptionHandler(true);
- $handler->setHandler(function () {
- throw new \RuntimeException();
- });
-
- $handler->handle(new \Exception('ccc'));
-
- $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc');
- }
-
- public function testHandleOutOfMemoryException()
- {
- $handler = new ExceptionHandler(true);
- ob_start();
- $handler->setHandler(function () {
- $this->fail('OutOfMemoryException should bypass the handler');
- });
-
- $handler->handle(new OutOfMemoryException('foo', 0, \E_ERROR, __FILE__, __LINE__));
-
- $this->assertThatTheExceptionWasOutput(ob_get_clean(), OutOfMemoryException::class, 'OutOfMemoryException', 'foo');
- }
-
- private function assertThatTheExceptionWasOutput($content, $expectedClass, $expectedTitle, $expectedMessage)
- {
- $this->assertStringContainsString(sprintf('%s', $expectedClass, $expectedTitle), $content);
- $this->assertStringContainsString(sprintf('
%s
', $expectedMessage), $content);
- }
-}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php
deleted file mode 100644
index 2b8a8678..00000000
--- a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php
+++ /dev/null
@@ -1,220 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
-
-use Composer\Autoload\ClassLoader as ComposerClassLoader;
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Debug\DebugClassLoader;
-use Symfony\Component\Debug\Exception\FatalErrorException;
-use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler;
-
-class ClassNotFoundFatalErrorHandlerTest extends TestCase
-{
- public static function setUpBeforeClass()
- {
- foreach (spl_autoload_functions() as $function) {
- if (!\is_array($function)) {
- continue;
- }
-
- // get class loaders wrapped by DebugClassLoader
- if ($function[0] instanceof DebugClassLoader) {
- $function = $function[0]->getClassLoader();
-
- if (!\is_array($function)) {
- continue;
- }
- }
-
- if ($function[0] instanceof ComposerClassLoader) {
- $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(\dirname(\dirname(\dirname(\dirname(__DIR__))))));
- break;
- }
- }
- }
-
- /**
- * @dataProvider provideClassNotFoundData
- */
- public function testHandleClassNotFound($error, $translatedMessage, $autoloader = null)
- {
- if ($autoloader) {
- // Unregister all autoloaders to ensure the custom provided
- // autoloader is the only one to be used during the test run.
- $autoloaders = spl_autoload_functions();
- array_map('spl_autoload_unregister', $autoloaders);
- spl_autoload_register($autoloader);
- }
-
- $handler = new ClassNotFoundFatalErrorHandler();
-
- $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
-
- if ($autoloader) {
- spl_autoload_unregister($autoloader);
- array_map('spl_autoload_register', $autoloaders);
- }
-
- $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
- $this->assertMatchesRegularExpression($translatedMessage, $exception->getMessage());
- $this->assertSame($error['type'], $exception->getSeverity());
- $this->assertSame($error['file'], $exception->getFile());
- $this->assertSame($error['line'], $exception->getLine());
- }
-
- public function provideClassNotFoundData()
- {
- $autoloader = new ComposerClassLoader();
- $autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception'));
- $autoloader->add('Symfony_Component_Debug_Tests_Fixtures', realpath(__DIR__.'/../../Tests/Fixtures'));
-
- $debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']);
-
- return [
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class "WhizBangFactory" not found',
- ],
- "/^Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'WhizBangFactory\' not found',
- ],
- "/^Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found',
- ],
- "/^Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class "Foo\\Bar\\WhizBangFactory" not found',
- ],
- "/^Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Interface "Foo\\Bar\\WhizBangInterface" not found',
- ],
- "/^Attempted to load interface \"WhizBangInterface\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Trait "Foo\\Bar\\WhizBangTrait" not found',
- ],
- "/^Attempted to load trait \"WhizBangTrait\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'UndefinedFunctionException\' not found',
- ],
- "/^Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
- [$debugClassLoader, 'loadClass'],
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'PEARClass\' not found',
- ],
- "/^Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"\?$/",
- [$debugClassLoader, 'loadClass'],
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
- ],
- "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
- [$debugClassLoader, 'loadClass'],
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
- ],
- "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/",
- [$autoloader, 'loadClass'],
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
- ],
- "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?/",
- [$debugClassLoader, 'loadClass'],
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found',
- ],
- "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/",
- function ($className) { /* do nothing here */ },
- ],
- ];
- }
-
- public function testCannotRedeclareClass()
- {
- if (!file_exists(__DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP')) {
- $this->markTestSkipped('Can only be run on case insensitive filesystems');
- }
-
- require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP';
-
- $error = [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found',
- ];
-
- $handler = new ClassNotFoundFatalErrorHandler();
- $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
-
- $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception);
- }
-}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php
deleted file mode 100644
index 2de44a25..00000000
--- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php
+++ /dev/null
@@ -1,81 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Debug\Exception\FatalErrorException;
-use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler;
-
-class UndefinedFunctionFatalErrorHandlerTest extends TestCase
-{
- /**
- * @dataProvider provideUndefinedFunctionData
- */
- public function testUndefinedFunction($error, $translatedMessage)
- {
- $handler = new UndefinedFunctionFatalErrorHandler();
- $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
-
- $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception);
- // class names are case insensitive and PHP/HHVM do not return the same
- $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage()));
- $this->assertSame($error['type'], $exception->getSeverity());
- $this->assertSame($error['file'], $exception->getFile());
- $this->assertSame($error['line'], $exception->getLine());
- }
-
- public function provideUndefinedFunctionData()
- {
- return [
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined function test_namespaced_function()',
- ],
- "Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()',
- ],
- "Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined function foo()',
- ],
- 'Attempted to call function "foo" from the global namespace.',
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()',
- ],
- 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".',
- ],
- ];
- }
-}
-
-function test_namespaced_function()
-{
-}
diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php
deleted file mode 100644
index 268a8413..00000000
--- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php
+++ /dev/null
@@ -1,76 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug\Tests\FatalErrorHandler;
-
-use PHPUnit\Framework\TestCase;
-use Symfony\Component\Debug\Exception\FatalErrorException;
-use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler;
-
-class UndefinedMethodFatalErrorHandlerTest extends TestCase
-{
- /**
- * @dataProvider provideUndefinedMethodData
- */
- public function testUndefinedMethod($error, $translatedMessage)
- {
- $handler = new UndefinedMethodFatalErrorHandler();
- $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line']));
-
- $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedMethodException', $exception);
- $this->assertSame($translatedMessage, $exception->getMessage());
- $this->assertSame($error['type'], $exception->getSeverity());
- $this->assertSame($error['file'], $exception->getFile());
- $this->assertSame($error['line'], $exception->getLine());
- }
-
- public function provideUndefinedMethodData()
- {
- return [
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined method SplObjectStorage::what()',
- ],
- 'Attempted to call an undefined method named "what" of class "SplObjectStorage".',
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined method SplObjectStorage::walid()',
- ],
- "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?",
- ],
- [
- [
- 'type' => 1,
- 'line' => 12,
- 'file' => 'foo.php',
- 'message' => 'Call to undefined method SplObjectStorage::offsetFet()',
- ],
- "Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?",
- ],
- [
- [
- 'type' => 1,
- 'message' => 'Call to undefined method class@anonymous::test()',
- 'file' => '/home/possum/work/symfony/test.php',
- 'line' => 11,
- ],
- 'Attempted to call an undefined method named "test" of class "class@anonymous".',
- ],
- ];
- }
-}
diff --git a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php
deleted file mode 100644
index dff9517d..00000000
--- a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php
+++ /dev/null
@@ -1,13 +0,0 @@
-exception = $e;
- }
-
- public function __toString()
- {
- try {
- throw $this->exception;
- } catch (\Exception $e) {
- // Using user_error() here is on purpose so we do not forget
- // that this alias also should work alongside with trigger_error().
- return trigger_error($e, E_USER_ERROR);
- }
- }
-}
diff --git a/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php b/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php
deleted file mode 100644
index 4c3dae37..00000000
--- a/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php
+++ /dev/null
@@ -1,13 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\Debug;
-
-function headers_sent()
-{
- return false;
-}
-
-function header($str, $replace = true, $status = null)
-{
- Tests\testHeader($str, $replace, $status);
-}
-
-namespace Symfony\Component\Debug\Tests;
-
-function testHeader()
-{
- static $headers = [];
-
- if (!$h = \func_get_args()) {
- $h = $headers;
- $headers = [];
-
- return $h;
- }
-
- $headers[] = \func_get_args();
-}
diff --git a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt b/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt
deleted file mode 100644
index 26b3abf4..00000000
--- a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt
+++ /dev/null
@@ -1,27 +0,0 @@
---TEST--
-Test DebugClassLoader with previously loaded parents
---FILE--
-
---EXPECTF--
-The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".
-The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod2()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".
diff --git a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt b/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt
deleted file mode 100644
index 9cd44388..00000000
--- a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt
+++ /dev/null
@@ -1,47 +0,0 @@
---TEST--
-Test catching fatal errors when handlers are nested
---INI--
-display_errors=0
---FILE--
-
---EXPECTF--
-object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) {
- ["message":protected]=>
- string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug".
-Did you forget a "use" statement for another namespace?"
- ["string":"Exception":private]=>
- string(0) ""
- ["code":protected]=>
- int(0)
- ["file":protected]=>
- string(%d) "%s"
- ["line":protected]=>
- int(%d)
- ["trace":"Exception":private]=>
- array(%d) {%A}
- ["previous":"Exception":private]=>
- NULL
- ["severity":protected]=>
- int(1)
-}
diff --git a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt
deleted file mode 100644
index b743d93a..00000000
--- a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt
+++ /dev/null
@@ -1,35 +0,0 @@
---TEST--
-Test rethrowing in custom exception handler
---FILE--
-setDefaultLogger(new TestLogger());
-ini_set('display_errors', 1);
-
-throw new \Exception('foo');
-?>
---EXPECTF--
-Uncaught Exception: foo
-123
-Fatal error: Uncaught %s:25
-Stack trace:
-%a
diff --git a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt
deleted file mode 100644
index b3f0e0eb..00000000
--- a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt
+++ /dev/null
@@ -1,42 +0,0 @@
---TEST--
-Test catching fatal errors when handlers are nested
---FILE--
-setExceptionHandler('print_r');
-
-if (true) {
- class Broken implements \Serializable
- {
- }
-}
-
-?>
---EXPECTF--
-array(1) {
- [0]=>
- string(37) "Error and exception handlers do match"
-}
-object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) {
- ["message":protected]=>
- string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)"
-%a
-}
diff --git a/vendor/symfony/debug/composer.json b/vendor/symfony/debug/composer.json
index 223d2bab..01e8f783 100644
--- a/vendor/symfony/debug/composer.json
+++ b/vendor/symfony/debug/composer.json
@@ -1,7 +1,7 @@
{
"name": "symfony/debug",
"type": "library",
- "description": "Symfony Debug Component",
+ "description": "Provides tools to ease debugging PHP code",
"keywords": [],
"homepage": "https://symfony.com",
"license": "MIT",
@@ -16,14 +16,14 @@
}
],
"require": {
- "php": "^5.5.9|>=7.0.8",
- "psr/log": "~1.0"
+ "php": ">=7.1.3",
+ "psr/log": "^1|^2|^3"
},
"conflict": {
- "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
+ "symfony/http-kernel": "<3.4"
},
"require-dev": {
- "symfony/http-kernel": "~2.8|~3.0|~4.0"
+ "symfony/http-kernel": "^3.4|^4.0|^5.0"
},
"autoload": {
"psr-4": { "Symfony\\Component\\Debug\\": "" },
diff --git a/vendor/symfony/debug/phpunit.xml.dist b/vendor/symfony/debug/phpunit.xml.dist
deleted file mode 100644
index a51bbff9..00000000
--- a/vendor/symfony/debug/phpunit.xml.dist
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
- ./Tests/
-
-
- ./Resources/ext/tests/
-
-
-
-
-
- ./
-
- ./Tests
- ./vendor
-
-
-
-
diff --git a/vendor/symfony/dependency-injection/Alias.php b/vendor/symfony/dependency-injection/Alias.php
index de14c5ea..248eeefa 100644
--- a/vendor/symfony/dependency-injection/Alias.php
+++ b/vendor/symfony/dependency-injection/Alias.php
@@ -11,21 +11,24 @@
namespace Symfony\Component\DependencyInjection;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+
class Alias
{
+ private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%alias_id%" service alias is deprecated. You should stop using it, as it will be removed in the future.';
+
private $id;
private $public;
private $private;
+ private $deprecated;
+ private $deprecationTemplate;
- /**
- * @param string $id Alias identifier
- * @param bool $public If this alias is public
- */
- public function __construct($id, $public = true)
+ public function __construct(string $id, bool $public = true)
{
- $this->id = (string) $id;
+ $this->id = $id;
$this->public = $public;
$this->private = 2 > \func_num_args();
+ $this->deprecated = false;
}
/**
@@ -82,6 +85,46 @@ public function isPrivate()
return $this->private;
}
+ /**
+ * Whether this alias is deprecated, that means it should not be referenced
+ * anymore.
+ *
+ * @param bool $status Whether this alias is deprecated, defaults to true
+ * @param string $template Optional template message to use if the alias is deprecated
+ *
+ * @return $this
+ *
+ * @throws InvalidArgumentException when the message template is invalid
+ */
+ public function setDeprecated($status = true, $template = null)
+ {
+ if (null !== $template) {
+ if (preg_match('#[\r\n]|\*/#', $template)) {
+ throw new InvalidArgumentException('Invalid characters found in deprecation template.');
+ }
+
+ if (!str_contains($template, '%alias_id%')) {
+ throw new InvalidArgumentException('The deprecation template must contain the "%alias_id%" placeholder.');
+ }
+
+ $this->deprecationTemplate = $template;
+ }
+
+ $this->deprecated = (bool) $status;
+
+ return $this;
+ }
+
+ public function isDeprecated(): bool
+ {
+ return $this->deprecated;
+ }
+
+ public function getDeprecationMessage(string $id): string
+ {
+ return str_replace('%alias_id%', $id, $this->deprecationTemplate ?: self::DEFAULT_DEPRECATION_TEMPLATE);
+ }
+
/**
* Returns the Id of this alias.
*
diff --git a/vendor/symfony/dependency-injection/Argument/BoundArgument.php b/vendor/symfony/dependency-injection/Argument/BoundArgument.php
index a2069844..c2afe2cf 100644
--- a/vendor/symfony/dependency-injection/Argument/BoundArgument.php
+++ b/vendor/symfony/dependency-injection/Argument/BoundArgument.php
@@ -16,24 +16,36 @@
*/
final class BoundArgument implements ArgumentInterface
{
+ public const SERVICE_BINDING = 0;
+ public const DEFAULTS_BINDING = 1;
+ public const INSTANCEOF_BINDING = 2;
+
private static $sequence = 0;
private $value;
private $identifier;
private $used;
+ private $type;
+ private $file;
- public function __construct($value)
+ public function __construct($value, bool $trackUsage = true, int $type = 0, string $file = null)
{
$this->value = $value;
- $this->identifier = ++self::$sequence;
+ if ($trackUsage) {
+ $this->identifier = ++self::$sequence;
+ } else {
+ $this->used = true;
+ }
+ $this->type = $type;
+ $this->file = $file;
}
/**
* {@inheritdoc}
*/
- public function getValues()
+ public function getValues(): array
{
- return [$this->value, $this->identifier, $this->used];
+ return [$this->value, $this->identifier, $this->used, $this->type, $this->file];
}
/**
@@ -41,6 +53,10 @@ public function getValues()
*/
public function setValues(array $values)
{
- list($this->value, $this->identifier, $this->used) = $values;
+ if (5 === \count($values)) {
+ [$this->value, $this->identifier, $this->used, $this->type, $this->file] = $values;
+ } else {
+ [$this->value, $this->identifier, $this->used] = $values;
+ }
}
}
diff --git a/vendor/symfony/dependency-injection/Argument/IteratorArgument.php b/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
index 2d796d2d..d413678a 100644
--- a/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
+++ b/vendor/symfony/dependency-injection/Argument/IteratorArgument.php
@@ -11,9 +11,6 @@
namespace Symfony\Component\DependencyInjection\Argument;
-use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
-use Symfony\Component\DependencyInjection\Reference;
-
/**
* Represents a collection of values to lazily iterate over.
*
@@ -21,35 +18,5 @@
*/
class IteratorArgument implements ArgumentInterface
{
- private $values;
-
- /**
- * @param Reference[] $values
- */
- public function __construct(array $values)
- {
- $this->setValues($values);
- }
-
- /**
- * @return array The values to lazily iterate over
- */
- public function getValues()
- {
- return $this->values;
- }
-
- /**
- * @param Reference[] $values The service references to lazily iterate over
- */
- public function setValues(array $values)
- {
- foreach ($values as $k => $v) {
- if (null !== $v && !$v instanceof Reference) {
- throw new InvalidArgumentException(sprintf('An IteratorArgument must hold only Reference instances, "%s" given.', \is_object($v) ? \get_class($v) : \gettype($v)));
- }
- }
-
- $this->values = $values;
- }
+ use ReferenceSetArgumentTrait;
}
diff --git a/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php b/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php
new file mode 100644
index 00000000..e3946ab3
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Argument/ReferenceSetArgumentTrait.php
@@ -0,0 +1,54 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Titouan Galopin
+ * @author Nicolas Grekas
+ */
+trait ReferenceSetArgumentTrait
+{
+ private $values;
+
+ /**
+ * @param Reference[] $values
+ */
+ public function __construct(array $values)
+ {
+ $this->setValues($values);
+ }
+
+ /**
+ * @return Reference[] The values in the set
+ */
+ public function getValues()
+ {
+ return $this->values;
+ }
+
+ /**
+ * @param Reference[] $values The service references to put in the set
+ */
+ public function setValues(array $values)
+ {
+ foreach ($values as $k => $v) {
+ if (null !== $v && !$v instanceof Reference) {
+ throw new InvalidArgumentException(sprintf('A "%s" must hold only Reference instances, "%s" given.', __CLASS__, \is_object($v) ? \get_class($v) : \gettype($v)));
+ }
+ }
+
+ $this->values = $values;
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php b/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
index b00a36c3..41fec786 100644
--- a/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
+++ b/vendor/symfony/dependency-injection/Argument/RewindableGenerator.php
@@ -28,14 +28,14 @@ public function __construct(callable $generator, $count)
$this->count = $count;
}
- public function getIterator()
+ public function getIterator(): \Traversable
{
$g = $this->generator;
return $g();
}
- public function count()
+ public function count(): int
{
if (\is_callable($count = $this->count)) {
$this->count = $count();
diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocator.php b/vendor/symfony/dependency-injection/Argument/ServiceLocator.php
new file mode 100644
index 00000000..4f3c19eb
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Argument/ServiceLocator.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+use Symfony\Component\DependencyInjection\ServiceLocator as BaseServiceLocator;
+
+/**
+ * @author Nicolas Grekas
+ *
+ * @internal
+ */
+class ServiceLocator extends BaseServiceLocator
+{
+ private $factory;
+ private $serviceMap;
+ private $serviceTypes;
+
+ public function __construct(\Closure $factory, array $serviceMap, array $serviceTypes = null)
+ {
+ $this->factory = $factory;
+ $this->serviceMap = $serviceMap;
+ $this->serviceTypes = $serviceTypes;
+ parent::__construct($serviceMap);
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @return mixed
+ */
+ public function get($id)
+ {
+ return isset($this->serviceMap[$id]) ? ($this->factory)(...$this->serviceMap[$id]) : parent::get($id);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getProvidedServices(): array
+ {
+ return $this->serviceTypes ?? $this->serviceTypes = array_map(function () { return '?'; }, $this->serviceMap);
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php b/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php
new file mode 100644
index 00000000..fcbf478c
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Argument/ServiceLocatorArgument.php
@@ -0,0 +1,44 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Argument;
+
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Represents a closure acting as a service locator.
+ *
+ * @author Nicolas Grekas
+ */
+class ServiceLocatorArgument implements ArgumentInterface
+{
+ use ReferenceSetArgumentTrait;
+
+ private $taggedIteratorArgument;
+
+ /**
+ * @param Reference[]|TaggedIteratorArgument $values
+ */
+ public function __construct($values = [])
+ {
+ if ($values instanceof TaggedIteratorArgument) {
+ $this->taggedIteratorArgument = $values;
+ $this->values = [];
+ } else {
+ $this->setValues($values);
+ }
+ }
+
+ public function getTaggedIteratorArgument(): ?TaggedIteratorArgument
+ {
+ return $this->taggedIteratorArgument;
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php b/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
index f00e5339..1ba8de79 100644
--- a/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
+++ b/vendor/symfony/dependency-injection/Argument/TaggedIteratorArgument.php
@@ -19,19 +19,55 @@
class TaggedIteratorArgument extends IteratorArgument
{
private $tag;
+ private $indexAttribute;
+ private $defaultIndexMethod;
+ private $defaultPriorityMethod;
+ private $needsIndexes = false;
/**
- * @param string $tag
+ * @param string $tag The name of the tag identifying the target services
+ * @param string|null $indexAttribute The name of the attribute that defines the key referencing each service in the tagged collection
+ * @param string|null $defaultIndexMethod The static method that should be called to get each service's key when their tag doesn't define the previous attribute
+ * @param bool $needsIndexes Whether indexes are required and should be generated when computing the map
+ * @param string|null $defaultPriorityMethod The static method that should be called to get each service's priority when their tag doesn't define the "priority" attribute
*/
- public function __construct($tag)
+ public function __construct(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, bool $needsIndexes = false, string $defaultPriorityMethod = null)
{
parent::__construct([]);
- $this->tag = (string) $tag;
+ if (null === $indexAttribute && $needsIndexes) {
+ $indexAttribute = preg_match('/[^.]++$/', $tag, $m) ? $m[0] : $tag;
+ }
+
+ $this->tag = $tag;
+ $this->indexAttribute = $indexAttribute;
+ $this->defaultIndexMethod = $defaultIndexMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Name' : null);
+ $this->needsIndexes = $needsIndexes;
+ $this->defaultPriorityMethod = $defaultPriorityMethod ?: ($indexAttribute ? 'getDefault'.str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $indexAttribute))).'Priority' : null);
}
public function getTag()
{
return $this->tag;
}
+
+ public function getIndexAttribute(): ?string
+ {
+ return $this->indexAttribute;
+ }
+
+ public function getDefaultIndexMethod(): ?string
+ {
+ return $this->defaultIndexMethod;
+ }
+
+ public function needsIndexes(): bool
+ {
+ return $this->needsIndexes;
+ }
+
+ public function getDefaultPriorityMethod(): ?string
+ {
+ return $this->defaultPriorityMethod;
+ }
}
diff --git a/vendor/symfony/dependency-injection/CHANGELOG.md b/vendor/symfony/dependency-injection/CHANGELOG.md
index a004161b..ee8583b2 100644
--- a/vendor/symfony/dependency-injection/CHANGELOG.md
+++ b/vendor/symfony/dependency-injection/CHANGELOG.md
@@ -1,6 +1,126 @@
CHANGELOG
=========
+4.4.0
+-----
+
+ * added `CheckTypeDeclarationsPass` to check injected parameters type during compilation
+ * added support for opcache.preload by generating a preloading script in the cache folder
+ * added support for dumping the container in one file instead of many files
+ * deprecated support for short factories and short configurators in Yaml
+ * added `tagged_iterator` alias for `tagged` which might be deprecated in a future version
+ * deprecated passing an instance of `Symfony\Component\DependencyInjection\Parameter` as class name to `Symfony\Component\DependencyInjection\Definition`
+ * added support for binding iterable and tagged services
+ * made singly-implemented interfaces detection be scoped by file
+ * added ability to define a static priority method for tagged service
+ * added support for improved syntax to define method calls in Yaml
+ * made the `%env(base64:...)%` processor able to decode base64url
+ * added ability to choose behavior of decorations on non existent decorated services
+
+4.3.0
+-----
+
+ * added `%env(trim:...)%` processor to trim a string value
+ * added `%env(default:param_name:...)%` processor to fallback to a parameter or to null when using `%env(default::...)%`
+ * added `%env(url:...)%` processor to convert an URL or DNS into an array of components
+ * added `%env(query_string:...)%` processor to convert a query string into an array of key values
+ * added support for deprecating aliases
+ * made `ContainerParametersResource` final and not implement `Serializable` anymore
+ * added `ReverseContainer`: a container that turns services back to their ids
+ * added ability to define an index for a tagged collection
+ * added ability to define an index for services in an injected service locator argument
+ * made `ServiceLocator` implement `ServiceProviderInterface`
+ * deprecated support for non-string default env() parameters
+ * added `%env(require:...)%` processor to `require()` a PHP file and use the value returned from it
+
+4.2.0
+-----
+
+ * added `ContainerBuilder::registerAliasForArgument()` to support autowiring by type+name
+ * added support for binding by type+name
+ * added `ServiceSubscriberTrait` to ease implementing `ServiceSubscriberInterface` using methods' return types
+ * added `ServiceLocatorArgument` and `!service_locator` config tag for creating optimized service-locators
+ * added support for autoconfiguring bindings
+ * added `%env(key:...)%` processor to fetch a specific key from an array
+ * deprecated `ServiceSubscriberInterface`, use the same interface from the `Symfony\Contracts\Service` namespace instead
+ * deprecated `ResettableContainerInterface`, use `Symfony\Contracts\Service\ResetInterface` instead
+
+4.1.0
+-----
+
+ * added support for variadics in named arguments
+ * added PSR-11 `ContainerBagInterface` and its `ContainerBag` implementation to access parameters as-a-service
+ * added support for service's decorators autowiring
+ * deprecated the `TypedReference::canBeAutoregistered()` and `TypedReference::getRequiringClass()` methods
+ * environment variables are validated when used in extension configuration
+ * deprecated support for auto-discovered extension configuration class which does not implement `ConfigurationInterface`
+
+4.0.0
+-----
+
+ * Relying on service auto-registration while autowiring is not supported anymore.
+ Explicitly inject your dependencies or create services whose ids are
+ their fully-qualified class name.
+
+ Before:
+
+ ```php
+ namespace App\Controller;
+
+ use App\Mailer;
+
+ class DefaultController
+ {
+ public function __construct(Mailer $mailer) {
+ // ...
+ }
+
+ // ...
+ }
+ ```
+ ```yml
+ services:
+ App\Controller\DefaultController:
+ autowire: true
+ ```
+
+ After:
+
+ ```php
+ // same PHP code
+ ```
+ ```yml
+ services:
+ App\Controller\DefaultController:
+ autowire: true
+
+ # or
+ # App\Controller\DefaultController:
+ # arguments: { $mailer: "@App\Mailer" }
+
+ App\Mailer:
+ autowire: true
+ ```
+ * removed autowiring services based on the types they implement
+ * added a third `$methodName` argument to the `getProxyFactoryCode()` method
+ of the `DumperInterface`
+ * removed support for autowiring types
+ * removed `Container::isFrozen`
+ * removed support for dumping an ucompiled container in `PhpDumper`
+ * removed support for generating a dumped `Container` without populating the method map
+ * removed support for case insensitive service identifiers
+ * removed the `DefinitionDecorator` class, replaced by `ChildDefinition`
+ * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method
+ * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead
+ * removed `FactoryReturnTypePass`
+ * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead.
+ * removed support for top-level anonymous services
+ * removed silent behavior for unused attributes and elements
+ * removed support for setting and accessing private services in `Container`
+ * removed support for setting pre-defined services in `Container`
+ * removed support for case insensitivity of parameter names
+ * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead
+
3.4.0
-----
@@ -16,7 +136,6 @@ CHANGELOG
* added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (``) support
* deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead
-
3.3.0
-----
@@ -85,8 +204,8 @@ CHANGELOG
2.5.0
-----
-* added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService())
-* deprecated SimpleXMLElement class.
+ * added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService())
+ * deprecated SimpleXMLElement class.
2.4.0
-----
diff --git a/vendor/symfony/dependency-injection/ChildDefinition.php b/vendor/symfony/dependency-injection/ChildDefinition.php
index 123b3874..5aefec64 100644
--- a/vendor/symfony/dependency-injection/ChildDefinition.php
+++ b/vendor/symfony/dependency-injection/ChildDefinition.php
@@ -27,7 +27,7 @@ class ChildDefinition extends Definition
/**
* @param string $parent The id of Definition instance to decorate
*/
- public function __construct($parent)
+ public function __construct(string $parent)
{
$this->parent = $parent;
$this->setPrivate(false);
@@ -97,7 +97,7 @@ public function replaceArgument($index, $value)
{
if (\is_int($index)) {
$this->arguments['index_'.$index] = $value;
- } elseif (0 === strpos($index, '$')) {
+ } elseif (str_starts_with($index, '$')) {
$this->arguments[$index] = $value;
} else {
throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.');
@@ -109,7 +109,7 @@ public function replaceArgument($index, $value)
/**
* @internal
*/
- public function setAutoconfigured($autoconfigured)
+ public function setAutoconfigured($autoconfigured): self
{
throw new BadMethodCallException('A ChildDefinition cannot be autoconfigured.');
}
@@ -117,10 +117,8 @@ public function setAutoconfigured($autoconfigured)
/**
* @internal
*/
- public function setInstanceofConditionals(array $instanceof)
+ public function setInstanceofConditionals(array $instanceof): self
{
throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.');
}
}
-
-class_alias(ChildDefinition::class, DefinitionDecorator::class);
diff --git a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
index 863bab47..4fb467d9 100644
--- a/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
+++ b/vendor/symfony/dependency-injection/Compiler/AbstractRecursivePass.php
@@ -12,10 +12,14 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\ChildDefinition;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\ExpressionLanguage\Expression;
/**
* @author Nicolas Grekas
@@ -28,6 +32,10 @@ abstract class AbstractRecursivePass implements CompilerPassInterface
protected $container;
protected $currentId;
+ private $processExpressions = false;
+ private $expressionLanguage;
+ private $inExpression = false;
+
/**
* {@inheritdoc}
*/
@@ -42,6 +50,21 @@ public function process(ContainerBuilder $container)
}
}
+ protected function enableExpressionProcessing()
+ {
+ $this->processExpressions = true;
+ }
+
+ protected function inExpression(bool $reset = true): bool
+ {
+ $inExpression = $this->inExpression;
+ if ($reset) {
+ $this->inExpression = false;
+ }
+
+ return $inExpression;
+ }
+
/**
* Processes a value found in a definition tree.
*
@@ -63,6 +86,8 @@ protected function processValue($value, $isRoot = false)
}
} elseif ($value instanceof ArgumentInterface) {
$value->setValues($this->processValue($value->getValues()));
+ } elseif ($value instanceof Expression && $this->processExpressions) {
+ $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']);
} elseif ($value instanceof Definition) {
$value->setArguments($this->processValue($value->getArguments()));
$value->setProperties($this->processValue($value->getProperties()));
@@ -106,23 +131,36 @@ protected function getConstructor(Definition $definition, $required)
}
if ($factory) {
- list($class, $method) = $factory;
+ [$class, $method] = $factory;
+
+ if ('__construct' === $method) {
+ throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
+ }
+
if ($class instanceof Reference) {
- $class = $this->container->findDefinition((string) $class)->getClass();
+ $factoryDefinition = $this->container->findDefinition((string) $class);
+ while ((null === $class = $factoryDefinition->getClass()) && $factoryDefinition instanceof ChildDefinition) {
+ $factoryDefinition = $this->container->findDefinition($factoryDefinition->getParent());
+ }
+ } elseif ($class instanceof Definition) {
+ $class = $class->getClass();
} elseif (null === $class) {
$class = $definition->getClass();
}
- if ('__construct' === $method) {
- throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId));
- }
return $this->getReflectionMethod(new Definition($class), $method);
}
- $class = $definition->getClass();
+ while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
+ $definition = $this->container->findDefinition($definition->getParent());
+ }
try {
if (!$r = $this->container->getReflectionClass($class)) {
+ if (null === $class) {
+ throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
+ }
+
throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class));
}
} catch (\ReflectionException $e) {
@@ -152,7 +190,11 @@ protected function getReflectionMethod(Definition $definition, $method)
return $this->getConstructor($definition, true);
}
- if (!$class = $definition->getClass()) {
+ while ((null === $class = $definition->getClass()) && $definition instanceof ChildDefinition) {
+ $definition = $this->container->findDefinition($definition->getParent());
+ }
+
+ if (null === $class) {
throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId));
}
@@ -161,6 +203,10 @@ protected function getReflectionMethod(Definition $definition, $method)
}
if (!$r->hasMethod($method)) {
+ if ($r->hasMethod('__call') && ($r = $r->getMethod('__call')) && $r->isPublic()) {
+ return new \ReflectionMethod(static function (...$arguments) {}, '__invoke');
+ }
+
throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method));
}
@@ -171,4 +217,31 @@ protected function getReflectionMethod(Definition $definition, $method)
return $r;
}
+
+ private function getExpressionLanguage(): ExpressionLanguage
+ {
+ if (null === $this->expressionLanguage) {
+ if (!class_exists(ExpressionLanguage::class)) {
+ throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
+ }
+
+ $providers = $this->container->getExpressionLanguageProviders();
+ $this->expressionLanguage = new ExpressionLanguage(null, $providers, function (string $arg): string {
+ if ('""' === substr_replace($arg, '', 1, -1)) {
+ $id = stripcslashes(substr($arg, 1, -1));
+ $this->inExpression = true;
+ $arg = $this->processValue(new Reference($id));
+ $this->inExpression = false;
+ if (!$arg instanceof Reference) {
+ throw new RuntimeException(sprintf('"%s::processValue()" must return a Reference when processing an expression, "%s" returned for service("%s").', static::class, \is_object($arg) ? \get_class($arg) : \gettype($arg), $id));
+ }
+ $arg = sprintf('"%s"', $arg);
+ }
+
+ return sprintf('$this->get(%s)', $arg);
+ });
+ }
+
+ return $this->expressionLanguage;
+ }
}
diff --git a/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
index bff9d420..92e4acac 100644
--- a/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php
@@ -12,13 +12,11 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Exception\RuntimeException;
-use Symfony\Component\DependencyInjection\ExpressionLanguage;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\ExpressionLanguage\Expression;
/**
* Run this pass before passes that need to know more about the relation of
@@ -28,6 +26,7 @@
* retrieve the graph in other passes from the compiler.
*
* @author Johannes M. Schmitt
+ * @author Nicolas Grekas
*/
class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
{
@@ -36,16 +35,19 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
private $onlyConstructorArguments;
private $hasProxyDumper;
private $lazy;
- private $expressionLanguage;
private $byConstructor;
+ private $byFactory;
+ private $definitions;
+ private $aliases;
/**
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
*/
- public function __construct($onlyConstructorArguments = false, $hasProxyDumper = true)
+ public function __construct(bool $onlyConstructorArguments = false, bool $hasProxyDumper = true)
{
- $this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
- $this->hasProxyDumper = (bool) $hasProxyDumper;
+ $this->onlyConstructorArguments = $onlyConstructorArguments;
+ $this->hasProxyDumper = $hasProxyDumper;
+ $this->enableExpressionProcessing();
}
/**
@@ -53,7 +55,7 @@ public function __construct($onlyConstructorArguments = false, $hasProxyDumper =
*/
public function setRepeatedPass(RepeatedPass $repeatedPass)
{
- // no-op for BC
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
}
/**
@@ -66,34 +68,37 @@ public function process(ContainerBuilder $container)
$this->graph->clear();
$this->lazy = false;
$this->byConstructor = false;
+ $this->byFactory = false;
+ $this->definitions = $container->getDefinitions();
+ $this->aliases = $container->getAliases();
- foreach ($container->getAliases() as $id => $alias) {
+ foreach ($this->aliases as $id => $alias) {
$targetId = $this->getDefinitionId((string) $alias);
- $this->graph->connect($id, $alias, $targetId, $this->getDefinition($targetId), null);
+ $this->graph->connect($id, $alias, $targetId, null !== $targetId ? $this->container->getDefinition($targetId) : null, null);
}
- parent::process($container);
+ try {
+ parent::process($container);
+ } finally {
+ $this->aliases = $this->definitions = [];
+ }
}
protected function processValue($value, $isRoot = false)
{
$lazy = $this->lazy;
+ $inExpression = $this->inExpression();
if ($value instanceof ArgumentInterface) {
- $this->lazy = true;
+ $this->lazy = !$this->byFactory || !$value instanceof IteratorArgument;
parent::processValue($value->getValues());
$this->lazy = $lazy;
return $value;
}
- if ($value instanceof Expression) {
- $this->getExpressionLanguage()->compile((string) $value, ['this' => 'container']);
-
- return $value;
- }
if ($value instanceof Reference) {
$targetId = $this->getDefinitionId((string) $value);
- $targetDefinition = $this->getDefinition($targetId);
+ $targetDefinition = null !== $targetId ? $this->container->getDefinition($targetId) : null;
$this->graph->connect(
$this->currentId,
@@ -106,6 +111,18 @@ protected function processValue($value, $isRoot = false)
$this->byConstructor
);
+ if ($inExpression) {
+ $this->graph->connect(
+ '.internal.reference_in_expression',
+ null,
+ $targetId,
+ $targetDefinition,
+ $value,
+ $this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
+ true
+ );
+ }
+
return $value;
}
if (!$value instanceof Definition) {
@@ -123,70 +140,60 @@ protected function processValue($value, $isRoot = false)
$byConstructor = $this->byConstructor;
$this->byConstructor = $isRoot || $byConstructor;
+
+ $byFactory = $this->byFactory;
+ $this->byFactory = true;
$this->processValue($value->getFactory());
+ $this->byFactory = $byFactory;
$this->processValue($value->getArguments());
- $this->byConstructor = $byConstructor;
- if (!$this->onlyConstructorArguments) {
- $this->processValue($value->getProperties());
- $this->processValue($value->getMethodCalls());
- $this->processValue($value->getConfigurator());
+ $properties = $value->getProperties();
+ $setters = $value->getMethodCalls();
+
+ // Any references before a "wither" are part of the constructor-instantiation graph
+ $lastWitherIndex = null;
+ foreach ($setters as $k => $call) {
+ if ($call[2] ?? false) {
+ $lastWitherIndex = $k;
+ }
}
- $this->lazy = $lazy;
- return $value;
- }
+ if (null !== $lastWitherIndex) {
+ $this->processValue($properties);
+ $setters = $properties = [];
- /**
- * Returns a service definition given the full name or an alias.
- *
- * @param string $id A full id or alias for a service definition
- *
- * @return Definition|null The definition related to the supplied id
- */
- private function getDefinition($id)
- {
- return null === $id ? null : $this->container->getDefinition($id);
- }
+ foreach ($value->getMethodCalls() as $k => $call) {
+ if (null === $lastWitherIndex) {
+ $setters[] = $call;
+ continue;
+ }
- private function getDefinitionId($id)
- {
- while ($this->container->hasAlias($id)) {
- $id = (string) $this->container->getAlias($id);
+ if ($lastWitherIndex === $k) {
+ $lastWitherIndex = null;
+ }
+
+ $this->processValue($call);
+ }
}
- if (!$this->container->hasDefinition($id)) {
- return null;
+ $this->byConstructor = $byConstructor;
+
+ if (!$this->onlyConstructorArguments) {
+ $this->processValue($properties);
+ $this->processValue($setters);
+ $this->processValue($value->getConfigurator());
}
+ $this->lazy = $lazy;
- return $this->container->normalizeId($id);
+ return $value;
}
- private function getExpressionLanguage()
+ private function getDefinitionId(string $id): ?string
{
- if (null === $this->expressionLanguage) {
- if (!class_exists(ExpressionLanguage::class)) {
- throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
- }
-
- $providers = $this->container->getExpressionLanguageProviders();
- $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
- if ('""' === substr_replace($arg, '', 1, -1)) {
- $id = stripcslashes(substr($arg, 1, -1));
- $id = $this->getDefinitionId($id);
-
- $this->graph->connect(
- $this->currentId,
- $this->currentDefinition,
- $id,
- $this->getDefinition($id)
- );
- }
-
- return sprintf('$this->get(%s)', $arg);
- });
+ while (isset($this->aliases[$id])) {
+ $id = (string) $this->aliases[$id];
}
- return $this->expressionLanguage;
+ return isset($this->definitions[$id]) ? $id : null;
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php b/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
deleted file mode 100644
index 6a755025..00000000
--- a/vendor/symfony/dependency-injection/Compiler/AutowireExceptionPass.php
+++ /dev/null
@@ -1,74 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Compiler;
-
-@trigger_error('The '.__NAMESPACE__.'\AutowireExceptionPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the DefinitionErrorExceptionPass class instead.', \E_USER_DEPRECATED);
-
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-
-/**
- * Throws autowire exceptions from AutowirePass for definitions that still exist.
- *
- * @deprecated since version 3.4, will be removed in 4.0.
- *
- * @author Ryan Weaver
- */
-class AutowireExceptionPass implements CompilerPassInterface
-{
- private $autowirePass;
- private $inlineServicePass;
-
- public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass)
- {
- $this->autowirePass = $autowirePass;
- $this->inlineServicePass = $inlineServicePass;
- }
-
- public function process(ContainerBuilder $container)
- {
- // the pass should only be run once
- if (null === $this->autowirePass || null === $this->inlineServicePass) {
- return;
- }
-
- $inlinedIds = $this->inlineServicePass->getInlinedServiceIds();
- $exceptions = $this->autowirePass->getAutowiringExceptions();
-
- // free up references
- $this->autowirePass = null;
- $this->inlineServicePass = null;
-
- foreach ($exceptions as $exception) {
- if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) {
- throw $exception;
- }
- }
- }
-
- private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds)
- {
- if ($container->hasDefinition($serviceId)) {
- return true;
- }
-
- // was the service inlined? Of so, does its parent service exist?
- if (isset($inlinedIds[$serviceId])) {
- foreach ($inlinedIds[$serviceId] as $parentId) {
- if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) {
- return true;
- }
- }
- }
-
- return false;
- }
-}
diff --git a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
index b1dae2a4..c88143d1 100644
--- a/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
+++ b/vendor/symfony/dependency-injection/Compiler/AutowirePass.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\Config\Resource\ClassExistenceResource;
-use Symfony\Component\DependencyInjection\Config\AutowireServiceResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
@@ -28,33 +27,26 @@
*/
class AutowirePass extends AbstractRecursivePass
{
- private $definedTypes = [];
private $types;
private $ambiguousServiceTypes;
- private $autowired = [];
private $lastFailure;
private $throwOnAutowiringException;
- private $autowiringExceptions = [];
- private $strictMode;
-
- /**
- * @param bool $throwOnAutowireException Errors can be retrieved via Definition::getErrors()
- */
- public function __construct($throwOnAutowireException = true)
+ private $decoratedClass;
+ private $decoratedId;
+ private $methodCalls;
+ private $defaultArgument;
+ private $getPreviousValue;
+ private $decoratedMethodIndex;
+ private $decoratedMethodArgumentIndex;
+ private $typesClone;
+
+ public function __construct(bool $throwOnAutowireException = true)
{
$this->throwOnAutowiringException = $throwOnAutowireException;
- }
-
- /**
- * @deprecated since version 3.4, to be removed in 4.0.
- *
- * @return AutowiringFailedException[]
- */
- public function getAutowiringExceptions()
- {
- @trigger_error('Calling AutowirePass::getAutowiringExceptions() is deprecated since Symfony 3.4 and will be removed in 4.0. Use Definition::getErrors() instead.', \E_USER_DEPRECATED);
-
- return $this->autowiringExceptions;
+ $this->defaultArgument = new class() {
+ public $value;
+ public $names;
+ };
}
/**
@@ -62,42 +54,21 @@ public function getAutowiringExceptions()
*/
public function process(ContainerBuilder $container)
{
- // clear out any possibly stored exceptions from before
- $this->autowiringExceptions = [];
- $this->strictMode = $container->hasParameter('container.autowiring.strict_mode') && $container->getParameter('container.autowiring.strict_mode');
-
try {
+ $this->typesClone = clone $this;
parent::process($container);
} finally {
- $this->definedTypes = [];
- $this->types = null;
- $this->ambiguousServiceTypes = null;
- $this->autowired = [];
+ $this->decoratedClass = null;
+ $this->decoratedId = null;
+ $this->methodCalls = null;
+ $this->defaultArgument->names = null;
+ $this->getPreviousValue = null;
+ $this->decoratedMethodIndex = null;
+ $this->decoratedMethodArgumentIndex = null;
+ $this->typesClone = null;
}
}
- /**
- * Creates a resource to help know if this service has changed.
- *
- * @return AutowireServiceResource
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.
- */
- public static function createResourceForClass(\ReflectionClass $reflectionClass)
- {
- @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', \E_USER_DEPRECATED);
-
- $metadata = [];
-
- foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) {
- if (!$reflectionMethod->isStatic()) {
- $metadata[$reflectionMethod->name] = self::getResourceMetadataForMethod($reflectionMethod);
- }
- }
-
- return new AutowireServiceResource($reflectionClass->name, $reflectionClass->getFileName(), $metadata);
- }
-
/**
* {@inheritdoc}
*/
@@ -110,20 +81,30 @@ protected function processValue($value, $isRoot = false)
throw $e;
}
- $this->autowiringExceptions[] = $e;
- $this->container->getDefinition($this->currentId)->addError($e->getMessage());
+ $this->container->getDefinition($this->currentId)->addError($e->getMessageCallback() ?? $e->getMessage());
return parent::processValue($value, $isRoot);
}
}
- private function doProcessValue($value, $isRoot = false)
+ /**
+ * @return mixed
+ */
+ private function doProcessValue($value, bool $isRoot = false)
{
if ($value instanceof TypedReference) {
- if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) {
+ if ($ref = $this->getAutowiredReference($value)) {
return $ref;
}
- $this->container->log($this, $this->createTypeNotFoundMessage($value, 'it'));
+ if (ContainerBuilder::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) {
+ $message = $this->createTypeNotFoundMessageCallback($value, 'it');
+
+ // since the error message varies by referenced id and $this->currentId, so should the id of the dummy errored definition
+ $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, (string) $value), $value->getType())
+ ->addError($message);
+
+ return new TypedReference($id, $value->getType(), $value->getInvalidBehavior(), $value->getName());
+ }
}
$value = parent::processValue($value, $isRoot);
@@ -136,7 +117,7 @@ private function doProcessValue($value, $isRoot = false)
return $value;
}
- $methodCalls = $value->getMethodCalls();
+ $this->methodCalls = $value->getMethodCalls();
try {
$constructor = $this->getConstructor($value, false);
@@ -145,33 +126,40 @@ private function doProcessValue($value, $isRoot = false)
}
if ($constructor) {
- array_unshift($methodCalls, [$constructor, $value->getArguments()]);
+ array_unshift($this->methodCalls, [$constructor, $value->getArguments()]);
}
- $methodCalls = $this->autowireCalls($reflectionClass, $methodCalls);
+ $this->methodCalls = $this->autowireCalls($reflectionClass, $isRoot);
if ($constructor) {
- list(, $arguments) = array_shift($methodCalls);
+ [, $arguments] = array_shift($this->methodCalls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
}
}
- if ($methodCalls !== $value->getMethodCalls()) {
- $value->setMethodCalls($methodCalls);
+ if ($this->methodCalls !== $value->getMethodCalls()) {
+ $value->setMethodCalls($this->methodCalls);
}
return $value;
}
- /**
- * @return array
- */
- private function autowireCalls(\ReflectionClass $reflectionClass, array $methodCalls)
+ private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array
{
- foreach ($methodCalls as $i => $call) {
- list($method, $arguments) = $call;
+ $this->decoratedId = null;
+ $this->decoratedClass = null;
+ $this->getPreviousValue = null;
+
+ if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && null !== ($this->decoratedId = $definition->innerServiceId) && $this->container->has($this->decoratedId)) {
+ $this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass();
+ }
+
+ $patchedIndexes = [];
+
+ foreach ($this->methodCalls as $i => $call) {
+ [$method, $arguments] = $call;
if ($method instanceof \ReflectionFunctionAbstract) {
$reflectionMethod = $method;
@@ -187,14 +175,40 @@ private function autowireCalls(\ReflectionClass $reflectionClass, array $methodC
}
}
- $arguments = $this->autowireMethod($reflectionMethod, $arguments);
+ $arguments = $this->autowireMethod($reflectionMethod, $arguments, $i);
if ($arguments !== $call[1]) {
- $methodCalls[$i][1] = $arguments;
+ $this->methodCalls[$i][1] = $arguments;
+ $patchedIndexes[] = $i;
+ }
+ }
+
+ // use named arguments to skip complex default values
+ foreach ($patchedIndexes as $i) {
+ $namedArguments = null;
+ $arguments = $this->methodCalls[$i][1];
+
+ foreach ($arguments as $j => $value) {
+ if ($namedArguments && !$value instanceof $this->defaultArgument) {
+ unset($arguments[$j]);
+ $arguments[$namedArguments[$j]] = $value;
+ }
+ if ($namedArguments || !$value instanceof $this->defaultArgument) {
+ continue;
+ }
+
+ if (\PHP_VERSION_ID >= 80100 && (\is_array($value->value) ? $value->value : \is_object($value->value))) {
+ unset($arguments[$j]);
+ $namedArguments = $value->names;
+ } else {
+ $arguments[$j] = $value->value;
+ }
}
+
+ $this->methodCalls[$i][1] = $arguments;
}
- return $methodCalls;
+ return $this->methodCalls;
}
/**
@@ -204,16 +218,19 @@ private function autowireCalls(\ReflectionClass $reflectionClass, array $methodC
*
* @throws AutowiringFailedException
*/
- private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments)
+ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments, int $methodIndex): array
{
$class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId;
$method = $reflectionMethod->name;
$parameters = $reflectionMethod->getParameters();
- if (method_exists('ReflectionMethod', 'isVariadic') && $reflectionMethod->isVariadic()) {
+ if ($reflectionMethod->isVariadic()) {
array_pop($parameters);
}
+ $this->defaultArgument->names = new \ArrayObject();
foreach ($parameters as $index => $parameter) {
+ $this->defaultArgument->names[$index] = $parameter->name;
+
if (\array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
continue;
}
@@ -231,38 +248,62 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
// be false when isOptional() returns true. If the
// argument *is* optional, allow it to be missing
if ($parameter->isOptional()) {
- continue;
+ --$index;
+ break;
}
$type = ProxyHelper::getTypeHint($reflectionMethod, $parameter, false);
- $type = $type ? sprintf('is type-hinted "%s"', $type) : 'has no type-hint';
+ $type = $type ? sprintf('is type-hinted "%s"', ltrim($type, '\\')) : 'has no type-hint';
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" %s, you should configure its value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method, $type));
}
// specifically pass the default value
- $arguments[$index] = $parameter->getDefaultValue();
+ $arguments[$index] = clone $this->defaultArgument;
+ $arguments[$index]->value = $parameter->getDefaultValue();
continue;
}
- if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''), 'for '.sprintf('argument "$%s" of method "%s()"', $parameter->name, $class.'::'.$method))) {
- $failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
+ $getValue = function () use ($type, $parameter, $class, $method) {
+ if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $parameter->name))) {
+ $failureMessage = $this->createTypeNotFoundMessageCallback($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
+
+ if ($parameter->isDefaultValueAvailable()) {
+ $value = clone $this->defaultArgument;
+ $value->value = $parameter->getDefaultValue();
+ } elseif (!$parameter->allowsNull()) {
+ throw new AutowiringFailedException($this->currentId, $failureMessage);
+ }
+ }
+
+ return $value;
+ };
+
+ if ($this->decoratedClass && $isDecorated = is_a($this->decoratedClass, $type, true)) {
+ if ($this->getPreviousValue) {
+ // The inner service is injected only if there is only 1 argument matching the type of the decorated class
+ // across all arguments of all autowired methods.
+ // If a second matching argument is found, the default behavior is restored.
+
+ $getPreviousValue = $this->getPreviousValue;
+ $this->methodCalls[$this->decoratedMethodIndex][1][$this->decoratedMethodArgumentIndex] = $getPreviousValue();
+ $this->decoratedClass = null; // Prevent further checks
+ } else {
+ $arguments[$index] = new TypedReference($this->decoratedId, $this->decoratedClass);
+ $this->getPreviousValue = $getValue;
+ $this->decoratedMethodIndex = $methodIndex;
+ $this->decoratedMethodArgumentIndex = $index;
- if ($parameter->isDefaultValueAvailable()) {
- $value = $parameter->getDefaultValue();
- } elseif (!$parameter->allowsNull()) {
- throw new AutowiringFailedException($this->currentId, $failureMessage);
+ continue;
}
- $this->container->log($this, $failureMessage);
}
- $arguments[$index] = $value;
+ $arguments[$index] = $getValue();
}
if ($parameters && !isset($arguments[++$index])) {
while (0 <= --$index) {
- $parameter = $parameters[$index];
- if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
+ if (!$arguments[$index] instanceof $this->defaultArgument) {
break;
}
unset($arguments[$index]);
@@ -277,48 +318,33 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
}
/**
- * @return TypedReference|null A reference to the service matching the given type, if any
+ * Returns a reference to the service matching the given type, if any.
*/
- private function getAutowiredReference(TypedReference $reference, $deprecationMessage)
+ private function getAutowiredReference(TypedReference $reference): ?TypedReference
{
$this->lastFailure = null;
$type = $reference->getType();
- if ($type !== $this->container->normalizeId($reference) || ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract())) {
+ if ($type !== (string) $reference) {
return $reference;
}
- if (null === $this->types) {
- $this->populateAvailableTypes($this->strictMode);
- }
-
- if (isset($this->definedTypes[$type])) {
- return new TypedReference($this->types[$type], $type);
- }
-
- if (!$this->strictMode && isset($this->types[$type])) {
- $message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.';
- if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) {
- $message .= ' '.$aliasSuggestion;
- } else {
- $message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type);
+ if (null !== $name = $reference->getName()) {
+ if ($this->container->has($alias = $type.' $'.$name) && !$this->container->findDefinition($alias)->isAbstract()) {
+ return new TypedReference($alias, $type, $reference->getInvalidBehavior());
}
- @trigger_error($message, \E_USER_DEPRECATED);
-
- return new TypedReference($this->types[$type], $type);
- }
-
- if (!$reference->canBeAutoregistered() || isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) {
- return null;
- }
-
- if (isset($this->autowired[$type])) {
- return $this->autowired[$type] ? new TypedReference($this->autowired[$type], $type) : null;
+ if ($this->container->has($name) && !$this->container->findDefinition($name)->isAbstract()) {
+ foreach ($this->container->getAliases() as $id => $alias) {
+ if ($name === (string) $alias && str_starts_with($id, $type.' $')) {
+ return new TypedReference($name, $type, $reference->getInvalidBehavior());
+ }
+ }
+ }
}
- if (!$this->strictMode) {
- return $this->createAutowiredDefinition($type);
+ if ($this->container->has($type) && !$this->container->findDefinition($type)->isAbstract()) {
+ return new TypedReference($type, $type, $reference->getInvalidBehavior());
}
return null;
@@ -327,41 +353,27 @@ private function getAutowiredReference(TypedReference $reference, $deprecationMe
/**
* Populates the list of available types.
*/
- private function populateAvailableTypes($onlyAutowiringTypes = false)
+ private function populateAvailableTypes(ContainerBuilder $container)
{
$this->types = [];
- if (!$onlyAutowiringTypes) {
- $this->ambiguousServiceTypes = [];
- }
+ $this->ambiguousServiceTypes = [];
- foreach ($this->container->getDefinitions() as $id => $definition) {
- $this->populateAvailableType($id, $definition, $onlyAutowiringTypes);
+ foreach ($container->getDefinitions() as $id => $definition) {
+ $this->populateAvailableType($container, $id, $definition);
}
}
/**
* Populates the list of available types for a given definition.
- *
- * @param string $id
*/
- private function populateAvailableType($id, Definition $definition, $onlyAutowiringTypes)
+ private function populateAvailableType(ContainerBuilder $container, string $id, Definition $definition)
{
// Never use abstract services
if ($definition->isAbstract()) {
return;
}
- foreach ($definition->getAutowiringTypes(false) as $type) {
- $this->definedTypes[$type] = true;
- $this->types[$type] = $id;
- unset($this->ambiguousServiceTypes[$type]);
- }
-
- if ($onlyAutowiringTypes) {
- return;
- }
-
- if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id) || $definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) {
+ if ('' === $id || '.' === $id[0] || $definition->isDeprecated() || !$reflectionClass = $container->getReflectionClass($definition->getClass(), false)) {
return;
}
@@ -376,16 +388,9 @@ private function populateAvailableType($id, Definition $definition, $onlyAutowir
/**
* Associates a type and a service id if applicable.
- *
- * @param string $type
- * @param string $id
*/
- private function set($type, $id)
+ private function set(string $type, string $id)
{
- if (isset($this->definedTypes[$type])) {
- return;
- }
-
// is this already a type/class that is known to match multiple services?
if (isset($this->ambiguousServiceTypes[$type])) {
$this->ambiguousServiceTypes[$type][] = $id;
@@ -408,62 +413,24 @@ private function set($type, $id)
$this->ambiguousServiceTypes[$type][] = $id;
}
- /**
- * Registers a definition for the type if possible or throws an exception.
- *
- * @param string $type
- *
- * @return TypedReference|null A reference to the registered definition
- */
- private function createAutowiredDefinition($type)
+ private function createTypeNotFoundMessageCallback(TypedReference $reference, string $label): \Closure
{
- if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) {
- return null;
+ if (null === $this->typesClone->container) {
+ $this->typesClone->container = new ContainerBuilder($this->container->getParameterBag());
+ $this->typesClone->container->setAliases($this->container->getAliases());
+ $this->typesClone->container->setDefinitions($this->container->getDefinitions());
+ $this->typesClone->container->setResourceTracking(false);
}
-
$currentId = $this->currentId;
- $this->currentId = $type;
- $this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type);
- $argumentDefinition = new Definition($type);
- $argumentDefinition->setPublic(false);
- $argumentDefinition->setAutowired(true);
- try {
- $originalThrowSetting = $this->throwOnAutowiringException;
- $this->throwOnAutowiringException = true;
- $this->processValue($argumentDefinition, true);
- $this->container->setDefinition($argumentId, $argumentDefinition);
- } catch (AutowiringFailedException $e) {
- $this->autowired[$type] = false;
- $this->lastFailure = $e->getMessage();
- $this->container->log($this, $this->lastFailure);
-
- return null;
- } finally {
- $this->throwOnAutowiringException = $originalThrowSetting;
- $this->currentId = $currentId;
- }
-
- @trigger_error(sprintf('Relying on service auto-registration for type "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), \E_USER_DEPRECATED);
-
- $this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId));
-
- return new TypedReference($argumentId, $type);
+ return (function () use ($reference, $label, $currentId) {
+ return $this->createTypeNotFoundMessage($reference, $label, $currentId);
+ })->bindTo($this->typesClone);
}
- private function createTypeNotFoundMessage(TypedReference $reference, $label)
+ private function createTypeNotFoundMessage(TypedReference $reference, string $label, string $currentId): string
{
- $trackResources = $this->container->isTrackingResources();
- $this->container->setResourceTracking(false);
- try {
- if ($r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
- $alternatives = $this->createTypeAlternatives($reference);
- }
- } finally {
- $this->container->setResourceTracking($trackResources);
- }
-
- if (!$r) {
+ if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) {
// either $type does not exist or a parent class does not exist
try {
$resource = new ClassExistenceResource($type, false);
@@ -476,6 +443,7 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label)
$message = sprintf('has type "%s" but this class %s.', $type, $parentMsg ? sprintf('is missing a parent class (%s)', $parentMsg) : 'was not found');
} else {
+ $alternatives = $this->createTypeAlternatives($this->container, $reference);
$message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists';
$message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $alternatives);
@@ -484,7 +452,7 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label)
}
}
- $message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
+ $message = sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message);
if (null !== $this->lastFailure) {
$message = $this->lastFailure."\n".$message;
@@ -494,22 +462,23 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label)
return $message;
}
- private function createTypeAlternatives(TypedReference $reference)
+ private function createTypeAlternatives(ContainerBuilder $container, TypedReference $reference): string
{
// try suggesting available aliases first
- if ($message = $this->getAliasesSuggestionForType($type = $reference->getType())) {
+ if ($message = $this->getAliasesSuggestionForType($container, $type = $reference->getType())) {
return ' '.$message;
}
if (null === $this->ambiguousServiceTypes) {
- $this->populateAvailableTypes();
+ $this->populateAvailableTypes($container);
}
- if (isset($this->ambiguousServiceTypes[$type])) {
+ $servicesAndAliases = $container->getServiceIds();
+ if (!$container->has($type) && false !== $key = array_search(strtolower($type), array_map('strtolower', $servicesAndAliases))) {
+ return sprintf(' Did you mean "%s"?', $servicesAndAliases[$key]);
+ } elseif (isset($this->ambiguousServiceTypes[$type])) {
$message = sprintf('one of these existing services: "%s"', implode('", "', $this->ambiguousServiceTypes[$type]));
} elseif (isset($this->types[$type])) {
$message = sprintf('the existing "%s" service', $this->types[$type]);
- } elseif ($reference->getRequiringClass() && !$reference->canBeAutoregistered() && !$this->strictMode) {
- return ' It cannot be auto-registered because it is from a different root namespace.';
} else {
return '';
}
@@ -517,52 +486,17 @@ private function createTypeAlternatives(TypedReference $reference)
return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message);
}
- /**
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- private static function getResourceMetadataForMethod(\ReflectionMethod $method)
- {
- $methodArgumentsMetadata = [];
- foreach ($method->getParameters() as $parameter) {
- try {
- if (method_exists($parameter, 'getType')) {
- $type = $parameter->getType();
- if ($type && !$type->isBuiltin()) {
- $class = new \ReflectionClass($type instanceof \ReflectionNamedType ? $type->getName() : (string) $type);
- } else {
- $class = null;
- }
- } else {
- $class = $parameter->getClass();
- }
- } catch (\ReflectionException $e) {
- // type-hint is against a non-existent class
- $class = false;
- }
-
- $isVariadic = method_exists($parameter, 'isVariadic') && $parameter->isVariadic();
- $methodArgumentsMetadata[] = [
- 'class' => $class,
- 'isOptional' => $parameter->isOptional(),
- 'defaultValue' => ($parameter->isOptional() && !$isVariadic) ? $parameter->getDefaultValue() : null,
- ];
- }
-
- return $methodArgumentsMetadata;
- }
-
- private function getAliasesSuggestionForType($type, $extraContext = null)
+ private function getAliasesSuggestionForType(ContainerBuilder $container, string $type): ?string
{
$aliases = [];
foreach (class_parents($type) + class_implements($type) as $parent) {
- if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) {
+ if ($container->has($parent) && !$container->findDefinition($parent)->isAbstract()) {
$aliases[] = $parent;
}
}
- $extraContext = $extraContext ? ' '.$extraContext : '';
if (1 < $len = \count($aliases)) {
- $message = sprintf('Try changing the type-hint%s to one of its parents: ', $extraContext);
+ $message = 'Try changing the type-hint to one of its parents: ';
for ($i = 0, --$len; $i < $len; ++$i) {
$message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]);
}
@@ -572,7 +506,7 @@ private function getAliasesSuggestionForType($type, $extraContext = null)
}
if ($aliases) {
- return sprintf('Try changing the type-hint%s to "%s" instead.', $extraContext, $aliases[0]);
+ return sprintf('Try changing the type-hint to "%s" instead.', $aliases[0]);
}
return null;
diff --git a/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php b/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
index efb9df7b..4e80bb4f 100644
--- a/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/AutowireRequiredMethodsPass.php
@@ -35,8 +35,9 @@ protected function processValue($value, $isRoot = false)
}
$alreadyCalledMethods = [];
+ $withers = [];
- foreach ($value->getMethodCalls() as list($method)) {
+ foreach ($value->getMethodCalls() as [$method]) {
$alreadyCalledMethods[strtolower($method)] = true;
}
@@ -50,7 +51,11 @@ protected function processValue($value, $isRoot = false)
while (true) {
if (false !== $doc = $r->getDocComment()) {
if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) {
- $value->addMethodCall($reflectionMethod->name);
+ if (preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@return\s++static[\s\*]#i', $doc)) {
+ $withers[] = [$reflectionMethod->name, [], true];
+ } else {
+ $value->addMethodCall($reflectionMethod->name, []);
+ }
break;
}
if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) {
@@ -65,6 +70,15 @@ protected function processValue($value, $isRoot = false)
}
}
+ if ($withers) {
+ // Prepend withers to prevent creating circular loops
+ $setters = $value->getMethodCalls();
+ $value->setMethodCalls($withers);
+ foreach ($setters as $call) {
+ $value->addMethodCall($call[0], $call[1], $call[2] ?? false);
+ }
+ }
+
return $value;
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
index 30a6f524..557e6af6 100644
--- a/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/CheckArgumentsValidityPass.php
@@ -24,7 +24,7 @@ class CheckArgumentsValidityPass extends AbstractRecursivePass
{
private $throwExceptions;
- public function __construct($throwExceptions = true)
+ public function __construct(bool $throwExceptions = true)
{
$this->throwExceptions = $throwExceptions;
}
@@ -39,7 +39,13 @@ protected function processValue($value, $isRoot = false)
}
$i = 0;
+ $hasNamedArgs = false;
foreach ($value->getArguments() as $k => $v) {
+ if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
+ $hasNamedArgs = true;
+ continue;
+ }
+
if ($k !== $i++) {
if (!\is_int($k)) {
$msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k);
@@ -57,11 +63,27 @@ protected function processValue($value, $isRoot = false)
throw new RuntimeException($msg);
}
}
+
+ if ($hasNamedArgs) {
+ $msg = sprintf('Invalid constructor argument for service "%s": cannot use positional argument after named argument. Check your service definition.', $this->currentId);
+ $value->addError($msg);
+ if ($this->throwExceptions) {
+ throw new RuntimeException($msg);
+ }
+
+ break;
+ }
}
foreach ($value->getMethodCalls() as $methodCall) {
$i = 0;
+ $hasNamedArgs = false;
foreach ($methodCall[1] as $k => $v) {
+ if (\PHP_VERSION_ID >= 80000 && preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $k)) {
+ $hasNamedArgs = true;
+ continue;
+ }
+
if ($k !== $i++) {
if (!\is_int($k)) {
$msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k);
@@ -79,6 +101,16 @@ protected function processValue($value, $isRoot = false)
throw new RuntimeException($msg);
}
}
+
+ if ($hasNamedArgs) {
+ $msg = sprintf('Invalid argument for method call "%s" of service "%s": cannot use positional argument after named argument. Check your service definition.', $methodCall[0], $this->currentId);
+ $value->addError($msg);
+ if ($this->throwExceptions) {
+ throw new RuntimeException($msg);
+ }
+
+ break;
+ }
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php b/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
index 4b6d277f..7abac908 100644
--- a/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/CheckDefinitionValidityPass.php
@@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\EnvParameterException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Loader\FileLoader;
/**
* This pass validates each definition individually only taking the information
@@ -38,17 +39,17 @@ public function process(ContainerBuilder $container)
{
foreach ($container->getDefinitions() as $id => $definition) {
// synthetic service is public
- if ($definition->isSynthetic() && !($definition->isPublic() || $definition->isPrivate())) {
+ if ($definition->isSynthetic() && !$definition->isPublic()) {
throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id));
}
// non-synthetic, non-abstract service has class
- if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass()) {
+ if (!$definition->isAbstract() && !$definition->isSynthetic() && !$definition->getClass() && (!$definition->getFactory() || !preg_match(FileLoader::ANONYMOUS_ID_REGEXP, $id))) {
if ($definition->getFactory()) {
throw new RuntimeException(sprintf('Please add the class to service "%s" even if it is constructed by a factory since we might need to add method calls based on compile-time checks.', $id));
}
if (class_exists($id) || interface_exists($id, false)) {
- if (0 === strpos($id, '\\') && 1 < substr_count($id, '\\')) {
+ if (str_starts_with($id, '\\') && 1 < substr_count($id, '\\')) {
throw new RuntimeException(sprintf('The definition for "%s" has no class attribute, and appears to reference a class or interface. Please specify the class attribute explicitly or remove the leading backslash by renaming the service to "%s" to get rid of this error.', $id, substr($id, 1)));
}
diff --git a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
index 77b35f18..eef71587 100644
--- a/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
@@ -22,15 +23,66 @@
*/
class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass
{
+ private $serviceLocatorContextIds = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $this->serviceLocatorContextIds = [];
+ foreach ($container->findTaggedServiceIds('container.service_locator_context') as $id => $tags) {
+ $this->serviceLocatorContextIds[$id] = $tags[0]['id'];
+ $container->getDefinition($id)->clearTag('container.service_locator_context');
+ }
+
+ try {
+ return parent::process($container);
+ } finally {
+ $this->serviceLocatorContextIds = [];
+ }
+ }
+
protected function processValue($value, $isRoot = false)
{
if (!$value instanceof Reference) {
return parent::processValue($value, $isRoot);
}
- if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) {
- throw new ServiceNotFoundException($id, $this->currentId);
+ if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $value->getInvalidBehavior() || $this->container->has($id = (string) $value)) {
+ return $value;
+ }
+
+ $currentId = $this->currentId;
+ $graph = $this->container->getCompiler()->getServiceReferenceGraph();
+
+ if (isset($this->serviceLocatorContextIds[$currentId])) {
+ $currentId = $this->serviceLocatorContextIds[$currentId];
+ $locator = $this->container->getDefinition($this->currentId)->getFactory()[0];
+
+ foreach ($locator->getArgument(0) as $k => $v) {
+ if ($v->getValues()[0] === $value) {
+ if ($k !== $id) {
+ $currentId = $k.'" in the container provided to "'.$currentId;
+ }
+ throw new ServiceNotFoundException($id, $currentId);
+ }
+ }
+ }
+
+ if ('.' === $currentId[0] && $graph->hasNode($currentId)) {
+ foreach ($graph->getNode($currentId)->getInEdges() as $edge) {
+ if (!$edge->getValue() instanceof Reference || ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $edge->getValue()->getInvalidBehavior()) {
+ continue;
+ }
+ $sourceId = $edge->getSourceNode()->getId();
+
+ if ('.' !== $sourceId[0]) {
+ $currentId = $sourceId;
+ break;
+ }
+ }
}
- return $value;
+ throw new ServiceNotFoundException($id, $currentId);
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php b/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php
new file mode 100644
index 00000000..ca10af65
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Compiler/CheckTypeDeclarationsPass.php
@@ -0,0 +1,329 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
+use Symfony\Component\DependencyInjection\Container;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\InvalidParameterTypeException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\ExpressionLanguage;
+use Symfony\Component\DependencyInjection\Parameter;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+use Symfony\Component\ExpressionLanguage\Expression;
+
+/**
+ * Checks whether injected parameters are compatible with type declarations.
+ *
+ * This pass should be run after all optimization passes.
+ *
+ * It can be added either:
+ * * before removing passes to check all services even if they are not currently used,
+ * * after removing passes to check only services are used in the app.
+ *
+ * @author Nicolas Grekas
+ * @author Julien Maulny
+ */
+final class CheckTypeDeclarationsPass extends AbstractRecursivePass
+{
+ private const SCALAR_TYPES = [
+ 'int' => true,
+ 'float' => true,
+ 'bool' => true,
+ 'string' => true,
+ ];
+
+ private const BUILTIN_TYPES = [
+ 'array' => true,
+ 'bool' => true,
+ 'callable' => true,
+ 'float' => true,
+ 'int' => true,
+ 'iterable' => true,
+ 'object' => true,
+ 'string' => true,
+ ];
+
+ private $autoload;
+ private $skippedIds;
+
+ private $expressionLanguage;
+
+ /**
+ * @param bool $autoload Whether services who's class in not loaded should be checked or not.
+ * Defaults to false to save loading code during compilation.
+ * @param array $skippedIds An array indexed by the service ids to skip
+ */
+ public function __construct(bool $autoload = false, array $skippedIds = [])
+ {
+ $this->autoload = $autoload;
+ $this->skippedIds = $skippedIds;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function processValue($value, $isRoot = false)
+ {
+ if (isset($this->skippedIds[$this->currentId])) {
+ return $value;
+ }
+
+ if (!$value instanceof Definition || $value->hasErrors() || $value->isDeprecated()) {
+ return parent::processValue($value, $isRoot);
+ }
+
+ if (!$this->autoload) {
+ if (!$class = $value->getClass()) {
+ return parent::processValue($value, $isRoot);
+ }
+ if (!class_exists($class, false) && !interface_exists($class, false)) {
+ return parent::processValue($value, $isRoot);
+ }
+ }
+
+ if (ServiceLocator::class === $value->getClass()) {
+ return parent::processValue($value, $isRoot);
+ }
+
+ if ($constructor = $this->getConstructor($value, false)) {
+ $this->checkTypeDeclarations($value, $constructor, $value->getArguments());
+ }
+
+ foreach ($value->getMethodCalls() as $methodCall) {
+ try {
+ $reflectionMethod = $this->getReflectionMethod($value, $methodCall[0]);
+ } catch (RuntimeException $e) {
+ if ($value->getFactory()) {
+ continue;
+ }
+
+ throw $e;
+ }
+
+ $this->checkTypeDeclarations($value, $reflectionMethod, $methodCall[1]);
+ }
+
+ return parent::processValue($value, $isRoot);
+ }
+
+ /**
+ * @throws InvalidArgumentException When not enough parameters are defined for the method
+ */
+ private function checkTypeDeclarations(Definition $checkedDefinition, \ReflectionFunctionAbstract $reflectionFunction, array $values): void
+ {
+ $numberOfRequiredParameters = $reflectionFunction->getNumberOfRequiredParameters();
+
+ if (\count($values) < $numberOfRequiredParameters) {
+ throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": "%s::%s()" requires %d arguments, %d passed.', $this->currentId, $reflectionFunction->class, $reflectionFunction->name, $numberOfRequiredParameters, \count($values)));
+ }
+
+ $reflectionParameters = $reflectionFunction->getParameters();
+ $checksCount = min($reflectionFunction->getNumberOfParameters(), \count($values));
+
+ $envPlaceholderUniquePrefix = $this->container->getParameterBag() instanceof EnvPlaceholderParameterBag ? $this->container->getParameterBag()->getEnvPlaceholderUniquePrefix() : null;
+
+ for ($i = 0; $i < $checksCount; ++$i) {
+ if (!$reflectionParameters[$i]->hasType() || $reflectionParameters[$i]->isVariadic()) {
+ continue;
+ }
+
+ $this->checkType($checkedDefinition, $values[$i], $reflectionParameters[$i], $envPlaceholderUniquePrefix);
+ }
+
+ if ($reflectionFunction->isVariadic() && ($lastParameter = end($reflectionParameters))->hasType()) {
+ $variadicParameters = \array_slice($values, $lastParameter->getPosition());
+
+ foreach ($variadicParameters as $variadicParameter) {
+ $this->checkType($checkedDefinition, $variadicParameter, $lastParameter, $envPlaceholderUniquePrefix);
+ }
+ }
+ }
+
+ /**
+ * @throws InvalidParameterTypeException When a parameter is not compatible with the declared type
+ */
+ private function checkType(Definition $checkedDefinition, $value, \ReflectionParameter $parameter, ?string $envPlaceholderUniquePrefix, \ReflectionType $reflectionType = null): void
+ {
+ $reflectionType = $reflectionType ?? $parameter->getType();
+
+ if ($reflectionType instanceof \ReflectionUnionType) {
+ foreach ($reflectionType->getTypes() as $t) {
+ try {
+ $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t);
+
+ return;
+ } catch (InvalidParameterTypeException $e) {
+ }
+ }
+
+ throw new InvalidParameterTypeException($this->currentId, $e->getCode(), $parameter);
+ }
+ if ($reflectionType instanceof \ReflectionIntersectionType) {
+ foreach ($reflectionType->getTypes() as $t) {
+ $this->checkType($checkedDefinition, $value, $parameter, $envPlaceholderUniquePrefix, $t);
+ }
+
+ return;
+ }
+ if (!$reflectionType instanceof \ReflectionNamedType) {
+ return;
+ }
+
+ $type = $reflectionType->getName();
+
+ if ($value instanceof Reference) {
+ if (!$this->container->has($value = (string) $value)) {
+ return;
+ }
+
+ if ('service_container' === $value && is_a($type, Container::class, true)) {
+ return;
+ }
+
+ $value = $this->container->findDefinition($value);
+ }
+
+ if ('self' === $type) {
+ $type = $parameter->getDeclaringClass()->getName();
+ }
+
+ if ('static' === $type) {
+ $type = $checkedDefinition->getClass();
+ }
+
+ $class = null;
+
+ if ($value instanceof Definition) {
+ if ($value->getFactory()) {
+ return;
+ }
+
+ $class = $value->getClass();
+
+ if ($class && isset(self::BUILTIN_TYPES[strtolower($class)])) {
+ $class = strtolower($class);
+ } elseif (!$class || (!$this->autoload && !class_exists($class, false) && !interface_exists($class, false))) {
+ return;
+ }
+ } elseif ($value instanceof Parameter) {
+ $value = $this->container->getParameter($value);
+ } elseif ($value instanceof Expression) {
+ try {
+ $value = $this->getExpressionLanguage()->evaluate($value, ['container' => $this->container]);
+ } catch (\Exception $e) {
+ // If a service from the expression cannot be fetched from the container, we skip the validation.
+ return;
+ }
+ } elseif (\is_string($value)) {
+ if ('%' === ($value[0] ?? '') && preg_match('/^%([^%]+)%$/', $value, $match)) {
+ $value = $this->container->getParameter(substr($value, 1, -1));
+ }
+
+ if ($envPlaceholderUniquePrefix && \is_string($value) && str_contains($value, 'env_')) {
+ // If the value is an env placeholder that is either mixed with a string or with another env placeholder, then its resolved value will always be a string, so we don't need to resolve it.
+ // We don't need to change the value because it is already a string.
+ if ('' === preg_replace('/'.$envPlaceholderUniquePrefix.'_\w+_[a-f0-9]{32}/U', '', $value, -1, $c) && 1 === $c) {
+ try {
+ $value = $this->container->resolveEnvPlaceholders($value, true);
+ } catch (\Exception $e) {
+ // If an env placeholder cannot be resolved, we skip the validation.
+ return;
+ }
+ }
+ }
+ }
+
+ if (null === $value && $parameter->allowsNull()) {
+ return;
+ }
+
+ if (null === $class) {
+ if ($value instanceof IteratorArgument) {
+ $class = RewindableGenerator::class;
+ } elseif ($value instanceof ServiceClosureArgument) {
+ $class = \Closure::class;
+ } elseif ($value instanceof ServiceLocatorArgument) {
+ $class = ServiceLocator::class;
+ } elseif (\is_object($value)) {
+ $class = \get_class($value);
+ } else {
+ $class = \gettype($value);
+ $class = ['integer' => 'int', 'double' => 'float', 'boolean' => 'bool'][$class] ?? $class;
+ }
+ }
+
+ if (isset(self::SCALAR_TYPES[$type]) && isset(self::SCALAR_TYPES[$class])) {
+ return;
+ }
+
+ if ('string' === $type && method_exists($class, '__toString')) {
+ return;
+ }
+
+ if ('callable' === $type && (\Closure::class === $class || method_exists($class, '__invoke'))) {
+ return;
+ }
+
+ if ('callable' === $type && \is_array($value) && isset($value[0]) && ($value[0] instanceof Reference || $value[0] instanceof Definition || \is_string($value[0]))) {
+ return;
+ }
+
+ if ('iterable' === $type && (\is_array($value) || 'array' === $class || is_subclass_of($class, \Traversable::class))) {
+ return;
+ }
+
+ if ($type === $class) {
+ return;
+ }
+
+ if ('object' === $type && !isset(self::BUILTIN_TYPES[$class])) {
+ return;
+ }
+
+ if ('mixed' === $type) {
+ return;
+ }
+
+ if (is_a($class, $type, true)) {
+ return;
+ }
+
+ if ('false' === $type) {
+ if (false === $value) {
+ return;
+ }
+ } elseif ($reflectionType->isBuiltin()) {
+ $checkFunction = sprintf('is_%s', $type);
+ if ($checkFunction($value)) {
+ return;
+ }
+ }
+
+ throw new InvalidParameterTypeException($this->currentId, \is_object($value) ? $class : \gettype($value), $parameter);
+ }
+
+ private function getExpressionLanguage(): ExpressionLanguage
+ {
+ if (null === $this->expressionLanguage) {
+ $this->expressionLanguage = new ExpressionLanguage(null, $this->container->getExpressionLanguageProviders());
+ }
+
+ return $this->expressionLanguage;
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Compiler/Compiler.php b/vendor/symfony/dependency-injection/Compiler/Compiler.php
index 0eb9d036..224ff6b1 100644
--- a/vendor/symfony/dependency-injection/Compiler/Compiler.php
+++ b/vendor/symfony/dependency-injection/Compiler/Compiler.php
@@ -23,7 +23,6 @@ class Compiler
{
private $passConfig;
private $log = [];
- private $loggingFormatter;
private $serviceReferenceGraph;
public function __construct()
@@ -52,68 +51,23 @@ public function getServiceReferenceGraph()
return $this->serviceReferenceGraph;
}
- /**
- * Returns the logging formatter which can be used by compilation passes.
- *
- * @return LoggingFormatter
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
- */
- public function getLoggingFormatter()
- {
- if (null === $this->loggingFormatter) {
- @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), \E_USER_DEPRECATED);
-
- $this->loggingFormatter = new LoggingFormatter();
- }
-
- return $this->loggingFormatter;
- }
-
/**
* Adds a pass to the PassConfig.
*
- * @param CompilerPassInterface $pass A compiler pass
- * @param string $type The type of the pass
+ * @param string $type The type of the pass
+ * @param int $priority Used to sort the passes
*/
- public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
+ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
{
- if (\func_num_args() >= 3) {
- $priority = func_get_arg(2);
- } else {
- if (__CLASS__ !== static::class) {
- $r = new \ReflectionMethod($this, __FUNCTION__);
- if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
- @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), \E_USER_DEPRECATED);
- }
- }
-
- $priority = 0;
- }
-
$this->passConfig->addPass($pass, $type, $priority);
}
- /**
- * Adds a log message.
- *
- * @param string $string The log message
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
- */
- public function addLogMessage($string)
- {
- @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), \E_USER_DEPRECATED);
-
- $this->log[] = $string;
- }
-
/**
* @final
*/
- public function log(CompilerPassInterface $pass, $message)
+ public function log(CompilerPassInterface $pass, string $message)
{
- if (false !== strpos($message, "\n")) {
+ if (str_contains($message, "\n")) {
$message = str_replace("\n", "\n".\get_class($pass).': ', trim($message));
}
diff --git a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
index bf5f9157..af7c957a 100644
--- a/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
+++ b/vendor/symfony/dependency-injection/Compiler/DecoratorServicePass.php
@@ -13,6 +13,10 @@
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
+use Symfony\Component\DependencyInjection\Reference;
/**
* Overwrites a service but keeps the overridden one.
@@ -36,14 +40,18 @@ public function process(ContainerBuilder $container)
}
$decoratingDefinitions = [];
- foreach ($definitions as list($id, $definition)) {
- list($inner, $renamedId) = $definition->getDecoratedService();
+ foreach ($definitions as [$id, $definition]) {
+ $decoratedService = $definition->getDecoratedService();
+ [$inner, $renamedId] = $decoratedService;
+ $invalidBehavior = $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
$definition->setDecoratedService(null);
if (!$renamedId) {
$renamedId = $id.'.inner';
}
+ $definition->innerServiceId = $renamedId;
+ $definition->decorationOnInvalid = $invalidBehavior;
// we create a new alias/service for the service we are replacing
// to be able to reference it in the new one
@@ -51,27 +59,46 @@ public function process(ContainerBuilder $container)
$alias = $container->getAlias($inner);
$public = $alias->isPublic();
$private = $alias->isPrivate();
- $container->setAlias($renamedId, new Alias($container->normalizeId($alias), false));
- } else {
+ $container->setAlias($renamedId, new Alias((string) $alias, false));
+ $decoratedDefinition = $container->findDefinition($alias);
+ } elseif ($container->hasDefinition($inner)) {
$decoratedDefinition = $container->getDefinition($inner);
$public = $decoratedDefinition->isPublic();
$private = $decoratedDefinition->isPrivate();
$decoratedDefinition->setPublic(false);
$container->setDefinition($renamedId, $decoratedDefinition);
$decoratingDefinitions[$inner] = $decoratedDefinition;
+ } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
+ $container->removeDefinition($id);
+ continue;
+ } elseif (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
+ $public = $definition->isPublic();
+ $private = $definition->isPrivate();
+ $decoratedDefinition = null;
+ } else {
+ throw new ServiceNotFoundException($inner, $id);
+ }
+
+ if ($decoratedDefinition && $decoratedDefinition->isSynthetic()) {
+ throw new InvalidArgumentException(sprintf('A synthetic service cannot be decorated: service "%s" cannot decorate "%s".', $id, $inner));
}
if (isset($decoratingDefinitions[$inner])) {
$decoratingDefinition = $decoratingDefinitions[$inner];
- $definition->setTags(array_merge($decoratingDefinition->getTags(), $definition->getTags()));
- $autowiringTypes = $decoratingDefinition->getAutowiringTypes(false);
- if ($types = array_merge($autowiringTypes, $definition->getAutowiringTypes(false))) {
- $definition->setAutowiringTypes($types);
- }
- $decoratingDefinition->setTags([]);
- if ($autowiringTypes) {
- $decoratingDefinition->setAutowiringTypes([]);
+
+ $decoratingTags = $decoratingDefinition->getTags();
+ $resetTags = [];
+
+ // container.service_locator and container.service_subscriber have special logic and they must not be transferred out to decorators
+ foreach (['container.service_locator', 'container.service_subscriber'] as $containerTag) {
+ if (isset($decoratingTags[$containerTag])) {
+ $resetTags[$containerTag] = $decoratingTags[$containerTag];
+ unset($decoratingTags[$containerTag]);
+ }
}
+
+ $definition->setTags(array_merge($decoratingTags, $definition->getTags()));
+ $decoratingDefinition->setTags($resetTags);
$decoratingDefinitions[$inner] = $definition;
}
diff --git a/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php b/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
index 73b5d1d5..5ee0ff1f 100644
--- a/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/DefinitionErrorExceptionPass.php
@@ -11,8 +11,10 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Reference;
/**
* Throws an exception for any Definitions that have errors and still exist.
@@ -26,10 +28,25 @@ class DefinitionErrorExceptionPass extends AbstractRecursivePass
*/
protected function processValue($value, $isRoot = false)
{
- if (!$value instanceof Definition || empty($value->getErrors())) {
+ if (!$value instanceof Definition || !$value->hasErrors()) {
return parent::processValue($value, $isRoot);
}
+ if ($isRoot && !$value->isPublic()) {
+ $graph = $this->container->getCompiler()->getServiceReferenceGraph();
+ $runtimeException = false;
+ foreach ($graph->getNode($this->currentId)->getInEdges() as $edge) {
+ if (!$edge->getValue() instanceof Reference || ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE !== $edge->getValue()->getInvalidBehavior()) {
+ $runtimeException = false;
+ break;
+ }
+ $runtimeException = true;
+ }
+ if ($runtimeException) {
+ return parent::processValue($value, $isRoot);
+ }
+ }
+
// only show the first error so the user can focus on it
$errors = $value->getErrors();
$message = reset($errors);
diff --git a/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php b/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
deleted file mode 100644
index 67575c03..00000000
--- a/vendor/symfony/dependency-injection/Compiler/FactoryReturnTypePass.php
+++ /dev/null
@@ -1,112 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Compiler;
-
-use Symfony\Component\DependencyInjection\ContainerBuilder;
-use Symfony\Component\DependencyInjection\Definition;
-use Symfony\Component\DependencyInjection\Reference;
-
-/**
- * @author Guilhem N.
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
-class FactoryReturnTypePass implements CompilerPassInterface
-{
- private $resolveClassPass;
-
- public function __construct(ResolveClassPass $resolveClassPass = null)
- {
- if (null === $resolveClassPass) {
- @trigger_error('The '.__CLASS__.' class is deprecated since Symfony 3.3 and will be removed in 4.0.', \E_USER_DEPRECATED);
- }
- $this->resolveClassPass = $resolveClassPass;
- }
-
- /**
- * {@inheritdoc}
- */
- public function process(ContainerBuilder $container)
- {
- // works only since php 7.0 and hhvm 3.11
- if (!method_exists(\ReflectionMethod::class, 'getReturnType')) {
- return;
- }
- $resolveClassPassChanges = null !== $this->resolveClassPass ? $this->resolveClassPass->getChanges() : [];
-
- foreach ($container->getDefinitions() as $id => $definition) {
- $this->updateDefinition($container, $id, $definition, $resolveClassPassChanges);
- }
- }
-
- private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $resolveClassPassChanges, array $previous = [])
- {
- // circular reference
- if (isset($previous[$id])) {
- return;
- }
-
- $factory = $definition->getFactory();
- if (null === $factory || (!isset($resolveClassPassChanges[$id]) && null !== $definition->getClass())) {
- return;
- }
-
- $class = null;
- if (\is_string($factory)) {
- try {
- $m = new \ReflectionFunction($factory);
- if (false !== $m->getFileName() && file_exists($m->getFileName())) {
- $container->fileExists($m->getFileName());
- }
- } catch (\ReflectionException $e) {
- return;
- }
- } else {
- if ($factory[0] instanceof Reference) {
- $previous[$id] = true;
- $factoryId = $container->normalizeId($factory[0]);
- $factoryDefinition = $container->findDefinition($factoryId);
- $this->updateDefinition($container, $factoryId, $factoryDefinition, $resolveClassPassChanges, $previous);
- $class = $factoryDefinition->getClass();
- } else {
- $class = $factory[0];
- }
-
- if (!$m = $container->getReflectionClass($class, false)) {
- return;
- }
- try {
- $m = $m->getMethod($factory[1]);
- } catch (\ReflectionException $e) {
- return;
- }
- }
-
- $returnType = $m->getReturnType();
- if (null !== $returnType && !$returnType->isBuiltin()) {
- $returnType = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
- if (null !== $class) {
- $declaringClass = $m->getDeclaringClass()->getName();
- if ('self' === strtolower($returnType)) {
- $returnType = $declaringClass;
- } elseif ('parent' === strtolower($returnType)) {
- $returnType = get_parent_class($declaringClass) ?: null;
- }
- }
-
- if (null !== $returnType && (!isset($resolveClassPassChanges[$id]) || $returnType !== $resolveClassPassChanges[$id])) {
- @trigger_error(sprintf('Relying on its factory\'s return-type to define the class of service "%s" is deprecated since Symfony 3.3 and won\'t work in 4.0. Set the "class" attribute to "%s" on the service definition instead.', $id, $returnType), \E_USER_DEPRECATED);
- }
- $definition->setClass($returnType);
- }
- }
-}
diff --git a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
index 9d8a02e7..358b750f 100644
--- a/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Reference;
@@ -23,31 +24,98 @@
*/
class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
{
+ private $analyzingPass;
+ private $repeatedPass;
private $cloningIds = [];
- private $inlinedServiceIds = [];
+ private $connectedIds = [];
+ private $notInlinedIds = [];
+ private $inlinedIds = [];
+ private $notInlinableIds = [];
+ private $graph;
+
+ public function __construct(AnalyzeServiceReferencesPass $analyzingPass = null)
+ {
+ $this->analyzingPass = $analyzingPass;
+ }
/**
* {@inheritdoc}
*/
public function setRepeatedPass(RepeatedPass $repeatedPass)
{
- // no-op for BC
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
+ $this->repeatedPass = $repeatedPass;
}
- /**
- * Returns an array of all services inlined by this pass.
- *
- * The key is the inlined service id and its value is the list of services it was inlined into.
- *
- * @deprecated since version 3.4, to be removed in 4.0.
- *
- * @return array
- */
- public function getInlinedServiceIds()
+ public function process(ContainerBuilder $container)
{
- @trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', \E_USER_DEPRECATED);
+ $this->container = $container;
+ if ($this->analyzingPass) {
+ $analyzedContainer = new ContainerBuilder();
+ $analyzedContainer->setAliases($container->getAliases());
+ $analyzedContainer->setDefinitions($container->getDefinitions());
+ foreach ($container->getExpressionLanguageProviders() as $provider) {
+ $analyzedContainer->addExpressionLanguageProvider($provider);
+ }
+ } else {
+ $analyzedContainer = $container;
+ }
+ try {
+ $remainingInlinedIds = [];
+ $this->connectedIds = $this->notInlinedIds = $container->getDefinitions();
+ do {
+ if ($this->analyzingPass) {
+ $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds));
+ $this->analyzingPass->process($analyzedContainer);
+ }
+ $this->graph = $analyzedContainer->getCompiler()->getServiceReferenceGraph();
+ $notInlinedIds = $this->notInlinedIds;
+ $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = [];
+
+ foreach ($analyzedContainer->getDefinitions() as $id => $definition) {
+ if (!$this->graph->hasNode($id)) {
+ continue;
+ }
+ foreach ($this->graph->getNode($id)->getOutEdges() as $edge) {
+ if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) {
+ $this->currentId = $id;
+ $this->processValue($definition, true);
+ break;
+ }
+ }
+ }
+
+ foreach ($this->inlinedIds as $id => $isPublicOrNotShared) {
+ if ($isPublicOrNotShared) {
+ $remainingInlinedIds[$id] = $id;
+ } else {
+ $container->removeDefinition($id);
+ $analyzedContainer->removeDefinition($id);
+ }
+ }
+ } while ($this->inlinedIds && $this->analyzingPass);
+
+ if ($this->inlinedIds && $this->repeatedPass) {
+ $this->repeatedPass->setRepeat();
+ }
+
+ foreach ($remainingInlinedIds as $id) {
+ if (isset($this->notInlinableIds[$id])) {
+ continue;
+ }
+
+ $definition = $container->getDefinition($id);
- return $this->inlinedServiceIds;
+ if (!$definition->isShared() && !$definition->isPublic()) {
+ $container->removeDefinition($id);
+ }
+ }
+ } finally {
+ $this->container = null;
+ $this->connectedIds = $this->notInlinedIds = $this->inlinedIds = [];
+ $this->notInlinableIds = [];
+ $this->graph = null;
+ }
}
/**
@@ -56,7 +124,7 @@ public function getInlinedServiceIds()
protected function processValue($value, $isRoot = false)
{
if ($value instanceof ArgumentInterface) {
- // Reference found in ArgumentInterface::getValues() are not inlineable
+ // References found in ArgumentInterface::getValues() are not inlineable
return $value;
}
@@ -67,18 +135,23 @@ protected function processValue($value, $isRoot = false)
$value = clone $value;
}
- if (!$value instanceof Reference || !$this->container->hasDefinition($id = $this->container->normalizeId($value))) {
+ if (!$value instanceof Reference) {
return parent::processValue($value, $isRoot);
+ } elseif (!$this->container->hasDefinition($id = (string) $value)) {
+ return $value;
}
$definition = $this->container->getDefinition($id);
- if (!$this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
+ if (!$this->isInlineableDefinition($id, $definition)) {
+ $this->notInlinableIds[$id] = true;
+
return $value;
}
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
- $this->inlinedServiceIds[$id][] = $this->currentId;
+ $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared();
+ $this->notInlinedIds[$this->currentId] = true;
if ($definition->isShared()) {
return $definition;
@@ -101,53 +174,64 @@ protected function processValue($value, $isRoot = false)
/**
* Checks if the definition is inlineable.
- *
- * @return bool If the definition is inlineable
*/
- private function isInlineableDefinition($id, Definition $definition, ServiceReferenceGraph $graph)
+ private function isInlineableDefinition(string $id, Definition $definition): bool
{
- if ($definition->getErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
+ if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
return false;
}
if (!$definition->isShared()) {
+ if (!$this->graph->hasNode($id)) {
+ return true;
+ }
+
+ foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
+ $srcId = $edge->getSourceNode()->getId();
+ $this->connectedIds[$srcId] = true;
+ if ($edge->isWeak() || $edge->isLazy()) {
+ return !$this->connectedIds[$id] = true;
+ }
+ }
+
return true;
}
- if ($definition->isPublic() || $definition->isPrivate()) {
+ if ($definition->isPublic()) {
return false;
}
- if (!$graph->hasNode($id)) {
+ if (!$this->graph->hasNode($id)) {
return true;
}
if ($this->currentId == $id) {
return false;
}
+ $this->connectedIds[$id] = true;
- $ids = [];
- $isReferencedByConstructor = false;
- foreach ($graph->getNode($id)->getInEdges() as $edge) {
- $isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor();
+ $srcIds = [];
+ $srcCount = 0;
+ foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
+ $srcId = $edge->getSourceNode()->getId();
+ $this->connectedIds[$srcId] = true;
if ($edge->isWeak() || $edge->isLazy()) {
return false;
}
- $ids[] = $edge->getSourceNode()->getId();
+ $srcIds[$srcId] = true;
+ ++$srcCount;
}
- if (!$ids) {
- return true;
- }
+ if (1 !== \count($srcIds)) {
+ $this->notInlinedIds[$id] = true;
- if (\count(array_unique($ids)) > 1) {
return false;
}
- if (\count($ids) > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
+ if ($srcCount > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
return false;
}
- return $this->container->getDefinition($ids[0])->isShared();
+ return $this->container->getDefinition($srcId)->isShared();
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php b/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
deleted file mode 100644
index 0d91f00f..00000000
--- a/vendor/symfony/dependency-injection/Compiler/LoggingFormatter.php
+++ /dev/null
@@ -1,54 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Compiler;
-
-@trigger_error('The '.__NAMESPACE__.'\LoggingFormatter class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', \E_USER_DEPRECATED);
-
-/**
- * Used to format logging messages during the compilation.
- *
- * @author Johannes M. Schmitt
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead.
- */
-class LoggingFormatter
-{
- public function formatRemoveService(CompilerPassInterface $pass, $id, $reason)
- {
- return $this->format($pass, sprintf('Removed service "%s"; reason: %s.', $id, $reason));
- }
-
- public function formatInlineService(CompilerPassInterface $pass, $id, $target)
- {
- return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target));
- }
-
- public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId)
- {
- return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId));
- }
-
- public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId)
- {
- return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId));
- }
-
- public function formatUnusedAutowiringPatterns(CompilerPassInterface $pass, $id, array $patterns)
- {
- return $this->format($pass, sprintf('Autowiring\'s patterns "%s" for service "%s" don\'t match any method.', implode('", "', $patterns), $id));
- }
-
- public function format(CompilerPassInterface $pass, $message)
- {
- return sprintf('%s: %s', \get_class($pass), $message);
- }
-}
diff --git a/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php b/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
index caa1fd22..5e4dd399 100644
--- a/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/MergeExtensionConfigurationPass.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+use Symfony\Component\Config\Definition\BaseNode;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\LogicException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -37,6 +38,7 @@ public function process(ContainerBuilder $container)
$definitions = $container->getDefinitions();
$aliases = $container->getAliases();
$exprLangProviders = $container->getExpressionLanguageProviders();
+ $configAvailable = class_exists(BaseNode::class);
foreach ($container->getExtensions() as $extension) {
if ($extension instanceof PrependExtensionInterface) {
@@ -53,6 +55,9 @@ public function process(ContainerBuilder $container)
if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) {
// create a dedicated bag so that we can track env vars per-extension
$resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag);
+ if ($configAvailable) {
+ BaseNode::setPlaceholderUniquePrefix($resolvingBag->getEnvPlaceholderUniquePrefix());
+ }
}
$config = $resolvingBag->resolveValue($config);
@@ -74,6 +79,10 @@ public function process(ContainerBuilder $container)
$container->getParameterBag()->mergeEnvPlaceholders($resolvingBag);
}
+ if ($configAvailable) {
+ BaseNode::resetPlaceholders();
+ }
+
throw $e;
}
@@ -86,6 +95,10 @@ public function process(ContainerBuilder $container)
$container->getParameterBag()->add($parameters);
}
+ if ($configAvailable) {
+ BaseNode::resetPlaceholders();
+ }
+
$container->addDefinitions($definitions);
$container->addAliases($aliases);
}
@@ -128,9 +141,14 @@ public function freezeAfterProcessing(Extension $extension, ContainerBuilder $co
/**
* {@inheritdoc}
*/
- public function getEnvPlaceholders()
+ public function getEnvPlaceholders(): array
+ {
+ return $this->processedEnvPlaceholders ?? parent::getEnvPlaceholders();
+ }
+
+ public function getUnusedEnvPlaceholders(): array
{
- return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders();
+ return null === $this->processedEnvPlaceholders ? [] : array_diff_key(parent::getEnvPlaceholders(), $this->processedEnvPlaceholders);
}
}
@@ -153,7 +171,7 @@ public function __construct(ExtensionInterface $extension, ParameterBagInterface
/**
* {@inheritdoc}
*/
- public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
+ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0): self
{
throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', \get_class($pass), $this->extensionClass));
}
@@ -169,7 +187,7 @@ public function registerExtension(ExtensionInterface $extension)
/**
* {@inheritdoc}
*/
- public function compile($resolveEnvPlaceholders = false)
+ public function compile(bool $resolveEnvPlaceholders = false)
{
throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass));
}
@@ -191,7 +209,7 @@ public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs
}
foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
- if (false === strpos($env, ':')) {
+ if (!str_contains($env, ':')) {
continue;
}
foreach ($placeholders as $placeholder) {
diff --git a/vendor/symfony/dependency-injection/Compiler/PassConfig.php b/vendor/symfony/dependency-injection/Compiler/PassConfig.php
index d95b2198..f02a88fc 100644
--- a/vendor/symfony/dependency-injection/Compiler/PassConfig.php
+++ b/vendor/symfony/dependency-injection/Compiler/PassConfig.php
@@ -22,11 +22,11 @@
*/
class PassConfig
{
- const TYPE_AFTER_REMOVING = 'afterRemoving';
- const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
- const TYPE_BEFORE_REMOVING = 'beforeRemoving';
- const TYPE_OPTIMIZE = 'optimization';
- const TYPE_REMOVE = 'removing';
+ public const TYPE_AFTER_REMOVING = 'afterRemoving';
+ public const TYPE_BEFORE_OPTIMIZATION = 'beforeOptimization';
+ public const TYPE_BEFORE_REMOVING = 'beforeRemoving';
+ public const TYPE_OPTIMIZE = 'optimization';
+ public const TYPE_REMOVE = 'removing';
private $mergePass;
private $afterRemovingPasses = [];
@@ -41,7 +41,7 @@ public function __construct()
$this->beforeOptimizationPasses = [
100 => [
- $resolveClassPass = new ResolveClassPass(),
+ new ResolveClassPass(),
new ResolveInstanceofConditionalsPass(),
new RegisterEnvVarProcessorsPass(),
],
@@ -49,17 +49,17 @@ public function __construct()
];
$this->optimizationPasses = [[
+ new ValidateEnvPlaceholdersPass(),
new ResolveChildDefinitionsPass(),
- new ServiceLocatorTagPass(),
new RegisterServiceSubscribersPass(),
- new DecoratorServicePass(),
new ResolveParameterPlaceHoldersPass(false, false),
new ResolveFactoryClassPass(),
- new FactoryReturnTypePass($resolveClassPass),
- new CheckDefinitionValidityPass(),
new ResolveNamedArgumentsPass(),
new AutowireRequiredMethodsPass(),
new ResolveBindingsPass(),
+ new ServiceLocatorTagPass(),
+ new DecoratorServicePass(),
+ new CheckDefinitionValidityPass(),
new AutowirePass(false),
new ResolveTaggedIteratorArgumentPass(),
new ResolveServiceSubscribersPass(),
@@ -81,14 +81,15 @@ public function __construct()
new RemovePrivateAliasesPass(),
new ReplaceAliasByActualDefinitionPass(),
new RemoveAbstractDefinitionsPass(),
- new RepeatedPass([
- new AnalyzeServiceReferencesPass(),
- new InlineServiceDefinitionsPass(),
- new AnalyzeServiceReferencesPass(),
- new RemoveUnusedDefinitionsPass(),
- ]),
- new DefinitionErrorExceptionPass(),
+ new RemoveUnusedDefinitionsPass(),
+ new AnalyzeServiceReferencesPass(),
new CheckExceptionOnInvalidReferenceBehaviorPass(),
+ new InlineServiceDefinitionsPass(new AnalyzeServiceReferencesPass()),
+ new AnalyzeServiceReferencesPass(),
+ new DefinitionErrorExceptionPass(),
+ ]];
+
+ $this->afterRemovingPasses = [[
new ResolveHotPathPass(),
]];
}
@@ -113,26 +114,13 @@ public function getPasses()
/**
* Adds a pass.
*
- * @param CompilerPassInterface $pass A Compiler pass
- * @param string $type The pass type
+ * @param string $type The pass type
+ * @param int $priority Used to sort the passes
*
* @throws InvalidArgumentException when a pass type doesn't exist
*/
- public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
+ public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
{
- if (\func_num_args() >= 3) {
- $priority = func_get_arg(2);
- } else {
- if (__CLASS__ !== static::class) {
- $r = new \ReflectionMethod($this, __FUNCTION__);
- if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
- @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), \E_USER_DEPRECATED);
- }
- }
-
- $priority = 0;
- }
-
$property = $type.'Passes';
if (!isset($this->$property)) {
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
@@ -268,7 +256,7 @@ public function setRemovingPasses(array $passes)
*
* @return CompilerPassInterface[]
*/
- private function sortPasses(array $passes)
+ private function sortPasses(array $passes): array
{
if (0 === \count($passes)) {
return [];
@@ -277,6 +265,6 @@ private function sortPasses(array $passes)
krsort($passes);
// Flatten the array
- return \call_user_func_array('array_merge', $passes);
+ return array_merge(...$passes);
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php b/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
index c7e12536..f558927e 100644
--- a/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
+++ b/vendor/symfony/dependency-injection/Compiler/PriorityTaggedServiceTrait.php
@@ -11,8 +11,11 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\TypedReference;
/**
* Trait that allows a generic method to find and sort service by priority option in the tag.
@@ -31,24 +34,141 @@ trait PriorityTaggedServiceTrait
* @see https://bugs.php.net/53710
* @see https://bugs.php.net/60926
*
- * @param string $tagName
+ * @param string|TaggedIteratorArgument $tagName
*
* @return Reference[]
*/
- private function findAndSortTaggedServices($tagName, ContainerBuilder $container)
+ private function findAndSortTaggedServices($tagName, ContainerBuilder $container): array
{
+ $indexAttribute = $defaultIndexMethod = $needsIndexes = $defaultPriorityMethod = null;
+
+ if ($tagName instanceof TaggedIteratorArgument) {
+ $indexAttribute = $tagName->getIndexAttribute();
+ $defaultIndexMethod = $tagName->getDefaultIndexMethod();
+ $needsIndexes = $tagName->needsIndexes();
+ $defaultPriorityMethod = $tagName->getDefaultPriorityMethod() ?? 'getDefaultPriority';
+ $tagName = $tagName->getTag();
+ }
+
+ $i = 0;
$services = [];
foreach ($container->findTaggedServiceIds($tagName, true) as $serviceId => $attributes) {
- $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
- $services[$priority][] = new Reference($serviceId);
+ $defaultPriority = null;
+ $defaultIndex = null;
+ $class = $container->getDefinition($serviceId)->getClass();
+ $class = $container->getParameterBag()->resolveValue($class) ?: null;
+
+ foreach ($attributes as $attribute) {
+ $index = $priority = null;
+
+ if (isset($attribute['priority'])) {
+ $priority = $attribute['priority'];
+ } elseif (null === $defaultPriority && $defaultPriorityMethod && $class) {
+ $defaultPriority = PriorityTaggedServiceUtil::getDefaultPriority($container, $serviceId, $class, $defaultPriorityMethod, $tagName);
+ }
+ $priority = $priority ?? $defaultPriority ?? $defaultPriority = 0;
+
+ if (null === $indexAttribute && !$defaultIndexMethod && !$needsIndexes) {
+ $services[] = [$priority, ++$i, null, $serviceId, null];
+ continue 2;
+ }
+
+ if (null !== $indexAttribute && isset($attribute[$indexAttribute])) {
+ $index = $attribute[$indexAttribute];
+ } elseif (null === $defaultIndex && $defaultPriorityMethod && $class) {
+ $defaultIndex = PriorityTaggedServiceUtil::getDefaultIndex($container, $serviceId, $class, $defaultIndexMethod ?? 'getDefaultName', $tagName, $indexAttribute);
+ }
+ $index = $index ?? $defaultIndex ?? $defaultIndex = $serviceId;
+
+ $services[] = [$priority, ++$i, $index, $serviceId, $class];
+ }
+ }
+
+ uasort($services, static function ($a, $b) { return $b[0] <=> $a[0] ?: $a[1] <=> $b[1]; });
+
+ $refs = [];
+ foreach ($services as [, , $index, $serviceId, $class]) {
+ if (!$class) {
+ $reference = new Reference($serviceId);
+ } elseif ($index === $serviceId) {
+ $reference = new TypedReference($serviceId, $class);
+ } else {
+ $reference = new TypedReference($serviceId, $class, ContainerBuilder::EXCEPTION_ON_INVALID_REFERENCE, $index);
+ }
+
+ if (null === $index) {
+ $refs[] = $reference;
+ } else {
+ $refs[$index] = $reference;
+ }
+ }
+
+ return $refs;
+ }
+}
+
+/**
+ * @internal
+ */
+class PriorityTaggedServiceUtil
+{
+ /**
+ * Gets the index defined by the default index method.
+ */
+ public static function getDefaultIndex(ContainerBuilder $container, string $serviceId, string $class, string $defaultIndexMethod, string $tagName, ?string $indexAttribute): ?string
+ {
+ if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultIndexMethod)) {
+ return null;
+ }
+
+ if (null !== $indexAttribute) {
+ $service = $class !== $serviceId ? sprintf('service "%s"', $serviceId) : 'on the corresponding service';
+ $message = [sprintf('Either method "%s::%s()" should ', $class, $defaultIndexMethod), sprintf(' or tag "%s" on %s is missing attribute "%s".', $tagName, $service, $indexAttribute)];
+ } else {
+ $message = [sprintf('Method "%s::%s()" should ', $class, $defaultIndexMethod), '.'];
+ }
+
+ if (!($rm = $r->getMethod($defaultIndexMethod))->isStatic()) {
+ throw new InvalidArgumentException(implode('be static', $message));
+ }
+
+ if (!$rm->isPublic()) {
+ throw new InvalidArgumentException(implode('be public', $message));
+ }
+
+ $defaultIndex = $rm->invoke(null);
+
+ if (!\is_string($defaultIndex)) {
+ throw new InvalidArgumentException(implode(sprintf('return a string (got "%s")', \gettype($defaultIndex)), $message));
+ }
+
+ return $defaultIndex;
+ }
+
+ /**
+ * Gets the priority defined by the default priority method.
+ */
+ public static function getDefaultPriority(ContainerBuilder $container, string $serviceId, string $class, string $defaultPriorityMethod, string $tagName): ?int
+ {
+ if (!($r = $container->getReflectionClass($class)) || !$r->hasMethod($defaultPriorityMethod)) {
+ return null;
}
- if ($services) {
- krsort($services);
- $services = \call_user_func_array('array_merge', $services);
+ if (!($rm = $r->getMethod($defaultPriorityMethod))->isStatic()) {
+ throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be static or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
+ }
+
+ if (!$rm->isPublic()) {
+ throw new InvalidArgumentException(sprintf('Either method "%s::%s()" should be public or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, $tagName, $serviceId));
+ }
+
+ $defaultPriority = $rm->invoke(null);
+
+ if (!\is_int($defaultPriority)) {
+ throw new InvalidArgumentException(sprintf('Method "%s::%s()" should return an integer (got "%s") or tag "%s" on service "%s" is missing attribute "priority".', $class, $defaultPriorityMethod, \gettype($defaultPriority), $tagName, $serviceId));
}
- return $services;
+ return $defaultPriority;
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
index b4d0d055..251889eb 100644
--- a/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/RegisterEnvVarProcessorsPass.php
@@ -11,14 +11,12 @@
namespace Symfony\Component\DependencyInjection\Compiler;
-use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\EnvVarProcessor;
use Symfony\Component\DependencyInjection\EnvVarProcessorInterface;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\ServiceLocator;
/**
* Creates the container.env_var_processors_locator service.
@@ -27,7 +25,7 @@
*/
class RegisterEnvVarProcessorsPass implements CompilerPassInterface
{
- private static $allowedTypes = ['array', 'bool', 'float', 'int', 'string'];
+ private const ALLOWED_TYPES = ['array', 'bool', 'float', 'int', 'string'];
public function process(ContainerBuilder $container)
{
@@ -41,7 +39,7 @@ public function process(ContainerBuilder $container)
throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class));
}
foreach ($class::getProvidedTypes() as $prefix => $type) {
- $processors[$prefix] = new ServiceClosureArgument(new Reference($id));
+ $processors[$prefix] = new Reference($id);
$types[$prefix] = self::validateProvidedTypes($type, $class);
}
}
@@ -56,20 +54,19 @@ public function process(ContainerBuilder $container)
}
if ($processors) {
- $container->register('container.env_var_processors_locator', ServiceLocator::class)
+ $container->setAlias('container.env_var_processors_locator', (string) ServiceLocatorTagPass::register($container, $processors))
->setPublic(true)
- ->setArguments([$processors])
;
}
}
- private static function validateProvidedTypes($types, $class)
+ private static function validateProvidedTypes(string $types, string $class): array
{
$types = explode('|', $types);
foreach ($types as $type) {
- if (!\in_array($type, self::$allowedTypes)) {
- throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes)));
+ if (!\in_array($type, self::ALLOWED_TYPES)) {
+ throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::ALLOWED_TYPES)));
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php
new file mode 100644
index 00000000..571eab3e
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Compiler/RegisterReverseContainerPass.php
@@ -0,0 +1,66 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * @author Nicolas Grekas
+ */
+class RegisterReverseContainerPass implements CompilerPassInterface
+{
+ private $beforeRemoving;
+ private $serviceId;
+ private $tagName;
+
+ public function __construct(bool $beforeRemoving, string $serviceId = 'reverse_container', string $tagName = 'container.reversible')
+ {
+ $this->beforeRemoving = $beforeRemoving;
+ $this->serviceId = $serviceId;
+ $this->tagName = $tagName;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->serviceId)) {
+ return;
+ }
+
+ $refType = $this->beforeRemoving ? ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
+ $services = [];
+ foreach ($container->findTaggedServiceIds($this->tagName) as $id => $tags) {
+ $services[$id] = new Reference($id, $refType);
+ }
+
+ if ($this->beforeRemoving) {
+ // prevent inlining of the reverse container
+ $services[$this->serviceId] = new Reference($this->serviceId, $refType);
+ }
+ $locator = $container->getDefinition($this->serviceId)->getArgument(1);
+
+ if ($locator instanceof Reference) {
+ $locator = $container->getDefinition((string) $locator);
+ }
+ if ($locator instanceof Definition) {
+ foreach ($services as $id => $ref) {
+ $services[$id] = new ServiceClosureArgument($ref);
+ }
+ $locator->replaceArgument(0, $services);
+ } else {
+ $locator->setValues($services);
+ }
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
index bf1387c0..b6d1ede4 100644
--- a/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/RegisterServiceSubscribersPass.php
@@ -11,12 +11,15 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+use Psr\Container\ContainerInterface as PsrContainerInterface;
+use Symfony\Component\DependencyInjection\Argument\BoundArgument;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Reference;
-use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
use Symfony\Component\DependencyInjection\TypedReference;
+use Symfony\Contracts\Service\ServiceProviderInterface;
+use Symfony\Contracts\Service\ServiceSubscriberInterface;
/**
* Compiler pass to register tagged services that require a service locator.
@@ -65,7 +68,6 @@ protected function processValue($value, $isRoot = false)
$class = $r->name;
$subscriberMap = [];
- $declaringClass = (new \ReflectionMethod($class, 'getSubscribedServices'))->class;
foreach ($class::getSubscribedServices() as $key => $type) {
if (!\is_string($type) || !preg_match('/^\??[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+$/', $type)) {
@@ -75,8 +77,9 @@ protected function processValue($value, $isRoot = false)
$type = substr($type, 1);
$optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE;
}
- if (\is_int($key)) {
+ if (\is_int($name = $key)) {
$key = $type;
+ $name = null;
}
if (!isset($serviceMap[$key])) {
if (!$autowire) {
@@ -85,7 +88,20 @@ protected function processValue($value, $isRoot = false)
$serviceMap[$key] = new Reference($type);
}
- $subscriberMap[$key] = new TypedReference($this->container->normalizeId($serviceMap[$key]), $type, $declaringClass, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
+ if ($name) {
+ if (false !== $i = strpos($name, '::get')) {
+ $name = lcfirst(substr($name, 5 + $i));
+ } elseif (str_contains($name, '::')) {
+ $name = null;
+ }
+ }
+
+ if (null !== $name && !$this->container->has($name) && !$this->container->has($type.' $'.$name)) {
+ $camelCaseName = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name))));
+ $name = $this->container->has($type.' $'.$camelCaseName) ? $camelCaseName : $name;
+ }
+
+ $subscriberMap[$key] = new TypedReference((string) $serviceMap[$key], $type, $optionalBehavior ?: ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $name);
unset($serviceMap[$key]);
}
@@ -94,7 +110,14 @@ protected function processValue($value, $isRoot = false)
throw new InvalidArgumentException(sprintf('Service %s not exist in the map returned by "%s::getSubscribedServices()" for service "%s".', $message, $class, $this->currentId));
}
- $value->addTag('container.service_subscriber.locator', ['id' => (string) ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId)]);
+ $locatorRef = ServiceLocatorTagPass::register($this->container, $subscriberMap, $this->currentId);
+
+ $value->addTag('container.service_subscriber.locator', ['id' => (string) $locatorRef]);
+
+ $value->setBindings([
+ PsrContainerInterface::class => new BoundArgument($locatorRef, false),
+ ServiceProviderInterface::class => new BoundArgument($locatorRef, false),
+ ] + $value->getBindings());
return parent::processValue($value);
}
diff --git a/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
index 03d9e1d8..75b36d22 100644
--- a/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/RemovePrivateAliasesPass.php
@@ -28,7 +28,7 @@ class RemovePrivateAliasesPass implements CompilerPassInterface
public function process(ContainerBuilder $container)
{
foreach ($container->getAliases() as $id => $alias) {
- if ($alias->isPublic() || $alias->isPrivate()) {
+ if ($alias->isPublic()) {
continue;
}
diff --git a/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
index a1013f66..8f3a1c2d 100644
--- a/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/RemoveUnusedDefinitionsPass.php
@@ -12,22 +12,24 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
/**
* Removes unused service definitions from the container.
*
* @author Johannes M. Schmitt
+ * @author Nicolas Grekas
*/
-class RemoveUnusedDefinitionsPass implements RepeatablePassInterface
+class RemoveUnusedDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
{
- private $repeatedPass;
+ private $connectedIds = [];
/**
* {@inheritdoc}
*/
public function setRepeatedPass(RepeatedPass $repeatedPass)
{
- $this->repeatedPass = $repeatedPass;
+ @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), \E_USER_DEPRECATED);
}
/**
@@ -35,51 +37,62 @@ public function setRepeatedPass(RepeatedPass $repeatedPass)
*/
public function process(ContainerBuilder $container)
{
- $graph = $container->getCompiler()->getServiceReferenceGraph();
+ try {
+ $this->enableExpressionProcessing();
+ $this->container = $container;
+ $connectedIds = [];
+ $aliases = $container->getAliases();
- $hasChanged = false;
- foreach ($container->getDefinitions() as $id => $definition) {
- if ($definition->isPublic() || $definition->isPrivate()) {
- continue;
+ foreach ($aliases as $id => $alias) {
+ if ($alias->isPublic()) {
+ $this->connectedIds[] = (string) $aliases[$id];
+ }
}
- if ($graph->hasNode($id)) {
- $edges = $graph->getNode($id)->getInEdges();
- $referencingAliases = [];
- $sourceIds = [];
- foreach ($edges as $edge) {
- if ($edge->isWeak()) {
- continue;
- }
- $node = $edge->getSourceNode();
- $sourceIds[] = $node->getId();
+ foreach ($container->getDefinitions() as $id => $definition) {
+ if ($definition->isPublic()) {
+ $connectedIds[$id] = true;
+ $this->processValue($definition);
+ }
+ }
- if ($node->isAlias()) {
- $referencingAliases[] = $node->getValue();
+ while ($this->connectedIds) {
+ $ids = $this->connectedIds;
+ $this->connectedIds = [];
+ foreach ($ids as $id) {
+ if (!isset($connectedIds[$id]) && $container->hasDefinition($id)) {
+ $connectedIds[$id] = true;
+ $this->processValue($container->getDefinition($id));
}
}
- $isReferenced = (\count(array_unique($sourceIds)) - \count($referencingAliases)) > 0;
- } else {
- $referencingAliases = [];
- $isReferenced = false;
}
- if (1 === \count($referencingAliases) && false === $isReferenced) {
- $container->setDefinition((string) reset($referencingAliases), $definition);
- $definition->setPublic(!$definition->isPrivate());
- $definition->setPrivate(reset($referencingAliases)->isPrivate());
- $container->removeDefinition($id);
- $container->log($this, sprintf('Removed service "%s"; reason: replaces alias %s.', $id, reset($referencingAliases)));
- } elseif (0 === \count($referencingAliases) && false === $isReferenced) {
- $container->removeDefinition($id);
- $container->resolveEnvPlaceholders(serialize($definition));
- $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id));
- $hasChanged = true;
+ foreach ($container->getDefinitions() as $id => $definition) {
+ if (!isset($connectedIds[$id])) {
+ $container->removeDefinition($id);
+ $container->resolveEnvPlaceholders(!$definition->hasErrors() ? serialize($definition) : $definition);
+ $container->log($this, sprintf('Removed service "%s"; reason: unused.', $id));
+ }
}
+ } finally {
+ $this->container = null;
+ $this->connectedIds = [];
}
+ }
- if ($hasChanged) {
- $this->repeatedPass->setRepeat();
+ /**
+ * {@inheritdoc}
+ */
+ protected function processValue($value, $isRoot = false)
+ {
+ if (!$value instanceof Reference) {
+ return parent::processValue($value, $isRoot);
}
+
+ if (ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior()) {
+ $this->connectedIds[] = (string) $value;
+ }
+
+ return $value;
}
}
diff --git a/vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php b/vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php
index 2b88bfb9..11a5b0d5 100644
--- a/vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php
+++ b/vendor/symfony/dependency-injection/Compiler/RepeatablePassInterface.php
@@ -16,6 +16,8 @@
* RepeatedPass.
*
* @author Johannes M. Schmitt
+ *
+ * @deprecated since Symfony 4.2.
*/
interface RepeatablePassInterface extends CompilerPassInterface
{
diff --git a/vendor/symfony/dependency-injection/Compiler/RepeatedPass.php b/vendor/symfony/dependency-injection/Compiler/RepeatedPass.php
index 3da1a0d5..bc155cf0 100644
--- a/vendor/symfony/dependency-injection/Compiler/RepeatedPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/RepeatedPass.php
@@ -11,6 +11,8 @@
namespace Symfony\Component\DependencyInjection\Compiler;
+@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.2.', RepeatedPass::class), \E_USER_DEPRECATED);
+
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -18,6 +20,8 @@
* A pass that might be run repeatedly.
*
* @author Johannes M. Schmitt
+ *
+ * @deprecated since Symfony 4.2.
*/
class RepeatedPass implements CompilerPassInterface
{
diff --git a/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php b/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
index 472bf941..99810963 100644
--- a/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ReplaceAliasByActualDefinitionPass.php
@@ -13,6 +13,7 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
/**
@@ -36,7 +37,7 @@ public function process(ContainerBuilder $container)
$seenAliasTargets = [];
$replacements = [];
foreach ($container->getAliases() as $definitionId => $target) {
- $targetId = $container->normalizeId($target);
+ $targetId = (string) $target;
// Special case: leave this target alone
if ('service_container' === $targetId) {
continue;
@@ -53,10 +54,14 @@ public function process(ContainerBuilder $container)
$seenAliasTargets[$targetId] = true;
try {
$definition = $container->getDefinition($targetId);
- } catch (InvalidArgumentException $e) {
- throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e);
+ } catch (ServiceNotFoundException $e) {
+ if ('' !== $e->getId() && '@' === $e->getId()[0]) {
+ throw new ServiceNotFoundException($e->getId(), $e->getSourceId(), null, [substr($e->getId(), 1)]);
+ }
+
+ throw $e;
}
- if ($definition->isPublic() || $definition->isPrivate()) {
+ if ($definition->isPublic()) {
continue;
}
// Remove private definition and schedule for replacement
@@ -77,7 +82,7 @@ public function process(ContainerBuilder $container)
*/
protected function processValue($value, $isRoot = false)
{
- if ($value instanceof Reference && isset($this->replacements[$referenceId = $this->container->normalizeId($value)])) {
+ if ($value instanceof Reference && isset($this->replacements[$referenceId = (string) $value])) {
// Perform the replacement
$newId = $this->replacements[$referenceId];
$value = new Reference($newId, $value->getInvalidBehavior());
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
index 065dbb4b..97b613f6 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveBindingsPass.php
@@ -12,6 +12,8 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
+use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -39,8 +41,39 @@ public function process(ContainerBuilder $container)
try {
parent::process($container);
- foreach ($this->unusedBindings as list($key, $serviceId)) {
- $message = sprintf('Unused binding "%s" in service "%s".', $key, $serviceId);
+ foreach ($this->unusedBindings as [$key, $serviceId, $bindingType, $file]) {
+ $argumentType = $argumentName = $message = null;
+
+ if (str_contains($key, ' ')) {
+ [$argumentType, $argumentName] = explode(' ', $key, 2);
+ } elseif ('$' === $key[0]) {
+ $argumentName = $key;
+ } else {
+ $argumentType = $key;
+ }
+
+ if ($argumentType) {
+ $message .= sprintf('of type "%s" ', $argumentType);
+ }
+
+ if ($argumentName) {
+ $message .= sprintf('named "%s" ', $argumentName);
+ }
+
+ if (BoundArgument::DEFAULTS_BINDING === $bindingType) {
+ $message .= 'under "_defaults"';
+ } elseif (BoundArgument::INSTANCEOF_BINDING === $bindingType) {
+ $message .= 'under "_instanceof"';
+ } else {
+ $message .= sprintf('for service "%s"', $serviceId);
+ }
+
+ if ($file) {
+ $message .= sprintf(' in file "%s"', $file);
+ }
+
+ $message = sprintf('A binding is configured for an argument %s, but no corresponding argument has been found. It may be unused and should be removed, or it may have a typo.', $message);
+
if ($this->errorMessages) {
$message .= sprintf("\nCould be related to%s:", 1 < \count($this->errorMessages) ? ' one of' : '');
}
@@ -61,9 +94,14 @@ public function process(ContainerBuilder $container)
*/
protected function processValue($value, $isRoot = false)
{
- if ($value instanceof TypedReference && $value->getType() === $this->container->normalizeId($value)) {
+ if ($value instanceof TypedReference && $value->getType() === (string) $value) {
// Already checked
$bindings = $this->container->getDefinition($this->currentId)->getBindings();
+ $name = $value->getName();
+
+ if (isset($name, $bindings[$name = $value.' $'.$name])) {
+ return $this->getBindingValue($bindings[$name]);
+ }
if (isset($bindings[$value->getType()])) {
return $this->getBindingValue($bindings[$value->getType()]);
@@ -76,21 +114,32 @@ protected function processValue($value, $isRoot = false)
return parent::processValue($value, $isRoot);
}
+ $bindingNames = [];
+
foreach ($bindings as $key => $binding) {
- list($bindingValue, $bindingId, $used) = $binding->getValues();
+ [$bindingValue, $bindingId, $used, $bindingType, $file] = $binding->getValues();
if ($used) {
$this->usedBindings[$bindingId] = true;
unset($this->unusedBindings[$bindingId]);
} elseif (!isset($this->usedBindings[$bindingId])) {
- $this->unusedBindings[$bindingId] = [$key, $this->currentId];
+ $this->unusedBindings[$bindingId] = [$key, $this->currentId, $bindingType, $file];
+ }
+
+ if (preg_match('/^(?:(?:array|bool|float|int|string|iterable|([^ $]++)) )\$/', $key, $m)) {
+ $bindingNames[substr($key, \strlen($m[0]))] = $binding;
}
- if (isset($key[0]) && '$' === $key[0]) {
+ if (!isset($m[1])) {
continue;
}
- if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition) {
- throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, an instance of "%s" or an instance of "%s", "%s" given.', $key, $this->currentId, Reference::class, Definition::class, \gettype($bindingValue)));
+ if (is_subclass_of($m[1], \UnitEnum::class)) {
+ $bindingNames[substr($key, \strlen($m[0]))] = $binding;
+ continue;
+ }
+
+ if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition && !$bindingValue instanceof TaggedIteratorArgument && !$bindingValue instanceof ServiceLocatorArgument) {
+ throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected "%s", "%s", "%s", "%s" or null, "%s" given.', $key, $this->currentId, Reference::class, Definition::class, TaggedIteratorArgument::class, ServiceLocatorArgument::class, \gettype($bindingValue)));
}
}
@@ -112,7 +161,7 @@ protected function processValue($value, $isRoot = false)
}
foreach ($calls as $i => $call) {
- list($method, $arguments) = $call;
+ [$method, $arguments] = $call;
if ($method instanceof \ReflectionFunctionAbstract) {
$reflectionMethod = $method;
@@ -132,19 +181,31 @@ protected function processValue($value, $isRoot = false)
continue;
}
+ $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter);
+
+ if ($typeHint && \array_key_exists($k = ltrim($typeHint, '\\').' $'.$parameter->name, $bindings)) {
+ $arguments[$key] = $this->getBindingValue($bindings[$k]);
+
+ continue;
+ }
+
if (\array_key_exists('$'.$parameter->name, $bindings)) {
$arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]);
continue;
}
- $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true);
+ if ($typeHint && '\\' === $typeHint[0] && isset($bindings[$typeHint = substr($typeHint, 1)])) {
+ $arguments[$key] = $this->getBindingValue($bindings[$typeHint]);
- if (!isset($bindings[$typeHint])) {
continue;
}
- $arguments[$key] = $this->getBindingValue($bindings[$typeHint]);
+ if (isset($bindingNames[$parameter->name])) {
+ $bindingKey = array_search($binding, $bindings, true);
+ $argumentType = substr($bindingKey, 0, strpos($bindingKey, ' '));
+ $this->errorMessages[] = sprintf('Did you forget to add the type "%s" to argument "$%s" of method "%s::%s()"?', $argumentType, $parameter->name, $reflectionMethod->class, $reflectionMethod->name);
+ }
}
if ($arguments !== $call[1]) {
@@ -154,7 +215,7 @@ protected function processValue($value, $isRoot = false)
}
if ($constructor) {
- list(, $arguments) = array_pop($calls);
+ [, $arguments] = array_pop($calls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
@@ -168,9 +229,12 @@ protected function processValue($value, $isRoot = false)
return parent::processValue($value, $isRoot);
}
+ /**
+ * @return mixed
+ */
private function getBindingValue(BoundArgument $binding)
{
- list($bindingValue, $bindingId) = $binding->getValues();
+ [$bindingValue, $bindingId] = $binding->getValues();
$this->usedBindings[$bindingId] = true;
unset($this->unusedBindings[$bindingId]);
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
index 539395a4..333480d6 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveChildDefinitionsPass.php
@@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
@@ -52,11 +53,9 @@ protected function processValue($value, $isRoot = false)
/**
* Resolves the definition.
*
- * @return Definition
- *
* @throws RuntimeException When the definition is invalid
*/
- private function resolveDefinition(ChildDefinition $definition)
+ private function resolveDefinition(ChildDefinition $definition): Definition
{
try {
return $this->doResolveDefinition($definition);
@@ -71,7 +70,7 @@ private function resolveDefinition(ChildDefinition $definition)
}
}
- private function doResolveDefinition(ChildDefinition $definition)
+ private function doResolveDefinition(ChildDefinition $definition): Definition
{
if (!$this->container->has($parent = $definition->getParent())) {
throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
@@ -102,9 +101,6 @@ private function doResolveDefinition(ChildDefinition $definition)
$def->setArguments($parentDef->getArguments());
$def->setMethodCalls($parentDef->getMethodCalls());
$def->setProperties($parentDef->getProperties());
- if ($parentDef->getAutowiringTypes(false)) {
- $def->setAutowiringTypes($parentDef->getAutowiringTypes(false));
- }
if ($parentDef->isDeprecated()) {
$def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
}
@@ -118,6 +114,8 @@ private function doResolveDefinition(ChildDefinition $definition)
$def->setBindings($definition->getBindings() + $parentDef->getBindings());
+ $def->setSynthetic($definition->isSynthetic());
+
// overwrite with values specified in the decorator
$changes = $definition->getChanges();
if (isset($changes['class'])) {
@@ -154,7 +152,7 @@ private function doResolveDefinition(ChildDefinition $definition)
if (null === $decoratedService) {
$def->setDecoratedService($decoratedService);
} else {
- $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
+ $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2], $decoratedService[3] ?? ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE);
}
}
@@ -162,7 +160,7 @@ private function doResolveDefinition(ChildDefinition $definition)
foreach ($definition->getArguments() as $k => $v) {
if (is_numeric($k)) {
$def->addArgument($v);
- } elseif (0 === strpos($k, 'index_')) {
+ } elseif (str_starts_with($k, 'index_')) {
$def->replaceArgument((int) substr($k, \strlen('index_')), $v);
} else {
$def->setArgument($k, $v);
@@ -179,10 +177,8 @@ private function doResolveDefinition(ChildDefinition $definition)
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
}
- // merge autowiring types
- foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
- $def->addAutowiringType($autowiringType);
- }
+ $def->addError($parentDef);
+ $def->addError($definition);
// these attributes are always taken from the child
$def->setAbstract($definition->isAbstract());
@@ -194,5 +190,3 @@ private function doResolveDefinition(ChildDefinition $definition)
return $def;
}
}
-
-class_alias(ResolveChildDefinitionsPass::class, ResolveDefinitionTemplatesPass::class);
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
index b1c1b4f8..e67a2a8e 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveClassPass.php
@@ -20,8 +20,6 @@
*/
class ResolveClassPass implements CompilerPassInterface
{
- private $changes = [];
-
/**
* {@inheritdoc}
*/
@@ -33,24 +31,10 @@ public function process(ContainerBuilder $container)
}
if (preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $id)) {
if ($definition instanceof ChildDefinition && !class_exists($id)) {
- throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
+ throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like an FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id));
}
- $this->changes[strtolower($id)] = $id;
$definition->setClass($id);
}
}
}
-
- /**
- * @internal
- *
- * @deprecated since 3.3, to be removed in 4.0.
- */
- public function getChanges()
- {
- $changes = $this->changes;
- $this->changes = [];
-
- return $changes;
- }
}
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
deleted file mode 100644
index 79fca8d5..00000000
--- a/vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Compiler;
-
-@trigger_error('The '.__NAMESPACE__.'\ResolveDefinitionTemplatesPass class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.', \E_USER_DEPRECATED);
-
-class_exists(ResolveChildDefinitionsPass::class);
-
-if (false) {
- /**
- * This definition decorates another definition.
- *
- * @author Johannes M. Schmitt
- *
- * @deprecated The ResolveDefinitionTemplatesPass class is deprecated since version 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.
- */
- class ResolveDefinitionTemplatesPass extends AbstractRecursivePass
- {
- }
-}
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
index 4e025113..bfdd91c4 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveHotPathPass.php
@@ -26,7 +26,7 @@ class ResolveHotPathPass extends AbstractRecursivePass
private $tagName;
private $resolvedIds = [];
- public function __construct($tagName = 'container.hot_path')
+ public function __construct(string $tagName = 'container.hot_path')
{
$this->tagName = $tagName;
}
@@ -55,7 +55,7 @@ protected function processValue($value, $isRoot = false)
if ($value instanceof Definition && $isRoot && (isset($this->resolvedIds[$this->currentId]) || !$value->hasTag($this->tagName) || $value->isDeprecated())) {
return $value->isDeprecated() ? $value->clearTag($this->tagName) : $value;
}
- if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = $this->container->normalizeId($value))) {
+ if ($value instanceof Reference && ContainerBuilder::IGNORE_ON_UNINITIALIZED_REFERENCE !== $value->getInvalidBehavior() && $this->container->has($id = (string) $value)) {
$definition = $this->container->findDefinition($id);
if (!$definition->hasTag($this->tagName) && !$definition->isDeprecated()) {
$this->resolvedIds[$id] = true;
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
index 6268ed9e..37ad3495 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.php
@@ -33,9 +33,12 @@ public function process(ContainerBuilder $container)
if ($definition->getArguments()) {
throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
}
- if ($definition->getMethodCalls()) {
- throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface));
- }
+ }
+
+ $tagsToKeep = [];
+
+ if ($container->hasParameter('container.behavior_describing_tags')) {
+ $tagsToKeep = $container->getParameter('container.behavior_describing_tags');
}
foreach ($container->getDefinitions() as $id => $definition) {
@@ -43,11 +46,15 @@ public function process(ContainerBuilder $container)
// don't apply "instanceof" to children: it will be applied to their parent
continue;
}
- $container->setDefinition($id, $this->processDefinition($container, $id, $definition));
+ $container->setDefinition($id, $this->processDefinition($container, $id, $definition, $tagsToKeep));
+ }
+
+ if ($container->hasParameter('container.behavior_describing_tags')) {
+ $container->getParameterBag()->remove('container.behavior_describing_tags');
}
}
- private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
+ private function processDefinition(ContainerBuilder $container, string $id, Definition $definition, array $tagsToKeep): Definition
{
$instanceofConditionals = $definition->getInstanceofConditionals();
$autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : [];
@@ -64,10 +71,12 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
$definition->setInstanceofConditionals([]);
$parent = $shared = null;
$instanceofTags = [];
+ $instanceofCalls = [];
+ $instanceofBindings = [];
$reflectionClass = null;
foreach ($conditionals as $interface => $instanceofDefs) {
- if ($interface !== $class && !(null === $reflectionClass ? $reflectionClass = ($container->getReflectionClass($class, false) ?: false) : $reflectionClass)) {
+ if ($interface !== $class && !($reflectionClass ?? $reflectionClass = $container->getReflectionClass($class, false) ?: false)) {
continue;
}
@@ -78,11 +87,19 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
foreach ($instanceofDefs as $key => $instanceofDef) {
/** @var ChildDefinition $instanceofDef */
$instanceofDef = clone $instanceofDef;
- $instanceofDef->setAbstract(true)->setParent($parent ?: 'abstract.instanceof.'.$id);
- $parent = 'instanceof.'.$interface.'.'.$key.'.'.$id;
+ $instanceofDef->setAbstract(true)->setParent($parent ?: '.abstract.instanceof.'.$id);
+ $parent = '.instanceof.'.$interface.'.'.$key.'.'.$id;
$container->setDefinition($parent, $instanceofDef);
$instanceofTags[] = $instanceofDef->getTags();
+ $instanceofBindings = $instanceofDef->getBindings() + $instanceofBindings;
+
+ foreach ($instanceofDef->getMethodCalls() as $methodCall) {
+ $instanceofCalls[] = $methodCall;
+ }
+
$instanceofDef->setTags([]);
+ $instanceofDef->setMethodCalls([]);
+ $instanceofDef->setBindings([]);
if (isset($instanceofDef->getChanges()['shared'])) {
$shared = $instanceofDef->isShared();
@@ -92,13 +109,14 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
if ($parent) {
$bindings = $definition->getBindings();
- $abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition);
+ $abstract = $container->setDefinition('.abstract.instanceof.'.$id, $definition);
// cast Definition to ChildDefinition
$definition->setBindings([]);
$definition = serialize($definition);
$definition = substr_replace($definition, '53', 2, 2);
$definition = substr_replace($definition, 'Child', 44, 0);
+ /** @var ChildDefinition $definition */
$definition = unserialize($definition);
$definition->setParent($parent);
@@ -106,19 +124,23 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
$definition->setShared($shared);
}
+ // Don't add tags to service decorators
$i = \count($instanceofTags);
while (0 <= --$i) {
foreach ($instanceofTags[$i] as $k => $v) {
- foreach ($v as $v) {
- if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) {
- continue;
+ if (null === $definition->getDecoratedService() || \in_array($k, $tagsToKeep, true)) {
+ foreach ($v as $v) {
+ if ($definition->hasTag($k) && \in_array($v, $definition->getTag($k))) {
+ continue;
+ }
+ $definition->addTag($k, $v);
}
- $definition->addTag($k, $v);
}
}
}
- $definition->setBindings($bindings);
+ $definition->setMethodCalls(array_merge($instanceofCalls, $definition->getMethodCalls()));
+ $definition->setBindings($bindings + $instanceofBindings);
// reset fields with "merge" behavior
$abstract
@@ -133,7 +155,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
return $definition;
}
- private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container)
+ private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container): array
{
// make each value an array of ChildDefinition
$conditionals = array_map(function ($childDef) { return [$childDef]; }, $autoconfiguredInstanceof);
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
index f1a1475a..948de421 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveInvalidReferencesPass.php
@@ -17,7 +17,9 @@
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
+use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\TypedReference;
/**
* Emulates the invalid behavior if the reference is not found within the
@@ -29,6 +31,7 @@ class ResolveInvalidReferencesPass implements CompilerPassInterface
{
private $container;
private $signalingException;
+ private $currentId;
/**
* Process the ContainerBuilder to resolve invalid references.
@@ -39,7 +42,9 @@ public function process(ContainerBuilder $container)
$this->signalingException = new RuntimeException('Invalid reference.');
try {
- $this->processValue($container->getDefinitions(), 1);
+ foreach ($container->getDefinitions() as $this->currentId => $definition) {
+ $this->processValue($definition);
+ }
} finally {
$this->container = $this->signalingException = null;
}
@@ -48,9 +53,11 @@ public function process(ContainerBuilder $container)
/**
* Processes arguments to determine invalid references.
*
+ * @return mixed
+ *
* @throws RuntimeException When an invalid reference is found
*/
- private function processValue($value, $rootLevel = 0, $level = 0)
+ private function processValue($value, int $rootLevel = 0, int $level = 0)
{
if ($value instanceof ServiceClosureArgument) {
$value->setValues($this->processValue($value->getValues(), 1, 1));
@@ -90,11 +97,29 @@ private function processValue($value, $rootLevel = 0, $level = 0)
$value = array_values($value);
}
} elseif ($value instanceof Reference) {
- if ($this->container->has($value)) {
+ if ($this->container->has($id = (string) $value)) {
return $value;
}
+
+ $currentDefinition = $this->container->getDefinition($this->currentId);
+
+ // resolve decorated service behavior depending on decorator service
+ if ($currentDefinition->innerServiceId === $id && ContainerInterface::NULL_ON_INVALID_REFERENCE === $currentDefinition->decorationOnInvalid) {
+ return null;
+ }
+
$invalidBehavior = $value->getInvalidBehavior();
+ if (ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior && $value instanceof TypedReference && !$this->container->has($id)) {
+ $e = new ServiceNotFoundException($id, $this->currentId);
+
+ // since the error message varies by $id and $this->currentId, so should the id of the dummy errored definition
+ $this->container->register($id = sprintf('.errored.%s.%s', $this->currentId, $id), $value->getType())
+ ->addError($e->getMessage());
+
+ return new TypedReference($id, $value->getType(), $value->getInvalidBehavior());
+ }
+
// resolve invalid behavior
if (ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$value = null;
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
index 225014f1..ab8ac1d0 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveNamedArgumentsPass.php
@@ -36,7 +36,7 @@ protected function processValue($value, $isRoot = false)
$calls[] = ['__construct', $value->getArguments()];
foreach ($calls as $i => $call) {
- list($method, $arguments) = $call;
+ [$method, $arguments] = $call;
$parameters = null;
$resolvedArguments = [];
@@ -53,10 +53,20 @@ protected function processValue($value, $isRoot = false)
$parameters = $r->getParameters();
}
+ if (isset($key[0]) && '$' !== $key[0] && !class_exists($key) && !interface_exists($key, false)) {
+ throw new InvalidArgumentException(sprintf('Invalid service "%s": did you forget to add the "$" prefix to argument "%s"?', $this->currentId, $key));
+ }
+
if (isset($key[0]) && '$' === $key[0]) {
foreach ($parameters as $j => $p) {
if ($key === '$'.$p->name) {
- $resolvedArguments[$j] = $argument;
+ if ($p->isVariadic() && \is_array($argument)) {
+ foreach ($argument as $variadicArgument) {
+ $resolvedArguments[$j++] = $variadicArgument;
+ }
+ } else {
+ $resolvedArguments[$j] = $argument;
+ }
continue 2;
}
@@ -88,7 +98,7 @@ protected function processValue($value, $isRoot = false)
}
}
- list(, $arguments) = array_pop($calls);
+ [, $arguments] = array_pop($calls);
if ($arguments !== $value->getArguments()) {
$value->setArguments($arguments);
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
index 2559dcf1..7764dde9 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveReferencesToAliasesPass.php
@@ -30,7 +30,9 @@ public function process(ContainerBuilder $container)
parent::process($container);
foreach ($container->getAliases() as $id => $alias) {
- $aliasId = $container->normalizeId($alias);
+ $aliasId = (string) $alias;
+ $this->currentId = $id;
+
if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) {
$container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate());
}
@@ -42,34 +44,39 @@ public function process(ContainerBuilder $container)
*/
protected function processValue($value, $isRoot = false)
{
- if ($value instanceof Reference) {
- $defId = $this->getDefinitionId($id = $this->container->normalizeId($value), $this->container);
-
- if ($defId !== $id) {
- return new Reference($defId, $value->getInvalidBehavior());
- }
+ if (!$value instanceof Reference) {
+ return parent::processValue($value, $isRoot);
}
- return parent::processValue($value);
+ $defId = $this->getDefinitionId($id = (string) $value, $this->container);
+
+ return $defId !== $id ? new Reference($defId, $value->getInvalidBehavior()) : $value;
}
- /**
- * Resolves an alias into a definition id.
- *
- * @param string $id The definition or alias id to resolve
- *
- * @return string The definition id with aliases resolved
- */
- private function getDefinitionId($id, ContainerBuilder $container)
+ private function getDefinitionId(string $id, ContainerBuilder $container): string
{
+ if (!$container->hasAlias($id)) {
+ return $id;
+ }
+
+ $alias = $container->getAlias($id);
+
+ if ($alias->isDeprecated()) {
+ $referencingDefinition = $container->hasDefinition($this->currentId) ? $container->getDefinition($this->currentId) : $container->getAlias($this->currentId);
+ if (!$referencingDefinition->isDeprecated()) {
+ @trigger_error(sprintf('%s. It is being referenced by the "%s" %s.', rtrim($alias->getDeprecationMessage($id), '. '), $this->currentId, $container->hasDefinition($this->currentId) ? 'service' : 'alias'), \E_USER_DEPRECATED);
+ }
+ }
+
$seen = [];
- while ($container->hasAlias($id)) {
+ do {
if (isset($seen[$id])) {
throw new ServiceCircularReferenceException($id, array_merge(array_keys($seen), [$id]));
}
+
$seen[$id] = true;
- $id = $container->normalizeId($container->getAlias($id));
- }
+ $id = (string) $container->getAlias($id);
+ } while ($container->hasAlias($id));
return $id;
}
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
index ccc80a44..399f3490 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveServiceSubscribersPass.php
@@ -14,6 +14,7 @@
use Psr\Container\ContainerInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Contracts\Service\ServiceProviderInterface;
/**
* Compiler pass to inject their service locator to service subscribers.
@@ -26,7 +27,7 @@ class ResolveServiceSubscribersPass extends AbstractRecursivePass
protected function processValue($value, $isRoot = false)
{
- if ($value instanceof Reference && $this->serviceLocator && ContainerInterface::class === $this->container->normalizeId($value)) {
+ if ($value instanceof Reference && $this->serviceLocator && \in_array((string) $value, [ContainerInterface::class, ServiceProviderInterface::class], true)) {
return new Reference($this->serviceLocator);
}
diff --git a/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php b/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
index 009cee9b..a4305722 100644
--- a/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ResolveTaggedIteratorArgumentPass.php
@@ -31,7 +31,7 @@ protected function processValue($value, $isRoot = false)
return parent::processValue($value, $isRoot);
}
- $value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container));
+ $value->setValues($this->findAndSortTaggedServices($value, $this->container));
return $value;
}
diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
index a7427c5a..5fdbe568 100644
--- a/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
+++ b/vendor/symfony/dependency-injection/Compiler/ServiceLocatorTagPass.php
@@ -13,6 +13,7 @@
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -26,8 +27,18 @@
*/
final class ServiceLocatorTagPass extends AbstractRecursivePass
{
+ use PriorityTaggedServiceTrait;
+
protected function processValue($value, $isRoot = false)
{
+ if ($value instanceof ServiceLocatorArgument) {
+ if ($value->getTaggedIteratorArgument()) {
+ $value->setValues($this->findAndSortTaggedServices($value->getTaggedIteratorArgument(), $this->container));
+ }
+
+ return self::register($this->container, $value->getValues());
+ }
+
if (!$value instanceof Definition || !$value->hasTag('container.service_locator')) {
return parent::processValue($value, $isRoot);
}
@@ -65,7 +76,7 @@ protected function processValue($value, $isRoot = false)
$value->setArguments($arguments);
- $id = 'service_locator.'.ContainerBuilder::hash($value);
+ $id = '.service_locator.'.ContainerBuilder::hash($value);
if ($isRoot) {
if ($id !== $this->currentId) {
@@ -82,11 +93,8 @@ protected function processValue($value, $isRoot = false)
/**
* @param Reference[] $refMap
- * @param string|null $callerId
- *
- * @return Reference
*/
- public static function register(ContainerBuilder $container, array $refMap, $callerId = null)
+ public static function register(ContainerBuilder $container, array $refMap, string $callerId = null): Reference
{
foreach ($refMap as $id => $ref) {
if (!$ref instanceof Reference) {
@@ -105,7 +113,7 @@ public static function register(ContainerBuilder $container, array $refMap, $cal
$locator->setBindings($container->getDefinition($callerId)->getBindings());
}
- if (!$container->hasDefinition($id = 'service_locator.'.ContainerBuilder::hash($locator))) {
+ if (!$container->hasDefinition($id = '.service_locator.'.ContainerBuilder::hash($locator))) {
$container->setDefinition($id, $locator);
}
@@ -117,6 +125,7 @@ public static function register(ContainerBuilder $container, array $refMap, $cal
$container->register($id .= '.'.$callerId, ServiceLocator::class)
->setPublic(false)
->setFactory([new Reference($locatorId), 'withContext'])
+ ->addTag('container.service_locator_context', ['id' => $callerId])
->addArgument($callerId)
->addArgument(new Reference('service_container'));
}
diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
index e419e297..308abc65 100644
--- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
+++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraph.php
@@ -21,7 +21,7 @@
*
* @author Johannes M. Schmitt
*
- * @final since version 3.4
+ * @final
*/
class ServiceReferenceGraph
{
@@ -30,14 +30,7 @@ class ServiceReferenceGraph
*/
private $nodes = [];
- /**
- * Checks if the graph has a specific node.
- *
- * @param string $id Id to check
- *
- * @return bool
- */
- public function hasNode($id)
+ public function hasNode(string $id): bool
{
return isset($this->nodes[$id]);
}
@@ -45,13 +38,9 @@ public function hasNode($id)
/**
* Gets a node by identifier.
*
- * @param string $id The id to retrieve
- *
- * @return ServiceReferenceGraphNode
- *
* @throws InvalidArgumentException if no node matches the supplied identifier
*/
- public function getNode($id)
+ public function getNode(string $id): ServiceReferenceGraphNode
{
if (!isset($this->nodes[$id])) {
throw new InvalidArgumentException(sprintf('There is no node with id "%s".', $id));
@@ -65,7 +54,7 @@ public function getNode($id)
*
* @return ServiceReferenceGraphNode[]
*/
- public function getNodes()
+ public function getNodes(): array
{
return $this->nodes;
}
@@ -83,19 +72,9 @@ public function clear()
/**
* Connects 2 nodes together in the Graph.
- *
- * @param string $sourceId
- * @param mixed $sourceValue
- * @param string $destId
- * @param mixed $destValue
- * @param string $reference
*/
- public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false, bool $weak = false, bool $byConstructor = false*/)
+ public function connect(?string $sourceId, $sourceValue, ?string $destId, $destValue = null, $reference = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false)
{
- $lazy = \func_num_args() >= 6 ? func_get_arg(5) : false;
- $weak = \func_num_args() >= 7 ? func_get_arg(6) : false;
- $byConstructor = \func_num_args() >= 8 ? func_get_arg(7) : false;
-
if (null === $sourceId || null === $destId) {
return;
}
@@ -108,15 +87,7 @@ public function connect($sourceId, $sourceValue, $destId, $destValue = null, $re
$destNode->addInEdge($edge);
}
- /**
- * Creates a graph node.
- *
- * @param string $id
- * @param mixed $value
- *
- * @return ServiceReferenceGraphNode
- */
- private function createNode($id, $value)
+ private function createNode(string $id, $value): ServiceReferenceGraphNode
{
if (isset($this->nodes[$id]) && $this->nodes[$id]->getValue() === $value) {
return $this->nodes[$id];
diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
index 911e7a5f..98614560 100644
--- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
+++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphEdge.php
@@ -27,13 +27,7 @@ class ServiceReferenceGraphEdge
private $weak;
private $byConstructor;
- /**
- * @param mixed $value
- * @param bool $lazy
- * @param bool $weak
- * @param bool $byConstructor
- */
- public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false, $weak = false, $byConstructor = false)
+ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, bool $lazy = false, bool $weak = false, bool $byConstructor = false)
{
$this->sourceNode = $sourceNode;
$this->destNode = $destNode;
@@ -46,7 +40,7 @@ public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceRefere
/**
* Returns the value of the edge.
*
- * @return string
+ * @return mixed
*/
public function getValue()
{
diff --git a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
index 50140b5f..fec14242 100644
--- a/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
+++ b/vendor/symfony/dependency-injection/Compiler/ServiceReferenceGraphNode.php
@@ -32,7 +32,7 @@ class ServiceReferenceGraphNode
* @param string $id The node identifier
* @param mixed $value The node value
*/
- public function __construct($id, $value)
+ public function __construct(string $id, $value)
{
$this->id = $id;
$this->value = $value;
diff --git a/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php b/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php
new file mode 100644
index 00000000..cae01c61
--- /dev/null
+++ b/vendor/symfony/dependency-injection/Compiler/ValidateEnvPlaceholdersPass.php
@@ -0,0 +1,120 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Component\DependencyInjection\Compiler;
+
+use Symfony\Component\Config\Definition\BaseNode;
+use Symfony\Component\Config\Definition\Exception\TreeWithoutRootNodeException;
+use Symfony\Component\Config\Definition\Processor;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
+use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
+use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+
+/**
+ * Validates environment variable placeholders used in extension configuration with dummy values.
+ *
+ * @author Roland Franssen
+ */
+class ValidateEnvPlaceholdersPass implements CompilerPassInterface
+{
+ private const TYPE_FIXTURES = ['array' => [], 'bool' => false, 'float' => 0.0, 'int' => 0, 'string' => ''];
+
+ private $extensionConfig = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $this->extensionConfig = [];
+
+ if (!class_exists(BaseNode::class) || !$extensions = $container->getExtensions()) {
+ return;
+ }
+
+ $resolvingBag = $container->getParameterBag();
+ if (!$resolvingBag instanceof EnvPlaceholderParameterBag) {
+ return;
+ }
+
+ $defaultBag = new ParameterBag($resolvingBag->all());
+ $envTypes = $resolvingBag->getProvidedTypes();
+ try {
+ foreach ($resolvingBag->getEnvPlaceholders() + $resolvingBag->getUnusedEnvPlaceholders() as $env => $placeholders) {
+ $values = [];
+ if (false === $i = strpos($env, ':')) {
+ $default = $defaultBag->has("env($env)") ? $defaultBag->get("env($env)") : self::TYPE_FIXTURES['string'];
+ $defaultType = null !== $default ? self::getType($default) : 'string';
+ $values[$defaultType] = $default;
+ } else {
+ $prefix = substr($env, 0, $i);
+ foreach ($envTypes[$prefix] ?? ['string'] as $type) {
+ $values[$type] = self::TYPE_FIXTURES[$type] ?? null;
+ }
+ }
+ foreach ($placeholders as $placeholder) {
+ BaseNode::setPlaceholder($placeholder, $values);
+ }
+ }
+
+ $processor = new Processor();
+
+ foreach ($extensions as $name => $extension) {
+ if (!$extension instanceof ConfigurationExtensionInterface || !$config = array_filter($container->getExtensionConfig($name))) {
+ // this extension has no semantic configuration or was not called
+ continue;
+ }
+
+ $config = $resolvingBag->resolveValue($config);
+
+ if (null === $configuration = $extension->getConfiguration($config, $container)) {
+ continue;
+ }
+
+ try {
+ $this->extensionConfig[$name] = $processor->processConfiguration($configuration, $config);
+ } catch (TreeWithoutRootNodeException $e) {
+ }
+ }
+ } finally {
+ BaseNode::resetPlaceholders();
+ }
+
+ $resolvingBag->clearUnusedEnvPlaceholders();
+ }
+
+ /**
+ * @internal
+ */
+ public function getExtensionConfig(): array
+ {
+ try {
+ return $this->extensionConfig;
+ } finally {
+ $this->extensionConfig = [];
+ }
+ }
+
+ private static function getType($value): string
+ {
+ switch ($type = \gettype($value)) {
+ case 'boolean':
+ return 'bool';
+ case 'double':
+ return 'float';
+ case 'integer':
+ return 'int';
+ }
+
+ return $type;
+ }
+}
diff --git a/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php b/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php
deleted file mode 100644
index 68c1e3f6..00000000
--- a/vendor/symfony/dependency-injection/Config/AutowireServiceResource.php
+++ /dev/null
@@ -1,88 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection\Config;
-
-@trigger_error('The '.__NAMESPACE__.'\AutowireServiceResource class is deprecated since Symfony 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', \E_USER_DEPRECATED);
-
-use Symfony\Component\Config\Resource\SelfCheckingResourceInterface;
-use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
-
-/**
- * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.
- */
-class AutowireServiceResource implements SelfCheckingResourceInterface, \Serializable
-{
- private $class;
- private $filePath;
- private $autowiringMetadata = [];
-
- public function __construct($class, $path, array $autowiringMetadata)
- {
- $this->class = $class;
- $this->filePath = $path;
- $this->autowiringMetadata = $autowiringMetadata;
- }
-
- public function isFresh($timestamp)
- {
- if (!file_exists($this->filePath)) {
- return false;
- }
-
- // has the file *not* been modified? Definitely fresh
- if (@filemtime($this->filePath) <= $timestamp) {
- return true;
- }
-
- try {
- $reflectionClass = new \ReflectionClass($this->class);
- } catch (\ReflectionException $e) {
- // the class does not exist anymore!
- return false;
- }
-
- return (array) $this === (array) AutowirePass::createResourceForClass($reflectionClass);
- }
-
- public function __toString()
- {
- return 'service.autowire.'.$this->class;
- }
-
- /**
- * @internal
- */
- public function serialize()
- {
- return serialize([$this->class, $this->filePath, $this->autowiringMetadata]);
- }
-
- /**
- * @internal
- */
- public function unserialize($serialized)
- {
- if (\PHP_VERSION_ID >= 70000) {
- list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized, ['allowed_classes' => false]);
- } else {
- list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized);
- }
- }
-
- /**
- * @deprecated Implemented for compatibility with Symfony 2.8
- */
- public function getResource()
- {
- return $this->filePath;
- }
-}
diff --git a/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php b/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
index 7560c335..d2a74eb5 100644
--- a/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
+++ b/vendor/symfony/dependency-injection/Config/ContainerParametersResource.php
@@ -17,8 +17,10 @@
* Tracks container parameters.
*
* @author Maxime Steinhausser
+ *
+ * @final since Symfony 4.3
*/
-class ContainerParametersResource implements ResourceInterface, \Serializable
+class ContainerParametersResource implements ResourceInterface
{
private $parameters;
@@ -30,30 +32,11 @@ public function __construct(array $parameters)
$this->parameters = $parameters;
}
- /**
- * {@inheritdoc}
- */
public function __toString()
{
return 'container_parameters_'.md5(serialize($this->parameters));
}
- /**
- * @internal
- */
- public function serialize()
- {
- return serialize($this->parameters);
- }
-
- /**
- * @internal
- */
- public function unserialize($serialized)
- {
- $this->parameters = unserialize($serialized);
- }
-
/**
* @return array Tracked parameters
*/
diff --git a/vendor/symfony/dependency-injection/Container.php b/vendor/symfony/dependency-injection/Container.php
index e9d53023..789c8f72 100644
--- a/vendor/symfony/dependency-injection/Container.php
+++ b/vendor/symfony/dependency-injection/Container.php
@@ -11,14 +11,22 @@
namespace Symfony\Component\DependencyInjection;
+use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocator as ArgumentServiceLocator;
use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
+use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
+use Symfony\Contracts\Service\ResetInterface;
+
+// Help opcache.preload discover always-needed symbols
+class_exists(RewindableGenerator::class);
+class_exists(ArgumentServiceLocator::class);
/**
* Container is a dependency injection container.
@@ -41,31 +49,22 @@ class Container implements ResettableContainerInterface
{
protected $parameterBag;
protected $services = [];
+ protected $privates = [];
protected $fileMap = [];
protected $methodMap = [];
+ protected $factories = [];
protected $aliases = [];
protected $loading = [];
protected $resolving = [];
protected $syntheticIds = [];
- /**
- * @internal
- */
- protected $privates = [];
-
- /**
- * @internal
- */
- protected $normalizedIds = [];
-
- private $underscoreMap = ['_' => '', '.' => '_', '\\' => '_'];
private $envCache = [];
private $compiled = false;
private $getEnv;
public function __construct(ParameterBagInterface $parameterBag = null)
{
- $this->parameterBag = $parameterBag ?: new EnvPlaceholderParameterBag();
+ $this->parameterBag = $parameterBag ?? new EnvPlaceholderParameterBag();
}
/**
@@ -95,20 +94,6 @@ public function isCompiled()
return $this->compiled;
}
- /**
- * Returns true if the container parameter bag are frozen.
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- *
- * @return bool true if the container parameter bag are frozen, false otherwise
- */
- public function isFrozen()
- {
- @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), \E_USER_DEPRECATED);
-
- return $this->parameterBag instanceof FrozenParameterBag;
- }
-
/**
* Gets the service container parameter bag.
*
@@ -124,7 +109,7 @@ public function getParameterBag()
*
* @param string $name The parameter name
*
- * @return mixed The parameter value
+ * @return array|bool|string|int|float|null
*
* @throws InvalidArgumentException if the parameter is not defined
*/
@@ -148,8 +133,8 @@ public function hasParameter($name)
/**
* Sets a parameter.
*
- * @param string $name The parameter name
- * @param mixed $value The parameter value
+ * @param string $name The parameter name
+ * @param array|bool|string|int|float|null $value The parameter value
*/
public function setParameter($name, $value)
{
@@ -174,27 +159,20 @@ public function set($id, $service)
$initialize();
}
- $id = $this->normalizeId($id);
-
if ('service_container' === $id) {
throw new InvalidArgumentException('You cannot set service "service_container".');
}
- if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
- if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) {
+ if (!(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
+ if (isset($this->syntheticIds[$id]) || !isset($this->getRemovedIds()[$id])) {
// no-op
} elseif (null === $service) {
- @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
- unset($this->privates[$id]);
+ throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot unset it.', $id));
} else {
- @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
+ throw new InvalidArgumentException(sprintf('The "%s" service is private, you cannot replace it.', $id));
}
} elseif (isset($this->services[$id])) {
- if (null === $service) {
- @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
- } else {
- @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
- }
+ throw new InvalidArgumentException(sprintf('The "%s" service is already initialized, you cannot replace it.', $id));
}
if (isset($this->aliases[$id])) {
@@ -219,47 +197,22 @@ public function set($id, $service)
*/
public function has($id)
{
- for ($i = 2;;) {
- if (isset($this->privates[$id])) {
- @trigger_error(sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), \E_USER_DEPRECATED);
- }
- if (isset($this->aliases[$id])) {
- $id = $this->aliases[$id];
- }
- if (isset($this->services[$id])) {
- return true;
- }
- if ('service_container' === $id) {
- return true;
- }
-
- if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
- return true;
- }
-
- if (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
- $id = $normalizedId;
- continue;
- }
-
- // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
- // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
- if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) {
- @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
-
- return true;
- }
-
- return false;
+ if (isset($this->aliases[$id])) {
+ $id = $this->aliases[$id];
+ }
+ if (isset($this->services[$id])) {
+ return true;
}
+ if ('service_container' === $id) {
+ return true;
+ }
+
+ return isset($this->fileMap[$id]) || isset($this->methodMap[$id]);
}
/**
* Gets a service.
*
- * If a service is defined both through a set() method and
- * with a get{$id}Service() method, the former has always precedence.
- *
* @param string $id The service identifier
* @param int $invalidBehavior The behavior when the service does not exist
*
@@ -273,57 +226,42 @@ public function has($id)
*/
public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERENCE */ 1)
{
- // Attempt to retrieve the service by checking first aliases then
- // available services. Service IDs are case insensitive, however since
- // this method can be called thousands of times during a request, avoid
- // calling $this->normalizeId($id) unless necessary.
- for ($i = 2;;) {
- if (isset($this->privates[$id])) {
- @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), \E_USER_DEPRECATED);
- }
- if (isset($this->aliases[$id])) {
- $id = $this->aliases[$id];
- }
+ $service = $this->services[$id]
+ ?? $this->services[$id = $this->aliases[$id] ?? $id]
+ ?? ('service_container' === $id ? $this : ($this->factories[$id] ?? [$this, 'make'])($id, $invalidBehavior));
- // Re-use shared service instance if it exists.
- if (isset($this->services[$id])) {
- return $this->services[$id];
- }
- if ('service_container' === $id) {
- return $this;
- }
-
- if (isset($this->loading[$id])) {
- throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id]));
- }
-
- $this->loading[$id] = true;
+ if (!\is_object($service) && null !== $service) {
+ @trigger_error(sprintf('Non-object services are deprecated since Symfony 4.4, please fix the "%s" service which is of type "%s" right now.', $id, \gettype($service)), \E_USER_DEPRECATED);
+ }
- try {
- if (isset($this->fileMap[$id])) {
- return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
- } elseif (isset($this->methodMap[$id])) {
- return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
- } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) {
- unset($this->loading[$id]);
- $id = $normalizedId;
- continue;
- } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) {
- // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
- // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
- @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
+ return $service;
+ }
- return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$method}();
- }
+ /**
+ * Creates a service.
+ *
+ * As a separate method to allow "get()" to use the really fast `??` operator.
+ */
+ private function make(string $id, int $invalidBehavior)
+ {
+ if (isset($this->loading[$id])) {
+ throw new ServiceCircularReferenceException($id, array_merge(array_keys($this->loading), [$id]));
+ }
- break;
- } catch (\Exception $e) {
- unset($this->services[$id]);
+ $this->loading[$id] = true;
- throw $e;
- } finally {
- unset($this->loading[$id]);
+ try {
+ if (isset($this->fileMap[$id])) {
+ return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->load($this->fileMap[$id]);
+ } elseif (isset($this->methodMap[$id])) {
+ return /* self::IGNORE_ON_UNINITIALIZED_REFERENCE */ 4 === $invalidBehavior ? null : $this->{$this->methodMap[$id]}();
}
+ } catch (\Exception $e) {
+ unset($this->services[$id]);
+
+ throw $e;
+ } finally {
+ unset($this->loading[$id]);
}
if (/* self::EXCEPTION_ON_INVALID_REFERENCE */ 1 === $invalidBehavior) {
@@ -339,14 +277,19 @@ public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERE
$alternatives = [];
foreach ($this->getServiceIds() as $knownId) {
+ if ('' === $knownId || '.' === $knownId[0]) {
+ continue;
+ }
$lev = levenshtein($id, $knownId);
- if ($lev <= \strlen($id) / 3 || false !== strpos($knownId, $id)) {
+ if ($lev <= \strlen($id) / 3 || str_contains($knownId, $id)) {
$alternatives[] = $knownId;
}
}
throw new ServiceNotFoundException($id, null, null, $alternatives);
}
+
+ return null;
}
/**
@@ -358,12 +301,6 @@ public function get($id, $invalidBehavior = /* self::EXCEPTION_ON_INVALID_REFERE
*/
public function initialized($id)
{
- $id = $this->normalizeId($id);
-
- if (isset($this->privates[$id])) {
- @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), \E_USER_DEPRECATED);
- }
-
if (isset($this->aliases[$id])) {
$id = $this->aliases[$id];
}
@@ -380,7 +317,18 @@ public function initialized($id)
*/
public function reset()
{
- $this->services = [];
+ $services = $this->services + $this->privates;
+ $this->services = $this->factories = $this->privates = [];
+
+ foreach ($services as $service) {
+ try {
+ if ($service instanceof ResetInterface) {
+ $service->reset();
+ }
+ } catch (\Throwable $e) {
+ continue;
+ }
+ }
}
/**
@@ -390,22 +338,7 @@ public function reset()
*/
public function getServiceIds()
{
- $ids = [];
-
- if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) {
- // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder,
- // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper)
- @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', \E_USER_DEPRECATED);
-
- foreach (get_class_methods($this) as $method) {
- if (preg_match('/^get(.+)Service$/', $method, $match)) {
- $ids[] = self::underscore($match[1]);
- }
- }
- }
- $ids[] = 'service_container';
-
- return array_map('strval', array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->aliases), array_keys($this->services))));
+ return array_map('strval', array_unique(array_merge(['service_container'], array_keys($this->fileMap), array_keys($this->methodMap), array_keys($this->aliases), array_keys($this->services))));
}
/**
@@ -471,9 +404,7 @@ protected function getEnv($name)
$this->set($id, new ServiceLocator([]));
}
if (!$this->getEnv) {
- $this->getEnv = new \ReflectionMethod($this, __FUNCTION__);
- $this->getEnv->setAccessible(true);
- $this->getEnv = $this->getEnv->getClosure($this);
+ $this->getEnv = \Closure::fromCallable([$this, 'getEnv']);
}
$processors = $this->get($id);
@@ -495,29 +426,32 @@ protected function getEnv($name)
}
/**
- * Returns the case sensitive id used at registration time.
- *
- * @param string $id
+ * @param string|false $registry
+ * @param string|bool $load
*
- * @return string
+ * @return mixed
*
* @internal
*/
- public function normalizeId($id)
+ final protected function getService($registry, string $id, ?string $method, $load)
{
- if (!\is_string($id)) {
- $id = (string) $id;
+ if ('service_container' === $id) {
+ return $this;
}
- if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) {
- $normalizedId = $this->normalizedIds[$normalizedId];
- if ($id !== $normalizedId) {
- @trigger_error(sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.', $id, $normalizedId), \E_USER_DEPRECATED);
- }
- } else {
- $normalizedId = $this->normalizedIds[$normalizedId] = $id;
+ if (\is_string($load)) {
+ throw new RuntimeException($load);
+ }
+ if (null === $method) {
+ return false !== $registry ? $this->{$registry}[$id] ?? null : null;
+ }
+ if (false !== $registry) {
+ return $this->{$registry}[$id] ?? $this->{$registry}[$id] = $load ? $this->load($method) : $this->{$method}();
+ }
+ if (!$load) {
+ return $this->{$method}();
}
- return $normalizedId;
+ return ($factory = $this->factories[$id] ?? $this->factories['service_container'][$id] ?? null) ? $factory() : $this->load($method);
}
private function __clone()
diff --git a/vendor/symfony/dependency-injection/ContainerBuilder.php b/vendor/symfony/dependency-injection/ContainerBuilder.php
index 97617cb0..f97a5740 100644
--- a/vendor/symfony/dependency-injection/ContainerBuilder.php
+++ b/vendor/symfony/dependency-injection/ContainerBuilder.php
@@ -23,6 +23,8 @@
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocator;
+use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
use Symfony\Component\DependencyInjection\Compiler\Compiler;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@@ -39,7 +41,6 @@
use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
-use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher;
use Symfony\Component\ExpressionLanguage\Expression;
use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
@@ -125,7 +126,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
private $removedBindingIds = [];
- private static $internalTypes = [
+ private const INTERNAL_TYPES = [
'int' => true,
'float' => true,
'string' => true,
@@ -143,7 +144,7 @@ public function __construct(ParameterBagInterface $parameterBag = null)
{
parent::__construct($parameterBag);
- $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface');
+ $this->trackResources = interface_exists(ResourceInterface::class);
$this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true));
$this->setAlias(PsrContainerInterface::class, new Alias('service_container', false));
$this->setAlias(ContainerInterface::class, new Alias('service_container', false));
@@ -325,39 +326,20 @@ public function addObjectResource($object)
return $this;
}
- /**
- * Adds the given class hierarchy as resources.
- *
- * @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0. Use addObjectResource() or getReflectionClass() instead.
- */
- public function addClassResource(\ReflectionClass $class)
- {
- @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the addObjectResource() or the getReflectionClass() method instead.', \E_USER_DEPRECATED);
-
- return $this->addObjectResource($class->name);
- }
-
/**
* Retrieves the requested reflection class and registers it for resource tracking.
*
- * @param string $class
- * @param bool $throw
- *
- * @return \ReflectionClass|null
- *
* @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true
*
* @final
*/
- public function getReflectionClass($class, $throw = true)
+ public function getReflectionClass(?string $class, bool $throw = true): ?\ReflectionClass
{
if (!$class = $this->getParameterBag()->resolveValue($class)) {
return null;
}
- if (isset(self::$internalTypes[$class])) {
+ if (isset(self::INTERNAL_TYPES[$class])) {
return null;
}
@@ -380,7 +362,7 @@ public function getReflectionClass($class, $throw = true)
if ($this->trackResources) {
if (!$classReflector) {
- $this->addResource($resource ?: new ClassExistenceResource($class, false));
+ $this->addResource($resource ?? new ClassExistenceResource($class, false));
} elseif (!$classReflector->isInternal()) {
$path = $classReflector->getFileName();
@@ -401,11 +383,9 @@ public function getReflectionClass($class, $throw = true)
* @param bool|string $trackContents Whether to track contents of the given resource. If a string is passed,
* it will be used as pattern for tracking contents of the requested directory
*
- * @return bool
- *
* @final
*/
- public function fileExists($path, $trackContents = true)
+ public function fileExists(string $path, $trackContents = true): bool
{
$exists = file_exists($path);
@@ -463,27 +443,13 @@ public function loadFromExtension($extension, array $values = null)
/**
* Adds a compiler pass.
*
- * @param CompilerPassInterface $pass A compiler pass
- * @param string $type The type of compiler pass
- * @param int $priority Used to sort the passes
+ * @param string $type The type of compiler pass
+ * @param int $priority Used to sort the passes
*
* @return $this
*/
- public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/)
+ public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0)
{
- if (\func_num_args() >= 3) {
- $priority = func_get_arg(2);
- } else {
- if (__CLASS__ !== static::class) {
- $r = new \ReflectionMethod($this, __FUNCTION__);
- if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
- @trigger_error(sprintf('Method %s() will have a third `int $priority = 0` argument in version 4.0. Not defining it is deprecated since Symfony 3.2.', __METHOD__), \E_USER_DEPRECATED);
- }
- }
-
- $priority = 0;
- }
-
$this->getCompiler()->addPass($pass, $type, $priority);
$this->addObjectResource($pass);
@@ -525,7 +491,11 @@ public function getCompiler()
*/
public function set($id, $service)
{
- $id = $this->normalizeId($id);
+ if (!\is_object($service) && null !== $service) {
+ @trigger_error(sprintf('Non-object services are deprecated since Symfony 4.4, setting the "%s" service to a value of type "%s" should be avoided.', $id, \gettype($service)), \E_USER_DEPRECATED);
+ }
+
+ $id = (string) $id;
if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) {
// setting a synthetic service on a compiled container is alright
@@ -544,7 +514,7 @@ public function set($id, $service)
*/
public function removeDefinition($id)
{
- if (isset($this->definitions[$id = $this->normalizeId($id)])) {
+ if (isset($this->definitions[$id = (string) $id])) {
unset($this->definitions[$id]);
$this->removedIds[$id] = true;
}
@@ -559,7 +529,7 @@ public function removeDefinition($id)
*/
public function has($id)
{
- $id = $this->normalizeId($id);
+ $id = (string) $id;
return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id);
}
@@ -581,17 +551,21 @@ public function has($id)
*/
public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
{
- if ($this->isCompiled() && isset($this->removedIds[$id = $this->normalizeId($id)])) {
- @trigger_error(sprintf('Fetching the "%s" private service or alias is deprecated since Symfony 3.4 and will fail in 4.0. Make it public instead.', $id), \E_USER_DEPRECATED);
+ if ($this->isCompiled() && isset($this->removedIds[$id = (string) $id]) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE >= $invalidBehavior) {
+ return parent::get($id);
+ }
+
+ $service = $this->doGet($id, $invalidBehavior);
+
+ if (!\is_object($service) && null !== $service) {
+ @trigger_error(sprintf('Non-object services are deprecated since Symfony 4.4, please fix the "%s" service which is of type "%s" right now.', $id, \gettype($service)), \E_USER_DEPRECATED);
}
- return $this->doGet($id, $invalidBehavior);
+ return $service;
}
- private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, $isConstructorArgument = false)
+ private function doGet(string $id, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = null, bool $isConstructorArgument = false)
{
- $id = $this->normalizeId($id);
-
if (isset($inlineServices[$id])) {
return $inlineServices[$id];
}
@@ -613,19 +587,29 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
}
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
- return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices, $isConstructorArgument);
+ $alias = $this->aliasDefinitions[$id];
+
+ if ($alias->isDeprecated()) {
+ @trigger_error($alias->getDeprecationMessage($id), \E_USER_DEPRECATED);
+ }
+
+ return $this->doGet((string) $alias, $invalidBehavior, $inlineServices, $isConstructorArgument);
}
try {
$definition = $this->getDefinition($id);
} catch (ServiceNotFoundException $e) {
- if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
+ if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE < $invalidBehavior) {
return null;
}
throw $e;
}
+ if ($definition->hasErrors() && $e = $definition->getErrors()) {
+ throw new RuntimeException(reset($e));
+ }
+
if ($isConstructorArgument) {
$this->loading[$id] = true;
}
@@ -760,19 +744,8 @@ public function prependExtensionConfig($name, array $config)
* Set to "true" when you want to use the current ContainerBuilder
* directly, keep to "false" when the container is dumped instead.
*/
- public function compile(/*$resolveEnvPlaceholders = false*/)
+ public function compile(bool $resolveEnvPlaceholders = false)
{
- if (1 <= \func_num_args()) {
- $resolveEnvPlaceholders = func_get_arg(0);
- } else {
- if (__CLASS__ !== static::class) {
- $r = new \ReflectionMethod($this, __FUNCTION__);
- if (__CLASS__ !== $r->getDeclaringClass()->getName() && (1 > $r->getNumberOfParameters() || 'resolveEnvPlaceholders' !== $r->getParameters()[0]->name)) {
- @trigger_error(sprintf('The %s::compile() method expects a first "$resolveEnvPlaceholders" argument since Symfony 3.3. It will be made mandatory in 4.0.', static::class), \E_USER_DEPRECATED);
- }
- }
- $resolveEnvPlaceholders = false;
- }
$compiler = $this->getCompiler();
if ($this->trackResources) {
@@ -863,14 +836,14 @@ public function setAliases(array $aliases)
*/
public function setAlias($alias, $id)
{
- $alias = $this->normalizeId($alias);
+ $alias = (string) $alias;
- if ('' === $alias || '\\' === substr($alias, -1) || \strlen($alias) !== strcspn($alias, "\0\r\n'")) {
+ if ('' === $alias || '\\' === $alias[-1] || \strlen($alias) !== strcspn($alias, "\0\r\n'")) {
throw new InvalidArgumentException(sprintf('Invalid alias id: "%s".', $alias));
}
if (\is_string($id)) {
- $id = new Alias($this->normalizeId($id));
+ $id = new Alias($id);
} elseif (!$id instanceof Alias) {
throw new InvalidArgumentException('$id must be a string, or an Alias object.');
}
@@ -891,7 +864,7 @@ public function setAlias($alias, $id)
*/
public function removeAlias($alias)
{
- if (isset($this->aliasDefinitions[$alias = $this->normalizeId($alias)])) {
+ if (isset($this->aliasDefinitions[$alias = (string) $alias])) {
unset($this->aliasDefinitions[$alias]);
$this->removedIds[$alias] = true;
}
@@ -906,12 +879,10 @@ public function removeAlias($alias)
*/
public function hasAlias($id)
{
- return isset($this->aliasDefinitions[$this->normalizeId($id)]);
+ return isset($this->aliasDefinitions[$id = (string) $id]);
}
/**
- * Gets all defined aliases.
- *
* @return Alias[] An array of aliases
*/
public function getAliases()
@@ -930,7 +901,7 @@ public function getAliases()
*/
public function getAlias($id)
{
- $id = $this->normalizeId($id);
+ $id = (string) $id;
if (!isset($this->aliasDefinitions[$id])) {
throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id));
@@ -1007,8 +978,7 @@ public function getDefinitions()
/**
* Sets a service definition.
*
- * @param string $id The service identifier
- * @param Definition $definition A Definition instance
+ * @param string $id The service identifier
*
* @return Definition the service definition
*
@@ -1020,9 +990,9 @@ public function setDefinition($id, Definition $definition)
throw new BadMethodCallException('Adding definition to a compiled container is not allowed.');
}
- $id = $this->normalizeId($id);
+ $id = (string) $id;
- if ('' === $id || '\\' === substr($id, -1) || \strlen($id) !== strcspn($id, "\0\r\n'")) {
+ if ('' === $id || '\\' === $id[-1] || \strlen($id) !== strcspn($id, "\0\r\n'")) {
throw new InvalidArgumentException(sprintf('Invalid service id: "%s".', $id));
}
@@ -1040,7 +1010,7 @@ public function setDefinition($id, Definition $definition)
*/
public function hasDefinition($id)
{
- return isset($this->definitions[$this->normalizeId($id)]);
+ return isset($this->definitions[(string) $id]);
}
/**
@@ -1054,7 +1024,7 @@ public function hasDefinition($id)
*/
public function getDefinition($id)
{
- $id = $this->normalizeId($id);
+ $id = (string) $id;
if (!isset($this->definitions[$id])) {
throw new ServiceNotFoundException($id);
@@ -1076,7 +1046,7 @@ public function getDefinition($id)
*/
public function findDefinition($id)
{
- $id = $this->normalizeId($id);
+ $id = (string) $id;
$seen = [];
while (isset($this->aliasDefinitions[$id])) {
@@ -1099,17 +1069,13 @@ public function findDefinition($id)
/**
* Creates a service for a service definition.
*
- * @param Definition $definition A service definition instance
- * @param string $id The service identifier
- * @param bool $tryProxy Whether to try proxying the service with a lazy proxy
- *
* @return mixed The service described by the service definition
*
* @throws RuntimeException When the factory definition is incomplete
* @throws RuntimeException When the service is a synthetic service
* @throws InvalidArgumentException When configure callable is not callable
*/
- private function createService(Definition $definition, array &$inlineServices, $isConstructorArgument = false, $id = null, $tryProxy = true)
+ private function createService(Definition $definition, array &$inlineServices, bool $isConstructorArgument = false, string $id = null, bool $tryProxy = true)
{
if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
return $inlineServices[$h];
@@ -1161,7 +1127,7 @@ private function createService(Definition $definition, array &$inlineServices, $
}
if (null !== $factory) {
- $service = \call_user_func_array($factory, $arguments);
+ $service = $factory(...$arguments);
if (!$definition->isDeprecated() && \is_array($factory) && \is_string($factory[0])) {
$r = new \ReflectionClass($factory[0]);
@@ -1171,20 +1137,24 @@ private function createService(Definition $definition, array &$inlineServices, $
}
}
} else {
- $r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass()));
+ $r = new \ReflectionClass($parameterBag->resolveValue($definition->getClass()));
$service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs(array_values($arguments));
- // don't trigger deprecations for internal uses
- // @deprecated since version 3.3, to be removed in 4.0 along with the deprecated class
- $deprecationAllowlist = ['event_dispatcher' => ContainerAwareEventDispatcher::class];
- if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ") && (!isset($deprecationAllowlist[$id]) || $deprecationAllowlist[$id] !== $class)) {
+ if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) {
@trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), \E_USER_DEPRECATED);
}
}
- if ($tryProxy || !$definition->isLazy()) {
- // share only if proxying failed, or if not a proxy
+ $lastWitherIndex = null;
+ foreach ($definition->getMethodCalls() as $k => $call) {
+ if ($call[2] ?? false) {
+ $lastWitherIndex = $k;
+ }
+ }
+
+ if (null === $lastWitherIndex && ($tryProxy || !$definition->isLazy())) {
+ // share only if proxying failed, or if not a proxy, and if no withers are found
$this->shareService($definition, $service, $id, $inlineServices);
}
@@ -1193,8 +1163,13 @@ private function createService(Definition $definition, array &$inlineServices, $
$service->$name = $value;
}
- foreach ($definition->getMethodCalls() as $call) {
- $this->callMethod($service, $call, $inlineServices);
+ foreach ($definition->getMethodCalls() as $k => $call) {
+ $service = $this->callMethod($service, $call, $inlineServices);
+
+ if ($lastWitherIndex === $k && ($tryProxy || !$definition->isLazy())) {
+ // share only if proxying failed, or if not a proxy, and this is the last wither
+ $this->shareService($definition, $service, $id, $inlineServices);
+ }
}
if ($callable = $definition->getConfigurator()) {
@@ -1212,7 +1187,7 @@ private function createService(Definition $definition, array &$inlineServices, $
throw new InvalidArgumentException(sprintf('The configure callable for class "%s" is not a callable.', \get_class($service)));
}
- \call_user_func($callable, $service);
+ $callable($service);
}
return $service;
@@ -1231,7 +1206,7 @@ public function resolveServices($value)
return $this->doResolveServices($value);
}
- private function doResolveServices($value, array &$inlineServices = [], $isConstructorArgument = false)
+ private function doResolveServices($value, array &$inlineServices = [], bool $isConstructorArgument = false)
{
if (\is_array($value)) {
foreach ($value as $k => $v) {
@@ -1243,7 +1218,7 @@ private function doResolveServices($value, array &$inlineServices = [], $isConst
return $this->resolveServices($reference);
};
} elseif ($value instanceof IteratorArgument) {
- $value = new RewindableGenerator(function () use ($value) {
+ $value = new RewindableGenerator(function () use ($value, &$inlineServices) {
foreach ($value->getValues() as $k => $v) {
foreach (self::getServiceConditionals($v) as $s) {
if (!$this->has($s)) {
@@ -1251,14 +1226,14 @@ private function doResolveServices($value, array &$inlineServices = [], $isConst
}
}
foreach (self::getInitializedConditionals($v) as $s) {
- if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
+ if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
continue 2;
}
}
- yield $k => $this->resolveServices($v);
+ yield $k => $this->doResolveServices($v, $inlineServices);
}
- }, function () use ($value) {
+ }, function () use ($value): int {
$count = 0;
foreach ($value->getValues() as $v) {
foreach (self::getServiceConditionals($v) as $s) {
@@ -1277,6 +1252,15 @@ private function doResolveServices($value, array &$inlineServices = [], $isConst
return $count;
});
+ } elseif ($value instanceof ServiceLocatorArgument) {
+ $refs = $types = [];
+ foreach ($value->getValues() as $k => $v) {
+ if ($v) {
+ $refs[$k] = [$v];
+ $types[$k] = $v instanceof TypedReference ? $v->getType() : '?';
+ }
+ }
+ $value = new ServiceLocator(\Closure::fromCallable([$this, 'resolveServices']), $refs, $types);
} elseif ($value instanceof Reference) {
$value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices, $isConstructorArgument);
} elseif ($value instanceof Definition) {
@@ -1379,6 +1363,25 @@ public function registerForAutoconfiguration($interface)
return $this->autoconfiguredInstanceof[$interface];
}
+ /**
+ * Registers an autowiring alias that only binds to a specific argument name.
+ *
+ * The argument name is derived from $name if provided (from $id otherwise)
+ * using camel case: "foo.bar" or "foo_bar" creates an alias bound to
+ * "$fooBar"-named arguments with $type as type-hint. Such arguments will
+ * receive the service $id when autowiring is used.
+ */
+ public function registerAliasForArgument(string $id, string $type, string $name = null): Alias
+ {
+ $name = lcfirst(str_replace(' ', '', ucwords(preg_replace('/[^a-zA-Z0-9\x7f-\xff]++/', ' ', $name ?? $id))));
+
+ if (!preg_match('/^[a-zA-Z_\x7f-\xff]/', $name)) {
+ throw new InvalidArgumentException(sprintf('Invalid argument name "%s" for service "%s": the first character must be a letter.', $name, $id));
+ }
+
+ return $this->setAlias($type.' $'.$name, $id);
+ }
+
/**
* Returns an array of ChildDefinition[] keyed by interface.
*
@@ -1411,6 +1414,10 @@ public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs
$value = $bag->resolveValue($value);
}
+ if ($value instanceof Definition) {
+ $value = (array) $value;
+ }
+
if (\is_array($value)) {
$result = [];
foreach ($value as $k => $v) {
@@ -1475,50 +1482,20 @@ public function getEnvCounters()
return $this->envCounters;
}
- /**
- * @internal
- */
- public function getNormalizedIds()
- {
- $normalizedIds = [];
-
- foreach ($this->normalizedIds as $k => $v) {
- if ($v !== (string) $k) {
- $normalizedIds[$k] = $v;
- }
- }
-
- return $normalizedIds;
- }
-
/**
* @final
*/
- public function log(CompilerPassInterface $pass, $message)
+ public function log(CompilerPassInterface $pass, string $message)
{
$this->getCompiler()->log($pass, $this->resolveEnvPlaceholders($message));
}
- /**
- * {@inheritdoc}
- */
- public function normalizeId($id)
- {
- if (!\is_string($id)) {
- $id = (string) $id;
- }
-
- return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || isset($this->removedIds[$id]) ? $id : parent::normalizeId($id);
- }
-
/**
* Gets removed binding ids.
*
- * @return array
- *
* @internal
*/
- public function getRemovedBindingIds()
+ public function getRemovedBindingIds(): array
{
return $this->removedBindingIds;
}
@@ -1526,15 +1503,13 @@ public function getRemovedBindingIds()
/**
* Removes bindings for a service.
*
- * @param string $id The service identifier
- *
* @internal
*/
- public function removeBindings($id)
+ public function removeBindings(string $id)
{
if ($this->hasDefinition($id)) {
foreach ($this->getDefinition($id)->getBindings() as $key => $binding) {
- list(, $bindingId) = $binding->getValues();
+ [, $bindingId] = $binding->getValues();
$this->removedBindingIds[(int) $bindingId] = true;
}
}
@@ -1545,11 +1520,9 @@ public function removeBindings($id)
*
* @param mixed $value An array of conditionals to return
*
- * @return array An array of Service conditionals
- *
- * @internal since version 3.4
+ * @internal
*/
- public static function getServiceConditionals($value)
+ public static function getServiceConditionals($value): array
{
$services = [];
@@ -1569,11 +1542,9 @@ public static function getServiceConditionals($value)
*
* @param mixed $value An array of conditionals to return
*
- * @return array An array of uninitialized conditionals
- *
* @internal
*/
- public static function getInitializedConditionals($value)
+ public static function getInitializedConditionals($value): array
{
$services = [];
@@ -1599,7 +1570,7 @@ public static function hash($value)
{
$hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7);
- return str_replace(['/', '+'], ['.', '_'], strtolower($hash));
+ return str_replace(['/', '+'], ['.', '_'], $hash);
}
/**
@@ -1614,11 +1585,15 @@ protected function getEnv($name)
return $value;
}
- foreach ($bag->getEnvPlaceholders() as $env => $placeholders) {
- if (isset($placeholders[$value])) {
- $bag = new ParameterBag($bag->all());
+ $envPlaceholders = $bag->getEnvPlaceholders();
+ if (isset($envPlaceholders[$name][$value])) {
+ $bag = new ParameterBag($bag->all());
- return $bag->unescapeValue($bag->get("env($name)"));
+ return $bag->unescapeValue($bag->get("env($name)"));
+ }
+ foreach ($envPlaceholders as $env => $placeholders) {
+ if (isset($placeholders[$value])) {
+ return $this->getEnv($env);
}
}
@@ -1630,31 +1605,32 @@ protected function getEnv($name)
}
}
- private function callMethod($service, $call, array &$inlineServices)
+ private function callMethod($service, array $call, array &$inlineServices)
{
foreach (self::getServiceConditionals($call[1]) as $s) {
if (!$this->has($s)) {
- return;
+ return $service;
}
}
foreach (self::getInitializedConditionals($call[1]) as $s) {
if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
- return;
+ return $service;
}
}
- \call_user_func_array([$service, $call[0]], $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
+ $result = $service->{$call[0]}(...$this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
+
+ return empty($call[2]) ? $service : $result;
}
/**
* Shares a given service in the container.
*
- * @param mixed $service
- * @param string|null $id
+ * @param mixed $service
*/
- private function shareService(Definition $definition, $service, $id, array &$inlineServices)
+ private function shareService(Definition $definition, $service, ?string $id, array &$inlineServices)
{
- $inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service;
+ $inlineServices[$id ?? spl_object_hash($definition)] = $service;
if (null !== $id && $definition->isShared()) {
$this->services[$id] = $service;
@@ -1662,11 +1638,11 @@ private function shareService(Definition $definition, $service, $id, array &$inl
}
}
- private function getExpressionLanguage()
+ private function getExpressionLanguage(): ExpressionLanguage
{
if (null === $this->expressionLanguage) {
- if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
- throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
+ if (!class_exists(\Symfony\Component\ExpressionLanguage\ExpressionLanguage::class)) {
+ throw new LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
}
$this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders);
}
@@ -1674,17 +1650,17 @@ private function getExpressionLanguage()
return $this->expressionLanguage;
}
- private function inVendors($path)
+ private function inVendors(string $path): bool
{
if (null === $this->vendors) {
- $resource = new ComposerResource();
- $this->vendors = $resource->getVendors();
- $this->addResource($resource);
+ $this->vendors = (new ComposerResource())->getVendors();
}
$path = realpath($path) ?: $path;
foreach ($this->vendors as $vendor) {
- if (0 === strpos($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
+ if (str_starts_with($path, $vendor) && false !== strpbrk(substr($path, \strlen($vendor), 1), '/'.\DIRECTORY_SEPARATOR)) {
+ $this->addResource(new FileResource($vendor.'/composer/installed.json'));
+
return true;
}
}
diff --git a/vendor/symfony/dependency-injection/ContainerInterface.php b/vendor/symfony/dependency-injection/ContainerInterface.php
index c5ab4c2e..a3acbbde 100644
--- a/vendor/symfony/dependency-injection/ContainerInterface.php
+++ b/vendor/symfony/dependency-injection/ContainerInterface.php
@@ -24,10 +24,11 @@
*/
interface ContainerInterface extends PsrContainerInterface
{
- const EXCEPTION_ON_INVALID_REFERENCE = 1;
- const NULL_ON_INVALID_REFERENCE = 2;
- const IGNORE_ON_INVALID_REFERENCE = 3;
- const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
+ public const RUNTIME_EXCEPTION_ON_INVALID_REFERENCE = 0;
+ public const EXCEPTION_ON_INVALID_REFERENCE = 1;
+ public const NULL_ON_INVALID_REFERENCE = 2;
+ public const IGNORE_ON_INVALID_REFERENCE = 3;
+ public const IGNORE_ON_UNINITIALIZED_REFERENCE = 4;
/**
* Sets a service.
@@ -53,8 +54,6 @@ public function set($id, $service);
public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE);
/**
- * Returns true if the given service is defined.
- *
* @param string $id The service identifier
*
* @return bool true if the service is defined, false otherwise
@@ -75,7 +74,7 @@ public function initialized($id);
*
* @param string $name The parameter name
*
- * @return mixed The parameter value
+ * @return array|bool|string|int|float|null
*
* @throws InvalidArgumentException if the parameter is not defined
*/
@@ -93,8 +92,8 @@ public function hasParameter($name);
/**
* Sets a parameter.
*
- * @param string $name The parameter name
- * @param mixed $value The parameter value
+ * @param string $name The parameter name
+ * @param array|bool|string|int|float|null $value The parameter value
*/
public function setParameter($name, $value);
}
diff --git a/vendor/symfony/dependency-injection/Definition.php b/vendor/symfony/dependency-injection/Definition.php
index c3a94f5c..34ddbbbd 100644
--- a/vendor/symfony/dependency-injection/Definition.php
+++ b/vendor/symfony/dependency-injection/Definition.php
@@ -22,6 +22,8 @@
*/
class Definition
{
+ private const DEFAULT_DEPRECATION_TEMPLATE = 'The "%service_id%" service is deprecated. You should stop using it, as it will be removed in the future.';
+
private $class;
private $file;
private $factory;
@@ -41,14 +43,25 @@ class Definition
private $lazy = false;
private $decoratedService;
private $autowired = false;
- private $autowiringTypes = [];
private $changes = [];
private $bindings = [];
private $errors = [];
protected $arguments = [];
- private static $defaultDeprecationTemplate = 'The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed.';
+ /**
+ * @internal
+ *
+ * Used to store the name of the inner id when using service decoration together with autowiring
+ */
+ public $innerServiceId;
+
+ /**
+ * @internal
+ *
+ * Used to store the behavior to follow when using service decoration and the decorated service is invalid
+ */
+ public $decorationOnInvalid;
/**
* @param string|null $class The service class
@@ -89,7 +102,7 @@ public function setChanges(array $changes)
/**
* Sets a factory.
*
- * @param string|array $factory A PHP function or an array containing a class/Reference and a method to call
+ * @param string|array|Reference|null $factory A PHP function, reference or an array containing a class/Reference and a method to call
*
* @return $this
*/
@@ -97,8 +110,10 @@ public function setFactory($factory)
{
$this->changes['factory'] = true;
- if (\is_string($factory) && false !== strpos($factory, '::')) {
+ if (\is_string($factory) && str_contains($factory, '::')) {
$factory = explode('::', $factory, 2);
+ } elseif ($factory instanceof Reference) {
+ $factory = [$factory, '__invoke'];
}
$this->factory = $factory;
@@ -119,26 +134,33 @@ public function getFactory()
/**
* Sets the service that this service is decorating.
*
- * @param string|null $id The decorated service id, use null to remove decoration
- * @param string|null $renamedId The new decorated service id
- * @param int $priority The priority of decoration
+ * @param string|null $id The decorated service id, use null to remove decoration
+ * @param string|null $renamedId The new decorated service id
+ * @param int $priority The priority of decoration
+ * @param int $invalidBehavior The behavior to adopt when decorated is invalid
*
* @return $this
*
* @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals
*/
- public function setDecoratedService($id, $renamedId = null, $priority = 0)
+ public function setDecoratedService($id, $renamedId = null, $priority = 0/*, int $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE*/)
{
if ($renamedId && $id === $renamedId) {
throw new InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
}
+ $invalidBehavior = 3 < \func_num_args() ? (int) func_get_arg(3) : ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE;
+
$this->changes['decorated_service'] = true;
if (null === $id) {
$this->decoratedService = null;
} else {
$this->decoratedService = [$id, $renamedId, (int) $priority];
+
+ if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
+ $this->decoratedService[] = $invalidBehavior;
+ }
}
return $this;
@@ -163,6 +185,13 @@ public function getDecoratedService()
*/
public function setClass($class)
{
+ if ($class instanceof Parameter) {
+ @trigger_error(sprintf('Passing an instance of %s as class name to %s in deprecated in Symfony 4.4 and will result in a TypeError in 5.0. Please pass the string "%%%s%%" instead.', Parameter::class, __CLASS__, (string) $class), \E_USER_DEPRECATED);
+ }
+ if (null !== $class && !\is_string($class)) {
+ @trigger_error(sprintf('The class name passed to %s is expected to be a string. Passing a %s is deprecated in Symfony 4.4 and will result in a TypeError in 5.0.', __CLASS__, \is_object($class) ? \get_class($class) : \gettype($class)), \E_USER_DEPRECATED);
+ }
+
$this->changes['class'] = true;
$this->class = $class;
@@ -324,7 +353,7 @@ public function setMethodCalls(array $calls = [])
{
$this->calls = [];
foreach ($calls as $call) {
- $this->addMethodCall($call[0], $call[1]);
+ $this->addMethodCall($call[0], $call[1], $call[2] ?? false);
}
return $this;
@@ -333,19 +362,20 @@ public function setMethodCalls(array $calls = [])
/**
* Adds a method to call after service initialization.
*
- * @param string $method The method name to call
- * @param array $arguments An array of arguments to pass to the method call
+ * @param string $method The method name to call
+ * @param array $arguments An array of arguments to pass to the method call
+ * @param bool $returnsClone Whether the call returns the service instance or not
*
* @return $this
*
* @throws InvalidArgumentException on empty $method param
*/
- public function addMethodCall($method, array $arguments = [])
+ public function addMethodCall($method, array $arguments = []/*, bool $returnsClone = false*/)
{
if (empty($method)) {
throw new InvalidArgumentException('Method name cannot be empty.');
}
- $this->calls[] = [$method, $arguments];
+ $this->calls[] = 2 < \func_num_args() && func_get_arg(2) ? [$method, $arguments, true] : [$method, $arguments];
return $this;
}
@@ -362,7 +392,6 @@ public function removeMethodCall($method)
foreach ($this->calls as $i => $call) {
if ($call[0] === $method) {
unset($this->calls[$i]);
- break;
}
}
@@ -476,7 +505,7 @@ public function getTags()
*/
public function getTag($name)
{
- return isset($this->tags[$name]) ? $this->tags[$name] : [];
+ return $this->tags[$name] ?? [];
}
/**
@@ -736,7 +765,7 @@ public function setDeprecated($status = true, $template = null)
throw new InvalidArgumentException('Invalid characters found in deprecation template.');
}
- if (false === strpos($template, '%service_id%')) {
+ if (!str_contains($template, '%service_id%')) {
throw new InvalidArgumentException('The deprecation template must contain the "%service_id%" placeholder.');
}
@@ -770,13 +799,13 @@ public function isDeprecated()
*/
public function getDeprecationMessage($id)
{
- return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::$defaultDeprecationTemplate);
+ return str_replace('%service_id%', $id, $this->deprecationTemplate ?: self::DEFAULT_DEPRECATION_TEMPLATE);
}
/**
* Sets a configurator to call after the service is fully initialized.
*
- * @param string|array $configurator A PHP callable
+ * @param string|array|Reference|null $configurator A PHP function, reference or an array containing a class/Reference and a method to call
*
* @return $this
*/
@@ -784,8 +813,10 @@ public function setConfigurator($configurator)
{
$this->changes['configurator'] = true;
- if (\is_string($configurator) && false !== strpos($configurator, '::')) {
+ if (\is_string($configurator) && str_contains($configurator, '::')) {
$configurator = explode('::', $configurator, 2);
+ } elseif ($configurator instanceof Reference) {
+ $configurator = [$configurator, '__invoke'];
}
$this->configurator = $configurator;
@@ -803,28 +834,6 @@ public function getConfigurator()
return $this->configurator;
}
- /**
- * Sets types that will default to this definition.
- *
- * @param string[] $types
- *
- * @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- public function setAutowiringTypes(array $types)
- {
- @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', \E_USER_DEPRECATED);
-
- $this->autowiringTypes = [];
-
- foreach ($types as $type) {
- $this->autowiringTypes[$type] = true;
- }
-
- return $this;
- }
-
/**
* Is the definition autowired?
*
@@ -851,78 +860,10 @@ public function setAutowired($autowired)
return $this;
}
- /**
- * Gets autowiring types that will default to this definition.
- *
- * @return string[]
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- public function getAutowiringTypes(/*$triggerDeprecation = true*/)
- {
- if (1 > \func_num_args() || func_get_arg(0)) {
- @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', \E_USER_DEPRECATED);
- }
-
- return array_keys($this->autowiringTypes);
- }
-
- /**
- * Adds a type that will default to this definition.
- *
- * @param string $type
- *
- * @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- public function addAutowiringType($type)
- {
- @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), \E_USER_DEPRECATED);
-
- $this->autowiringTypes[$type] = true;
-
- return $this;
- }
-
- /**
- * Removes a type.
- *
- * @param string $type
- *
- * @return $this
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- public function removeAutowiringType($type)
- {
- @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), \E_USER_DEPRECATED);
-
- unset($this->autowiringTypes[$type]);
-
- return $this;
- }
-
- /**
- * Will this definition default for the given type?
- *
- * @param string $type
- *
- * @return bool
- *
- * @deprecated since version 3.3, to be removed in 4.0.
- */
- public function hasAutowiringType($type)
- {
- @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), \E_USER_DEPRECATED);
-
- return isset($this->autowiringTypes[$type]);
- }
-
/**
* Gets bindings.
*
- * @return array
+ * @return array|BoundArgument[]
*/
public function getBindings()
{
@@ -941,6 +882,10 @@ public function getBindings()
public function setBindings(array $bindings)
{
foreach ($bindings as $key => $binding) {
+ if (0 < strpos($key, '$') && $key !== $k = preg_replace('/[ \t]*\$/', ' $', $key)) {
+ unset($bindings[$key]);
+ $bindings[$key = $k] = $binding;
+ }
if (!$binding instanceof BoundArgument) {
$bindings[$key] = new BoundArgument($binding);
}
@@ -954,11 +899,19 @@ public function setBindings(array $bindings)
/**
* Add an error that occurred when building this Definition.
*
- * @param string $error
+ * @param string|\Closure|self $error
+ *
+ * @return $this
*/
public function addError($error)
{
- $this->errors[] = $error;
+ if ($error instanceof self) {
+ $this->errors = array_merge($this->errors, $error->errors);
+ } else {
+ $this->errors[] = $error;
+ }
+
+ return $this;
}
/**
@@ -968,6 +921,19 @@ public function addError($error)
*/
public function getErrors()
{
+ foreach ($this->errors as $i => $error) {
+ if ($error instanceof \Closure) {
+ $this->errors[$i] = (string) $error();
+ } elseif (!\is_string($error)) {
+ $this->errors[$i] = (string) $error;
+ }
+ }
+
return $this->errors;
}
+
+ public function hasErrors(): bool
+ {
+ return (bool) $this->errors;
+ }
}
diff --git a/vendor/symfony/dependency-injection/DefinitionDecorator.php b/vendor/symfony/dependency-injection/DefinitionDecorator.php
deleted file mode 100644
index 4753c2aa..00000000
--- a/vendor/symfony/dependency-injection/DefinitionDecorator.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-namespace Symfony\Component\DependencyInjection;
-
-@trigger_error('The '.__NAMESPACE__.'\DefinitionDecorator class is deprecated since Symfony 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.', \E_USER_DEPRECATED);
-
-class_exists(ChildDefinition::class);
-
-if (false) {
- /**
- * This definition decorates another definition.
- *
- * @author Johannes M. Schmitt