updated core and modules
This commit is contained in:
+6
-4
@@ -59,8 +59,8 @@ class ApcClassLoader
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix The APC namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
* @param string $prefix The APC namespace prefix to use
|
||||
* @param object $decorated A class loader object that implements the findFile() method
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
@@ -122,8 +122,10 @@ class ApcClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if (false === $file = apcu_fetch($this->prefix.$class)) {
|
||||
apcu_store($this->prefix.$class, $file = $this->decorated->findFile($class));
|
||||
$file = apcu_fetch($this->prefix.$class, $success);
|
||||
|
||||
if (!$success) {
|
||||
apcu_store($this->prefix.$class, $file = $this->decorated->findFile($class) ?: null);
|
||||
}
|
||||
|
||||
return $file;
|
||||
|
||||
+4
-2
@@ -92,8 +92,10 @@ class ApcUniversalClassLoader extends UniversalClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if (false === $file = apcu_fetch($this->prefix.$class)) {
|
||||
apcu_store($this->prefix.$class, $file = parent::findFile($class));
|
||||
$file = apcu_fetch($this->prefix.$class, $success);
|
||||
|
||||
if (!$success) {
|
||||
apcu_store($this->prefix.$class, $file = parent::findFile($class) ?: null);
|
||||
}
|
||||
|
||||
return $file;
|
||||
|
||||
+63
-20
@@ -43,12 +43,12 @@ class ClassCollectionLoader
|
||||
|
||||
self::$loaded[$name] = true;
|
||||
|
||||
$declared = array_merge(get_declared_classes(), get_declared_interfaces());
|
||||
if (function_exists('get_declared_traits')) {
|
||||
$declared = array_merge($declared, get_declared_traits());
|
||||
}
|
||||
|
||||
if ($adaptive) {
|
||||
$declared = array_merge(get_declared_classes(), get_declared_interfaces());
|
||||
if (function_exists('get_declared_traits')) {
|
||||
$declared = array_merge($declared, get_declared_traits());
|
||||
}
|
||||
|
||||
// don't include already declared classes
|
||||
$classes = array_diff($classes, $declared);
|
||||
|
||||
@@ -58,6 +58,11 @@ class ClassCollectionLoader
|
||||
|
||||
$classes = array_unique($classes);
|
||||
|
||||
// cache the core classes
|
||||
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
|
||||
}
|
||||
$cacheDir = rtrim(realpath($cacheDir) ?: $cacheDir, '/'.DIRECTORY_SEPARATOR);
|
||||
$cache = $cacheDir.'/'.$name.$extension;
|
||||
|
||||
// auto-reload
|
||||
@@ -87,12 +92,29 @@ class ClassCollectionLoader
|
||||
}
|
||||
}
|
||||
|
||||
if (!$reload && is_file($cache)) {
|
||||
if (!$reload && file_exists($cache)) {
|
||||
require_once $cache;
|
||||
|
||||
return;
|
||||
}
|
||||
if (!$adaptive) {
|
||||
$declared = array_merge(get_declared_classes(), get_declared_interfaces());
|
||||
if (function_exists('get_declared_traits')) {
|
||||
$declared = array_merge($declared, get_declared_traits());
|
||||
}
|
||||
}
|
||||
|
||||
$spacesRegex = '(?:\s*+(?:(?:\#|//)[^\n]*+\n|/\*(?:(?<!\*/).)++)?+)*+';
|
||||
$dontInlineRegex = <<<REGEX
|
||||
'(?:
|
||||
^<\?php\s.declare.\(.strict_types.=.1.\).;
|
||||
| \b__halt_compiler.\(.\)
|
||||
| \b__(?:DIR|FILE)__\b
|
||||
)'isx
|
||||
REGEX;
|
||||
$dontInlineRegex = str_replace('.', $spacesRegex, $dontInlineRegex);
|
||||
|
||||
$cacheDir = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $cacheDir));
|
||||
$files = array();
|
||||
$content = '';
|
||||
foreach (self::getOrderedClasses($classes) as $class) {
|
||||
@@ -100,25 +122,40 @@ class ClassCollectionLoader
|
||||
continue;
|
||||
}
|
||||
|
||||
$files[] = $class->getFileName();
|
||||
$files[] = $file = $class->getFileName();
|
||||
$c = file_get_contents($file);
|
||||
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', file_get_contents($class->getFileName()));
|
||||
if (preg_match($dontInlineRegex, $c)) {
|
||||
$file = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $file));
|
||||
|
||||
// fakes namespace declaration for global code
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".$c."\n}\n";
|
||||
for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) {
|
||||
if ($file[$i] !== $cacheDir[$i]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (1 >= $i) {
|
||||
$file = var_export(implode('/', $file), true);
|
||||
} else {
|
||||
$file = array_slice($file, $i);
|
||||
$file = str_repeat('../', count($cacheDir) - $i).implode('/', $file);
|
||||
$file = '__DIR__.'.var_export('/'.$file, true);
|
||||
}
|
||||
|
||||
$c = "\nnamespace {require $file;}";
|
||||
} else {
|
||||
$c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', $c);
|
||||
|
||||
// fakes namespace declaration for global code
|
||||
if (!$class->inNamespace()) {
|
||||
$c = "\nnamespace\n{\n".$c."\n}\n";
|
||||
}
|
||||
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
}
|
||||
|
||||
$c = self::fixNamespaceDeclarations('<?php '.$c);
|
||||
$c = preg_replace('/^\s*<\?php/', '', $c);
|
||||
|
||||
$content .= $c;
|
||||
}
|
||||
|
||||
// cache the core classes
|
||||
if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) {
|
||||
throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir));
|
||||
}
|
||||
self::writeCacheFile($cache, '<?php '.$content);
|
||||
|
||||
if ($autoReload) {
|
||||
@@ -238,7 +275,13 @@ class ClassCollectionLoader
|
||||
*/
|
||||
private static function writeCacheFile($file, $content)
|
||||
{
|
||||
$tmpFile = tempnam(dirname($file), basename($file));
|
||||
$dir = dirname($file);
|
||||
if (!is_writable($dir)) {
|
||||
throw new \RuntimeException(sprintf('Cache directory "%s" is not writable.', $dir));
|
||||
}
|
||||
|
||||
$tmpFile = tempnam($dir, basename($file));
|
||||
|
||||
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
|
||||
@chmod($file, 0666 & ~umask());
|
||||
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ class ClassMapGenerator
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = $file->getRealPath();
|
||||
$path = $file->getRealPath() ?: $file->getPathname();
|
||||
|
||||
if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
|
||||
continue;
|
||||
|
||||
+1
-1
@@ -89,7 +89,7 @@ class DebugClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
return $this->classFinder->findFile($class);
|
||||
return $this->classFinder->findFile($class) ?: null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2016 Fabien Potencier
|
||||
Copyright (c) 2004-2017 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
|
||||
|
||||
+6
-4
@@ -60,8 +60,8 @@ class WinCacheClassLoader
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix The WinCache namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
* @param string $prefix The WinCache namespace prefix to use
|
||||
* @param object $decorated A class loader object that implements the findFile() method
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
@@ -123,8 +123,10 @@ class WinCacheClassLoader
|
||||
*/
|
||||
public function findFile($class)
|
||||
{
|
||||
if (false === $file = wincache_ucache_get($this->prefix.$class)) {
|
||||
wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class), 0);
|
||||
$file = wincache_ucache_get($this->prefix.$class, $success);
|
||||
|
||||
if (!$success) {
|
||||
wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class) ?: null, 0);
|
||||
}
|
||||
|
||||
return $file;
|
||||
|
||||
+3
-3
@@ -60,8 +60,8 @@ class XcacheClassLoader
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $prefix The XCache namespace prefix to use.
|
||||
* @param object $decorated A class loader object that implements the findFile() method.
|
||||
* @param string $prefix The XCache namespace prefix to use
|
||||
* @param object $decorated A class loader object that implements the findFile() method
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws \InvalidArgumentException
|
||||
@@ -126,7 +126,7 @@ class XcacheClassLoader
|
||||
if (xcache_isset($this->prefix.$class)) {
|
||||
$file = xcache_get($this->prefix.$class);
|
||||
} else {
|
||||
$file = $this->decorated->findFile($class);
|
||||
$file = $this->decorated->findFile($class) ?: null;
|
||||
xcache_set($this->prefix.$class, $file);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
"symfony/polyfill-apcu": "~1.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/finder": "~2.0,>=2.0.5|~3.0.0"
|
||||
"symfony/finder": "^2.0.5|~3.0.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\ClassLoader\\": "" },
|
||||
|
||||
+37
-18
@@ -41,6 +41,7 @@ use Symfony\Component\Console\Event\ConsoleExceptionEvent;
|
||||
use Symfony\Component\Console\Event\ConsoleTerminateEvent;
|
||||
use Symfony\Component\Console\Exception\CommandNotFoundException;
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Debug\Exception\FatalThrowableError;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
/**
|
||||
@@ -104,8 +105,6 @@ class Application
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*
|
||||
* @throws \Exception When doRun returns Exception
|
||||
*/
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null)
|
||||
{
|
||||
@@ -216,7 +215,7 @@ class Application
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an input definition set to be used with this application.
|
||||
* Set an input definition to be used with this application.
|
||||
*
|
||||
* @param InputDefinition $definition The input definition
|
||||
*/
|
||||
@@ -238,7 +237,7 @@ class Application
|
||||
/**
|
||||
* Gets the help message.
|
||||
*
|
||||
* @return string A help message.
|
||||
* @return string A help message
|
||||
*/
|
||||
public function getHelp()
|
||||
{
|
||||
@@ -338,6 +337,8 @@ class Application
|
||||
/**
|
||||
* Adds an array of command objects.
|
||||
*
|
||||
* If a Command is not enabled it will not be added.
|
||||
*
|
||||
* @param Command[] $commands An array of commands
|
||||
*/
|
||||
public function addCommands(array $commands)
|
||||
@@ -351,10 +352,11 @@ class Application
|
||||
* Adds a command object.
|
||||
*
|
||||
* If a command with the same name already exists, it will be overridden.
|
||||
* If the command is not enabled it will not be added.
|
||||
*
|
||||
* @param Command $command A Command object
|
||||
*
|
||||
* @return Command The registered command
|
||||
* @return Command|null The registered command if enabled or null
|
||||
*/
|
||||
public function add(Command $command)
|
||||
{
|
||||
@@ -386,7 +388,7 @@ class Application
|
||||
*
|
||||
* @return Command A Command object
|
||||
*
|
||||
* @throws CommandNotFoundException When command name given does not exist
|
||||
* @throws CommandNotFoundException When given command name does not exist
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
@@ -423,9 +425,9 @@ class Application
|
||||
/**
|
||||
* Returns an array of all unique namespaces used by currently registered commands.
|
||||
*
|
||||
* It does not returns the global namespace which always exists.
|
||||
* It does not return the global namespace which always exists.
|
||||
*
|
||||
* @return array An array of namespaces
|
||||
* @return string[] An array of namespaces
|
||||
*/
|
||||
public function getNamespaces()
|
||||
{
|
||||
@@ -773,7 +775,7 @@ class Application
|
||||
* @param int $width The width
|
||||
* @param int $height The height
|
||||
*
|
||||
* @return Application The current application
|
||||
* @return $this
|
||||
*/
|
||||
public function setTerminalDimensions($width, $height)
|
||||
{
|
||||
@@ -807,6 +809,7 @@ class Application
|
||||
|
||||
if (true === $input->hasParameterOption(array('--quiet', '-q'))) {
|
||||
$output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
|
||||
$input->setInteractive(false);
|
||||
} else {
|
||||
if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) {
|
||||
$output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
|
||||
@@ -829,8 +832,6 @@ class Application
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return int 0 if everything went fine, or an error code
|
||||
*
|
||||
* @throws \Exception when the command being run threw an exception
|
||||
*/
|
||||
protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
@@ -841,7 +842,13 @@ class Application
|
||||
}
|
||||
|
||||
if (null === $this->dispatcher) {
|
||||
return $command->run($input, $output);
|
||||
try {
|
||||
return $command->run($input, $output);
|
||||
} catch (\Exception $e) {
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
throw new FatalThrowableError($e);
|
||||
}
|
||||
}
|
||||
|
||||
// bind before the console.command event, so the listeners have access to input options/arguments
|
||||
@@ -852,22 +859,34 @@ class Application
|
||||
// ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
|
||||
}
|
||||
|
||||
// don't bind the input again as it would override any input argument/option set from the command event in
|
||||
// addition to being useless
|
||||
$command->setInputBound(true);
|
||||
|
||||
$event = new ConsoleCommandEvent($command, $input, $output);
|
||||
$this->dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
|
||||
|
||||
if ($event->commandShouldRun()) {
|
||||
try {
|
||||
$e = null;
|
||||
$exitCode = $command->run($input, $output);
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception $x) {
|
||||
$e = $x;
|
||||
} catch (\Throwable $x) {
|
||||
$e = new FatalThrowableError($x);
|
||||
}
|
||||
if (null !== $e) {
|
||||
$event = new ConsoleExceptionEvent($command, $input, $output, $e, $e->getCode());
|
||||
$this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event);
|
||||
|
||||
$e = $event->getException();
|
||||
if ($e !== $event->getException()) {
|
||||
$x = $e = $event->getException();
|
||||
}
|
||||
|
||||
$event = new ConsoleTerminateEvent($command, $input, $output, $e->getCode());
|
||||
$this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event);
|
||||
|
||||
throw $e;
|
||||
throw $x;
|
||||
}
|
||||
} else {
|
||||
$exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
|
||||
@@ -965,7 +984,7 @@ class Application
|
||||
/**
|
||||
* Runs and parses mode CON if it's available, suppressing any error output.
|
||||
*
|
||||
* @return string <width>x<height> or null if it could not be parsed
|
||||
* @return string|null <width>x<height> or null if it could not be parsed
|
||||
*/
|
||||
private function getConsoleMode()
|
||||
{
|
||||
@@ -1024,7 +1043,7 @@ class Application
|
||||
* @param string $name The string
|
||||
* @param array|\Traversable $collection The collection
|
||||
*
|
||||
* @return array A sorted array of similar string
|
||||
* @return string[] A sorted array of similar string
|
||||
*/
|
||||
private function findAlternatives($name, $collection)
|
||||
{
|
||||
@@ -1123,7 +1142,7 @@ class Application
|
||||
*
|
||||
* @param string $name The full name of the command
|
||||
*
|
||||
* @return array The namespaces of the command
|
||||
* @return string[] The namespaces of the command
|
||||
*/
|
||||
private function extractAllNamespaces($name)
|
||||
{
|
||||
|
||||
+51
-20
@@ -42,6 +42,7 @@ class Command
|
||||
private $ignoreValidationErrors = false;
|
||||
private $applicationDefinitionMerged = false;
|
||||
private $applicationDefinitionMergedWithArgs = false;
|
||||
private $inputBound = false;
|
||||
private $code;
|
||||
private $synopsis = array();
|
||||
private $usages = array();
|
||||
@@ -205,8 +206,6 @@ class Command
|
||||
*
|
||||
* @return int The command exit code
|
||||
*
|
||||
* @throws \Exception
|
||||
*
|
||||
* @see setCode()
|
||||
* @see execute()
|
||||
*/
|
||||
@@ -220,11 +219,13 @@ class Command
|
||||
$this->mergeApplicationDefinition();
|
||||
|
||||
// bind the input against the command specific arguments/options
|
||||
try {
|
||||
$input->bind($this->definition);
|
||||
} catch (ExceptionInterface $e) {
|
||||
if (!$this->ignoreValidationErrors) {
|
||||
throw $e;
|
||||
if (!$this->inputBound) {
|
||||
try {
|
||||
$input->bind($this->definition);
|
||||
} catch (ExceptionInterface $e) {
|
||||
if (!$this->ignoreValidationErrors) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,7 +233,14 @@ class Command
|
||||
|
||||
if (null !== $this->processTitle) {
|
||||
if (function_exists('cli_set_process_title')) {
|
||||
cli_set_process_title($this->processTitle);
|
||||
if (false === @cli_set_process_title($this->processTitle)) {
|
||||
if ('Darwin' === PHP_OS) {
|
||||
$output->writeln('<comment>Running "cli_get_process_title" as an unprivileged user is not supported on MacOS.</comment>');
|
||||
} else {
|
||||
$error = error_get_last();
|
||||
trigger_error($error['message'], E_USER_WARNING);
|
||||
}
|
||||
}
|
||||
} elseif (function_exists('setproctitle')) {
|
||||
setproctitle($this->processTitle);
|
||||
} elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
|
||||
@@ -270,7 +278,7 @@ class Command
|
||||
*
|
||||
* @param callable $code A callable(InputInterface $input, OutputInterface $output)
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*
|
||||
@@ -285,7 +293,15 @@ class Command
|
||||
if (PHP_VERSION_ID >= 50400 && $code instanceof \Closure) {
|
||||
$r = new \ReflectionFunction($code);
|
||||
if (null === $r->getClosureThis()) {
|
||||
$code = \Closure::bind($code, $this);
|
||||
if (PHP_VERSION_ID < 70000) {
|
||||
// Bug in PHP5: https://bugs.php.net/bug.php?id=64761
|
||||
// This means that we cannot bind static closures and therefore we must
|
||||
// ignore any errors here. There is no way to test if the closure is
|
||||
// bindable.
|
||||
$code = @\Closure::bind($code, $this);
|
||||
} else {
|
||||
$code = \Closure::bind($code, $this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -307,14 +323,14 @@ class Command
|
||||
return;
|
||||
}
|
||||
|
||||
$this->definition->addOptions($this->application->getDefinition()->getOptions());
|
||||
|
||||
if ($mergeArgs) {
|
||||
$currentArguments = $this->definition->getArguments();
|
||||
$this->definition->setArguments($this->application->getDefinition()->getArguments());
|
||||
$this->definition->addArguments($currentArguments);
|
||||
}
|
||||
|
||||
$this->definition->addOptions($this->application->getDefinition()->getOptions());
|
||||
|
||||
$this->applicationDefinitionMerged = true;
|
||||
if ($mergeArgs) {
|
||||
$this->applicationDefinitionMergedWithArgs = true;
|
||||
@@ -326,7 +342,7 @@ class Command
|
||||
*
|
||||
* @param array|InputDefinition $definition An array of argument and option instances or a definition instance
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setDefinition($definition)
|
||||
{
|
||||
@@ -374,7 +390,7 @@ class Command
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addArgument($name, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
@@ -392,7 +408,7 @@ class Command
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
@@ -411,7 +427,7 @@ class Command
|
||||
*
|
||||
* @param string $name The command name
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException When the name is invalid
|
||||
*/
|
||||
@@ -434,7 +450,7 @@ class Command
|
||||
*
|
||||
* @param string $title The process title
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setProcessTitle($title)
|
||||
{
|
||||
@@ -458,7 +474,7 @@ class Command
|
||||
*
|
||||
* @param string $description The description for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
@@ -482,7 +498,7 @@ class Command
|
||||
*
|
||||
* @param string $help The help for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setHelp($help)
|
||||
{
|
||||
@@ -528,7 +544,7 @@ class Command
|
||||
*
|
||||
* @param string[] $aliases An array of aliases for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException When an alias is invalid
|
||||
*/
|
||||
@@ -579,6 +595,8 @@ class Command
|
||||
* Add a command usage example.
|
||||
*
|
||||
* @param string $usage The usage, it'll be prefixed with the command name
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addUsage($usage)
|
||||
{
|
||||
@@ -608,10 +626,15 @@ class Command
|
||||
*
|
||||
* @return mixed The helper value
|
||||
*
|
||||
* @throws LogicException if no HelperSet is defined
|
||||
* @throws InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function getHelper($name)
|
||||
{
|
||||
if (null === $this->helperSet) {
|
||||
throw new LogicException(sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
|
||||
}
|
||||
|
||||
return $this->helperSet->get($name);
|
||||
}
|
||||
|
||||
@@ -658,6 +681,14 @@ class Command
|
||||
return $output->fetch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
public function setInputBound($inputBound)
|
||||
{
|
||||
$this->inputBound = $inputBound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates a command name.
|
||||
*
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Symfony\Component\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
@@ -94,11 +95,11 @@ class MarkdownDescriptor extends Descriptor
|
||||
|
||||
$this->write(
|
||||
$command->getName()."\n"
|
||||
.str_repeat('-', strlen($command->getName()))."\n\n"
|
||||
.str_repeat('-', Helper::strlen($command->getName()))."\n\n"
|
||||
.'* Description: '.($command->getDescription() ?: '<none>')."\n"
|
||||
.'* Usage:'."\n\n"
|
||||
.array_reduce(array_merge(array($command->getSynopsis()), $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
|
||||
return $carry .= ' * `'.$usage.'`'."\n";
|
||||
return $carry.' * `'.$usage.'`'."\n";
|
||||
})
|
||||
);
|
||||
|
||||
@@ -121,7 +122,7 @@ class MarkdownDescriptor extends Descriptor
|
||||
$describedNamespace = isset($options['namespace']) ? $options['namespace'] : null;
|
||||
$description = new ApplicationDescription($application, $describedNamespace);
|
||||
|
||||
$this->write($application->getName()."\n".str_repeat('=', strlen($application->getName())));
|
||||
$this->write($application->getName()."\n".str_repeat('=', Helper::strlen($application->getName())));
|
||||
|
||||
foreach ($description->getNamespaces() as $namespace) {
|
||||
if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
|
||||
|
||||
+28
-16
@@ -13,6 +13,8 @@ namespace Symfony\Component\Console\Descriptor;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
use Symfony\Component\Console\Helper\Helper;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
@@ -37,14 +39,14 @@ class TextDescriptor extends Descriptor
|
||||
$default = '';
|
||||
}
|
||||
|
||||
$totalWidth = isset($options['total_width']) ? $options['total_width'] : strlen($argument->getName());
|
||||
$spacingWidth = $totalWidth - strlen($argument->getName()) + 2;
|
||||
$totalWidth = isset($options['total_width']) ? $options['total_width'] : Helper::strlen($argument->getName());
|
||||
$spacingWidth = $totalWidth - strlen($argument->getName());
|
||||
|
||||
$this->writeText(sprintf(' <info>%s</info>%s%s%s',
|
||||
$this->writeText(sprintf(' <info>%s</info> %s%s%s',
|
||||
$argument->getName(),
|
||||
str_repeat(' ', $spacingWidth),
|
||||
// + 17 = 2 spaces + <info> + </info> + 2 spaces
|
||||
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $argument->getDescription()),
|
||||
// + 4 = 2 spaces before <info>, 2 spaces after </info>
|
||||
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
|
||||
$default
|
||||
), $options);
|
||||
}
|
||||
@@ -75,13 +77,13 @@ class TextDescriptor extends Descriptor
|
||||
sprintf('--%s%s', $option->getName(), $value)
|
||||
);
|
||||
|
||||
$spacingWidth = $totalWidth - strlen($synopsis) + 2;
|
||||
$spacingWidth = $totalWidth - Helper::strlen($synopsis);
|
||||
|
||||
$this->writeText(sprintf(' <info>%s</info>%s%s%s%s',
|
||||
$this->writeText(sprintf(' <info>%s</info> %s%s%s%s',
|
||||
$synopsis,
|
||||
str_repeat(' ', $spacingWidth),
|
||||
// + 17 = 2 spaces + <info> + </info> + 2 spaces
|
||||
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 17), $option->getDescription()),
|
||||
// + 4 = 2 spaces before <info>, 2 spaces after </info>
|
||||
preg_replace('/\s*[\r\n]\s*/', "\n".str_repeat(' ', $totalWidth + 4), $option->getDescription()),
|
||||
$default,
|
||||
$option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
|
||||
), $options);
|
||||
@@ -94,7 +96,7 @@ class TextDescriptor extends Descriptor
|
||||
{
|
||||
$totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
|
||||
foreach ($definition->getArguments() as $argument) {
|
||||
$totalWidth = max($totalWidth, strlen($argument->getName()));
|
||||
$totalWidth = max($totalWidth, Helper::strlen($argument->getName()));
|
||||
}
|
||||
|
||||
if ($definition->getArguments()) {
|
||||
@@ -156,7 +158,7 @@ class TextDescriptor extends Descriptor
|
||||
$this->writeText("\n");
|
||||
$this->writeText('<comment>Help:</comment>', $options);
|
||||
$this->writeText("\n");
|
||||
$this->writeText(' '.str_replace("\n", "\n ", $help), $options);
|
||||
$this->writeText(' '.str_replace("\n", "\n ", $help), $options);
|
||||
$this->writeText("\n");
|
||||
}
|
||||
}
|
||||
@@ -206,7 +208,7 @@ class TextDescriptor extends Descriptor
|
||||
|
||||
foreach ($namespace['commands'] as $name) {
|
||||
$this->writeText("\n");
|
||||
$spacingWidth = $width - strlen($name);
|
||||
$spacingWidth = $width - Helper::strlen($name);
|
||||
$this->writeText(sprintf(' <info>%s</info>%s%s', $name, str_repeat(' ', $spacingWidth), $description->getCommand($name)->getDescription()), $options);
|
||||
}
|
||||
}
|
||||
@@ -235,6 +237,16 @@ class TextDescriptor extends Descriptor
|
||||
*/
|
||||
private function formatDefaultValue($default)
|
||||
{
|
||||
if (is_string($default)) {
|
||||
$default = OutputFormatter::escape($default);
|
||||
} elseif (is_array($default)) {
|
||||
foreach ($default as $key => $value) {
|
||||
if (is_string($value)) {
|
||||
$default[$key] = OutputFormatter::escape($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PHP_VERSION_ID < 50400) {
|
||||
return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default));
|
||||
}
|
||||
@@ -252,9 +264,9 @@ class TextDescriptor extends Descriptor
|
||||
$widths = array();
|
||||
|
||||
foreach ($commands as $command) {
|
||||
$widths[] = strlen($command->getName());
|
||||
$widths[] = Helper::strlen($command->getName());
|
||||
foreach ($command->getAliases() as $alias) {
|
||||
$widths[] = strlen($alias);
|
||||
$widths[] = Helper::strlen($alias);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,10 +283,10 @@ class TextDescriptor extends Descriptor
|
||||
$totalWidth = 0;
|
||||
foreach ($options as $option) {
|
||||
// "-" + shortcut + ", --" + name
|
||||
$nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + strlen($option->getName());
|
||||
$nameLength = 1 + max(strlen($option->getShortcut()), 1) + 4 + Helper::strlen($option->getName());
|
||||
|
||||
if ($option->acceptValue()) {
|
||||
$valueLength = 1 + strlen($option->getName()); // = + value
|
||||
$valueLength = 1 + Helper::strlen($option->getName()); // = + value
|
||||
$valueLength += $option->isValueOptional() ? 2 : 0; // [ + ]
|
||||
|
||||
$nameLength += $valueLength;
|
||||
|
||||
@@ -21,10 +21,10 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce
|
||||
private $alternatives;
|
||||
|
||||
/**
|
||||
* @param string $message Exception message to throw.
|
||||
* @param array $alternatives List of similar defined names.
|
||||
* @param int $code Exception code.
|
||||
* @param Exception $previous previous exception used for the exception chaining.
|
||||
* @param string $message Exception message to throw
|
||||
* @param array $alternatives List of similar defined names
|
||||
* @param int $code Exception code
|
||||
* @param Exception $previous previous exception used for the exception chaining
|
||||
*/
|
||||
public function __construct($message, array $alternatives = array(), $code = 0, \Exception $previous = null)
|
||||
{
|
||||
@@ -34,7 +34,7 @@ class CommandNotFoundException extends \InvalidArgumentException implements Exce
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array A list of similar defined names.
|
||||
* @return array A list of similar defined names
|
||||
*/
|
||||
public function getAlternatives()
|
||||
{
|
||||
|
||||
+15
-1
@@ -35,6 +35,20 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
{
|
||||
$text = preg_replace('/([^\\\\]?)</', '$1\\<', $text);
|
||||
|
||||
return self::escapeTrailingBackslash($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Escapes trailing "\" in given text.
|
||||
*
|
||||
* @param string $text Text to escape
|
||||
*
|
||||
* @return string Escaped text
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public static function escapeTrailingBackslash($text)
|
||||
{
|
||||
if ('\\' === substr($text, -1)) {
|
||||
$len = strlen($text);
|
||||
$text = rtrim($text, '\\');
|
||||
@@ -194,7 +208,7 @@ class OutputFormatter implements OutputFormatterInterface
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return OutputFormatterStyle|bool false if string is not format string
|
||||
* @return OutputFormatterStyle|false false if string is not format string
|
||||
*/
|
||||
private function createStyleFromString($string)
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ class OutputFormatterStyleStack
|
||||
/**
|
||||
* @param OutputFormatterStyleInterface $emptyStyle
|
||||
*
|
||||
* @return OutputFormatterStyleStack
|
||||
* @return $this
|
||||
*/
|
||||
public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
|
||||
{
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ class DescriptorHelper extends Helper
|
||||
* @param string $format
|
||||
* @param DescriptorInterface $descriptor
|
||||
*
|
||||
* @return DescriptorHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function register($format, DescriptorInterface $descriptor)
|
||||
{
|
||||
|
||||
+17
-15
@@ -35,7 +35,7 @@ abstract class Helper implements HelperInterface
|
||||
/**
|
||||
* Gets the helper set associated with this helper.
|
||||
*
|
||||
* @return HelperSet A HelperSet instance
|
||||
* @return HelperSet|null
|
||||
*/
|
||||
public function getHelperSet()
|
||||
{
|
||||
@@ -62,26 +62,28 @@ abstract class Helper implements HelperInterface
|
||||
{
|
||||
static $timeFormats = array(
|
||||
array(0, '< 1 sec'),
|
||||
array(2, '1 sec'),
|
||||
array(59, 'secs', 1),
|
||||
array(1, '1 sec'),
|
||||
array(2, 'secs', 1),
|
||||
array(60, '1 min'),
|
||||
array(3600, 'mins', 60),
|
||||
array(5400, '1 hr'),
|
||||
array(86400, 'hrs', 3600),
|
||||
array(129600, '1 day'),
|
||||
array(604800, 'days', 86400),
|
||||
array(120, 'mins', 60),
|
||||
array(3600, '1 hr'),
|
||||
array(7200, 'hrs', 3600),
|
||||
array(86400, '1 day'),
|
||||
array(172800, 'days', 86400),
|
||||
);
|
||||
|
||||
foreach ($timeFormats as $format) {
|
||||
foreach ($timeFormats as $index => $format) {
|
||||
if ($secs >= $format[0]) {
|
||||
continue;
|
||||
}
|
||||
if ((isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0])
|
||||
|| $index == count($timeFormats) - 1
|
||||
) {
|
||||
if (2 == count($format)) {
|
||||
return $format[1];
|
||||
}
|
||||
|
||||
if (2 == count($format)) {
|
||||
return $format[1];
|
||||
return floor($secs / $format[2]).' '.$format[1];
|
||||
}
|
||||
}
|
||||
|
||||
return ceil($secs / $format[2]).' '.$format[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-1
@@ -21,13 +21,16 @@ use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
*/
|
||||
class HelperSet implements \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* @var Helper[]
|
||||
*/
|
||||
private $helpers = array();
|
||||
private $command;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Helper[] $helpers An array of helper.
|
||||
* @param Helper[] $helpers An array of helper
|
||||
*/
|
||||
public function __construct(array $helpers = array())
|
||||
{
|
||||
@@ -110,6 +113,9 @@ class HelperSet implements \IteratorAggregate
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Helper[]
|
||||
*/
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->helpers);
|
||||
|
||||
+25
-26
@@ -41,10 +41,10 @@ class ProgressBar
|
||||
private $startTime;
|
||||
private $stepWidth;
|
||||
private $percent = 0.0;
|
||||
private $lastMessagesLength = 0;
|
||||
private $formatLineCount;
|
||||
private $messages;
|
||||
private $messages = array();
|
||||
private $overwrite = true;
|
||||
private $firstRun = true;
|
||||
|
||||
private static $formatters;
|
||||
private static $formats;
|
||||
@@ -141,6 +141,16 @@ class ProgressBar
|
||||
return isset(self::$formats[$name]) ? self::$formats[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates a text with a named placeholder.
|
||||
*
|
||||
* The text is displayed when the progress bar is rendered but only
|
||||
* when the corresponding placeholder is part of the custom format line
|
||||
* (by wrapping the name with %).
|
||||
*
|
||||
* @param string $message The text to associate with the placeholder
|
||||
* @param string $name The name of the placeholder
|
||||
*/
|
||||
public function setMessage($message, $name = 'message')
|
||||
{
|
||||
$this->messages[$name] = $message;
|
||||
@@ -473,7 +483,7 @@ class ProgressBar
|
||||
$this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
|
||||
}
|
||||
|
||||
$this->overwrite(str_repeat("\n", $this->formatLineCount));
|
||||
$this->overwrite('');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -513,37 +523,26 @@ class ProgressBar
|
||||
*/
|
||||
private function overwrite($message)
|
||||
{
|
||||
$lines = explode("\n", $message);
|
||||
if ($this->overwrite) {
|
||||
if (!$this->firstRun) {
|
||||
// Move the cursor to the beginning of the line
|
||||
$this->output->write("\x0D");
|
||||
|
||||
// append whitespace to match the line's length
|
||||
if (null !== $this->lastMessagesLength) {
|
||||
foreach ($lines as $i => $line) {
|
||||
if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $line)) {
|
||||
$lines[$i] = str_pad($line, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
|
||||
// Erase the line
|
||||
$this->output->write("\x1B[2K");
|
||||
|
||||
// Erase previous lines
|
||||
if ($this->formatLineCount > 0) {
|
||||
$this->output->write(str_repeat("\x1B[1A\x1B[2K", $this->formatLineCount));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->overwrite) {
|
||||
// move back to the beginning of the progress bar before redrawing it
|
||||
$this->output->write("\x0D");
|
||||
} elseif ($this->step > 0) {
|
||||
// move to new line
|
||||
$this->output->writeln('');
|
||||
}
|
||||
|
||||
if ($this->formatLineCount) {
|
||||
$this->output->write(sprintf("\033[%dA", $this->formatLineCount));
|
||||
}
|
||||
$this->output->write(implode("\n", $lines));
|
||||
$this->firstRun = false;
|
||||
|
||||
$this->lastMessagesLength = 0;
|
||||
foreach ($lines as $line) {
|
||||
$len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $line);
|
||||
if ($len > $this->lastMessagesLength) {
|
||||
$this->lastMessagesLength = $len;
|
||||
}
|
||||
}
|
||||
$this->output->write($message);
|
||||
}
|
||||
|
||||
private function determineBestFormat()
|
||||
|
||||
@@ -372,8 +372,6 @@ class ProgressHelper extends Helper
|
||||
}
|
||||
|
||||
if (isset($this->formatVars['bar'])) {
|
||||
$completeBars = 0;
|
||||
|
||||
if ($this->max > 0) {
|
||||
$completeBars = floor($percent * $this->barWidth);
|
||||
} else {
|
||||
|
||||
+7
-22
@@ -11,6 +11,8 @@
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\LogicException;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/**
|
||||
@@ -26,7 +28,6 @@ class ProgressIndicator
|
||||
private $indicatorCurrent;
|
||||
private $indicatorChangeInterval;
|
||||
private $indicatorUpdateTime;
|
||||
private $lastMessagesLength;
|
||||
private $started = false;
|
||||
|
||||
private static $formatters;
|
||||
@@ -53,7 +54,7 @@ class ProgressIndicator
|
||||
$indicatorValues = array_values($indicatorValues);
|
||||
|
||||
if (2 > count($indicatorValues)) {
|
||||
throw new \InvalidArgumentException('Must have at least 2 indicator value characters.');
|
||||
throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
|
||||
}
|
||||
|
||||
$this->format = self::getFormatDefinition($format);
|
||||
@@ -118,12 +119,11 @@ class ProgressIndicator
|
||||
public function start($message)
|
||||
{
|
||||
if ($this->started) {
|
||||
throw new \LogicException('Progress indicator already started.');
|
||||
throw new LogicException('Progress indicator already started.');
|
||||
}
|
||||
|
||||
$this->message = $message;
|
||||
$this->started = true;
|
||||
$this->lastMessagesLength = 0;
|
||||
$this->startTime = time();
|
||||
$this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
|
||||
$this->indicatorCurrent = 0;
|
||||
@@ -137,7 +137,7 @@ class ProgressIndicator
|
||||
public function advance()
|
||||
{
|
||||
if (!$this->started) {
|
||||
throw new \LogicException('Progress indicator has not yet been started.');
|
||||
throw new LogicException('Progress indicator has not yet been started.');
|
||||
}
|
||||
|
||||
if (!$this->output->isDecorated()) {
|
||||
@@ -164,7 +164,7 @@ class ProgressIndicator
|
||||
public function finish($message)
|
||||
{
|
||||
if (!$this->started) {
|
||||
throw new \LogicException('Progress indicator has not yet been started.');
|
||||
throw new LogicException('Progress indicator has not yet been started.');
|
||||
}
|
||||
|
||||
$this->message = $message;
|
||||
@@ -260,27 +260,12 @@ class ProgressIndicator
|
||||
*/
|
||||
private function overwrite($message)
|
||||
{
|
||||
// append whitespace to match the line's length
|
||||
if (null !== $this->lastMessagesLength) {
|
||||
if ($this->lastMessagesLength > Helper::strlenWithoutDecoration($this->output->getFormatter(), $message)) {
|
||||
$message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->output->isDecorated()) {
|
||||
$this->output->write("\x0D");
|
||||
$this->output->write("\x0D\x1B[2K");
|
||||
$this->output->write($message);
|
||||
} else {
|
||||
$this->output->writeln($message);
|
||||
}
|
||||
|
||||
$this->lastMessagesLength = 0;
|
||||
|
||||
$len = Helper::strlenWithoutDecoration($this->output->getFormatter(), $message);
|
||||
|
||||
if ($len > $this->lastMessagesLength) {
|
||||
$this->lastMessagesLength = $len;
|
||||
}
|
||||
}
|
||||
|
||||
private function getCurrentTimeInMilliseconds()
|
||||
|
||||
+8
-4
@@ -38,7 +38,7 @@ class QuestionHelper extends Helper
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
* @param Question $question The question to ask
|
||||
*
|
||||
* @return string The user answer
|
||||
* @return mixed The user answer
|
||||
*
|
||||
* @throws RuntimeException If there is no data to read in the input stream
|
||||
*/
|
||||
@@ -136,7 +136,7 @@ class QuestionHelper extends Helper
|
||||
if (false === $ret) {
|
||||
$ret = fgets($inputStream, 4096);
|
||||
if (false === $ret) {
|
||||
throw new \RuntimeException('Aborted');
|
||||
throw new RuntimeException('Aborted');
|
||||
}
|
||||
$ret = trim($ret);
|
||||
}
|
||||
@@ -202,6 +202,7 @@ class QuestionHelper extends Helper
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param Question $question
|
||||
* @param resource $inputStream
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
@@ -318,7 +319,8 @@ class QuestionHelper extends Helper
|
||||
/**
|
||||
* Gets a hidden response from user.
|
||||
*
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param resource $inputStream The handler resource
|
||||
*
|
||||
* @return string The answer
|
||||
*
|
||||
@@ -382,7 +384,7 @@ class QuestionHelper extends Helper
|
||||
* @param OutputInterface $output An Output instance
|
||||
* @param Question $question A Question instance
|
||||
*
|
||||
* @return string The validated response
|
||||
* @return mixed The validated response
|
||||
*
|
||||
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
|
||||
*/
|
||||
@@ -397,6 +399,8 @@ class QuestionHelper extends Helper
|
||||
|
||||
try {
|
||||
return call_user_func($question->getValidator(), $interviewer());
|
||||
} catch (RuntimeException $e) {
|
||||
throw $e;
|
||||
} catch (\Exception $error) {
|
||||
}
|
||||
}
|
||||
|
||||
+21
-8
@@ -18,6 +18,7 @@ use Symfony\Component\Console\Question\ChoiceQuestion;
|
||||
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
||||
use Symfony\Component\Console\Question\Question;
|
||||
use Symfony\Component\Console\Style\SymfonyStyle;
|
||||
use Symfony\Component\Console\Formatter\OutputFormatter;
|
||||
|
||||
/**
|
||||
* Symfony Style Guide compliant question helper.
|
||||
@@ -35,11 +36,11 @@ class SymfonyQuestionHelper extends QuestionHelper
|
||||
$question->setValidator(function ($value) use ($validator) {
|
||||
if (null !== $validator) {
|
||||
$value = $validator($value);
|
||||
}
|
||||
|
||||
// make required
|
||||
if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
|
||||
throw new LogicException('A value is required.');
|
||||
} else {
|
||||
// make required
|
||||
if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) {
|
||||
throw new LogicException('A value is required.');
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
@@ -53,7 +54,7 @@ class SymfonyQuestionHelper extends QuestionHelper
|
||||
*/
|
||||
protected function writePrompt(OutputInterface $output, Question $question)
|
||||
{
|
||||
$text = $question->getQuestion();
|
||||
$text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
|
||||
$default = $question->getDefault();
|
||||
|
||||
switch (true) {
|
||||
@@ -67,14 +68,26 @@ class SymfonyQuestionHelper extends QuestionHelper
|
||||
|
||||
break;
|
||||
|
||||
case $question instanceof ChoiceQuestion && $question->isMultiselect():
|
||||
$choices = $question->getChoices();
|
||||
$default = explode(',', $default);
|
||||
|
||||
foreach ($default as $key => $value) {
|
||||
$default[$key] = $choices[trim($value)];
|
||||
}
|
||||
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(implode(', ', $default)));
|
||||
|
||||
break;
|
||||
|
||||
case $question instanceof ChoiceQuestion:
|
||||
$choices = $question->getChoices();
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $choices[$default]);
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default]));
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, $default);
|
||||
$text = sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
|
||||
}
|
||||
|
||||
$output->writeln($text);
|
||||
|
||||
+48
-35
@@ -100,7 +100,7 @@ class Table
|
||||
*
|
||||
* @param string $name The style name
|
||||
*
|
||||
* @return TableStyle A TableStyle instance
|
||||
* @return TableStyle
|
||||
*/
|
||||
public static function getStyleDefinition($name)
|
||||
{
|
||||
@@ -108,11 +108,11 @@ class Table
|
||||
self::$styles = self::initStyles();
|
||||
}
|
||||
|
||||
if (!self::$styles[$name]) {
|
||||
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
if (isset(self::$styles[$name])) {
|
||||
return self::$styles[$name];
|
||||
}
|
||||
|
||||
return self::$styles[$name];
|
||||
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,17 +120,11 @@ class Table
|
||||
*
|
||||
* @param TableStyle|string $name The style name or a TableStyle instance
|
||||
*
|
||||
* @return Table
|
||||
* @return $this
|
||||
*/
|
||||
public function setStyle($name)
|
||||
{
|
||||
if ($name instanceof TableStyle) {
|
||||
$this->style = $name;
|
||||
} elseif (isset(self::$styles[$name])) {
|
||||
$this->style = self::$styles[$name];
|
||||
} else {
|
||||
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
}
|
||||
$this->style = $this->resolveStyle($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -151,19 +145,13 @@ class Table
|
||||
* @param int $columnIndex Column index
|
||||
* @param TableStyle|string $name The style name or a TableStyle instance
|
||||
*
|
||||
* @return Table
|
||||
* @return $this
|
||||
*/
|
||||
public function setColumnStyle($columnIndex, $name)
|
||||
{
|
||||
$columnIndex = intval($columnIndex);
|
||||
|
||||
if ($name instanceof TableStyle) {
|
||||
$this->columnStyles[$columnIndex] = $name;
|
||||
} elseif (isset(self::$styles[$name])) {
|
||||
$this->columnStyles[$columnIndex] = self::$styles[$name];
|
||||
} else {
|
||||
throw new \InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
}
|
||||
$this->columnStyles[$columnIndex] = $this->resolveStyle($name);
|
||||
|
||||
return $this;
|
||||
}
|
||||
@@ -307,7 +295,7 @@ class Table
|
||||
*/
|
||||
private function renderColumnSeparator()
|
||||
{
|
||||
$this->output->write(sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar()));
|
||||
return sprintf($this->style->getBorderFormat(), $this->style->getVerticalBorderChar());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,12 +312,12 @@ class Table
|
||||
return;
|
||||
}
|
||||
|
||||
$this->renderColumnSeparator();
|
||||
$rowContent = $this->renderColumnSeparator();
|
||||
foreach ($this->getRowColumns($row) as $column) {
|
||||
$this->renderCell($row, $column, $cellFormat);
|
||||
$this->renderColumnSeparator();
|
||||
$rowContent .= $this->renderCell($row, $column, $cellFormat);
|
||||
$rowContent .= $this->renderColumnSeparator();
|
||||
}
|
||||
$this->output->writeln('');
|
||||
$this->output->writeln($rowContent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,12 +346,13 @@ class Table
|
||||
$style = $this->getColumnStyle($column);
|
||||
|
||||
if ($cell instanceof TableSeparator) {
|
||||
$this->output->write(sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width)));
|
||||
} else {
|
||||
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
|
||||
$content = sprintf($style->getCellRowContentFormat(), $cell);
|
||||
$this->output->write(sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType())));
|
||||
return sprintf($style->getBorderFormat(), str_repeat($style->getHorizontalBorderChar(), $width));
|
||||
}
|
||||
|
||||
$width += Helper::strlen($cell) - Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
|
||||
$content = sprintf($style->getCellRowContentFormat(), $cell);
|
||||
|
||||
return sprintf($cellFormat, str_pad($content, $width, $style->getPaddingChar(), $style->getPadType()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,10 +436,13 @@ class Table
|
||||
}
|
||||
|
||||
// create a two dimensional array (rowspan x colspan)
|
||||
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, ''), $unmergedRows);
|
||||
$unmergedRows = array_replace_recursive(array_fill($line + 1, $nbLines, array()), $unmergedRows);
|
||||
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
|
||||
$value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
|
||||
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
|
||||
if ($nbLines === $unmergedRowKey - $line) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -569,6 +561,18 @@ class Table
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($row as $i => $cell) {
|
||||
if ($cell instanceof TableCell) {
|
||||
$textLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
|
||||
if ($textLength > 0) {
|
||||
$contentColumns = str_split($cell, ceil($textLength / $cell->getColspan()));
|
||||
foreach ($contentColumns as $position => $content) {
|
||||
$row[$i + $position] = $content;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$lengths[] = $this->getCellWidth($row, $column);
|
||||
}
|
||||
|
||||
@@ -599,10 +603,6 @@ class Table
|
||||
if (isset($row[$column])) {
|
||||
$cell = $row[$column];
|
||||
$cellWidth = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
|
||||
if ($cell instanceof TableCell && $cell->getColspan() > 1) {
|
||||
// we assume that cell value will be across more than one column.
|
||||
$cellWidth = $cellWidth / $cell->getColspan();
|
||||
}
|
||||
|
||||
return $cellWidth;
|
||||
}
|
||||
@@ -651,4 +651,17 @@ class Table
|
||||
'symfony-style-guide' => $styleGuide,
|
||||
);
|
||||
}
|
||||
|
||||
private function resolveStyle($name)
|
||||
{
|
||||
if ($name instanceof TableStyle) {
|
||||
return $name;
|
||||
}
|
||||
|
||||
if (isset(self::$styles[$name])) {
|
||||
return self::$styles[$name];
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException(sprintf('Style "%s" is not defined.', $name));
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -37,6 +37,10 @@ class TableCell
|
||||
*/
|
||||
public function __construct($value = '', array $options = array())
|
||||
{
|
||||
if (is_numeric($value) && !is_string($value)) {
|
||||
$value = (string) $value;
|
||||
}
|
||||
|
||||
$this->value = $value;
|
||||
|
||||
// check option names
|
||||
|
||||
+10
-10
@@ -49,7 +49,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param int $layout self::LAYOUT_*
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException when the table layout is not known
|
||||
*/
|
||||
@@ -115,7 +115,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $paddingChar
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setPaddingChar($paddingChar)
|
||||
{
|
||||
@@ -129,7 +129,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $horizontalBorderChar
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setHorizontalBorderChar($horizontalBorderChar)
|
||||
{
|
||||
@@ -143,7 +143,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $verticalBorderChar
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setVerticalBorderChar($verticalBorderChar)
|
||||
{
|
||||
@@ -157,7 +157,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $crossingChar
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setCrossingChar($crossingChar)
|
||||
{
|
||||
@@ -171,7 +171,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $cellHeaderFormat
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellHeaderFormat($cellHeaderFormat)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $cellRowFormat
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowFormat($cellRowFormat)
|
||||
{
|
||||
@@ -199,7 +199,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $cellRowContentFormat
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowContentFormat($cellRowContentFormat)
|
||||
{
|
||||
@@ -213,7 +213,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param string $borderFormat
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setBorderFormat($borderFormat)
|
||||
{
|
||||
@@ -227,7 +227,7 @@ class TableHelper extends Helper
|
||||
*
|
||||
* @param int $padType STR_PAD_*
|
||||
*
|
||||
* @return TableHelper
|
||||
* @return $this
|
||||
*/
|
||||
public function setPadType($padType)
|
||||
{
|
||||
|
||||
+1
-2
@@ -19,8 +19,7 @@ namespace Symfony\Component\Console\Helper;
|
||||
class TableSeparator extends TableCell
|
||||
{
|
||||
/**
|
||||
* @param string $value
|
||||
* @param array $options
|
||||
* @param array $options
|
||||
*/
|
||||
public function __construct(array $options = array())
|
||||
{
|
||||
|
||||
+9
-9
@@ -37,7 +37,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $paddingChar
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setPaddingChar($paddingChar)
|
||||
{
|
||||
@@ -65,7 +65,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $horizontalBorderChar
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setHorizontalBorderChar($horizontalBorderChar)
|
||||
{
|
||||
@@ -89,7 +89,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $verticalBorderChar
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setVerticalBorderChar($verticalBorderChar)
|
||||
{
|
||||
@@ -113,7 +113,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $crossingChar
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setCrossingChar($crossingChar)
|
||||
{
|
||||
@@ -137,7 +137,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $cellHeaderFormat
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellHeaderFormat($cellHeaderFormat)
|
||||
{
|
||||
@@ -161,7 +161,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $cellRowFormat
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowFormat($cellRowFormat)
|
||||
{
|
||||
@@ -185,7 +185,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $cellRowContentFormat
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setCellRowContentFormat($cellRowContentFormat)
|
||||
{
|
||||
@@ -209,7 +209,7 @@ class TableStyle
|
||||
*
|
||||
* @param string $borderFormat
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setBorderFormat($borderFormat)
|
||||
{
|
||||
@@ -233,7 +233,7 @@ class TableStyle
|
||||
*
|
||||
* @param int $padType STR_PAD_*
|
||||
*
|
||||
* @return TableStyle
|
||||
* @return $this
|
||||
*/
|
||||
public function setPadType($padType)
|
||||
{
|
||||
|
||||
+18
-27
@@ -46,8 +46,8 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv An array of parameters from the CLI (in the argv format)
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
* @param array|null $argv An array of parameters from the CLI (in the argv format)
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $argv = null, InputDefinition $definition = null)
|
||||
{
|
||||
@@ -69,7 +69,7 @@ class ArgvInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command line arguments.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function parse()
|
||||
{
|
||||
@@ -93,7 +93,7 @@ class ArgvInput extends Input
|
||||
/**
|
||||
* Parses a short option.
|
||||
*
|
||||
* @param string $token The current token.
|
||||
* @param string $token The current token
|
||||
*/
|
||||
private function parseShortOption($token)
|
||||
{
|
||||
@@ -147,7 +147,10 @@ class ArgvInput extends Input
|
||||
$name = substr($token, 2);
|
||||
|
||||
if (false !== $pos = strpos($name, '=')) {
|
||||
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
|
||||
if (0 === strlen($value = substr($name, $pos + 1))) {
|
||||
array_unshift($this->parsed, null);
|
||||
}
|
||||
$this->addLongOption(substr($name, 0, $pos), $value);
|
||||
} else {
|
||||
$this->addLongOption($name, null);
|
||||
}
|
||||
@@ -176,7 +179,12 @@ class ArgvInput extends Input
|
||||
|
||||
// unexpected argument
|
||||
} else {
|
||||
throw new RuntimeException('Too many arguments.');
|
||||
$all = $this->definition->getArguments();
|
||||
if (count($all)) {
|
||||
throw new RuntimeException(sprintf('Too many arguments, expected arguments "%s".', implode('" "', array_keys($all))));
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('No arguments expected, got "%s".', $token));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +237,7 @@ class ArgvInput extends Input
|
||||
if (isset($next[0]) && '-' !== $next[0]) {
|
||||
$value = $next;
|
||||
} elseif (empty($next)) {
|
||||
$value = '';
|
||||
$value = null;
|
||||
} else {
|
||||
array_unshift($this->parsed, $next);
|
||||
}
|
||||
@@ -253,9 +261,7 @@ class ArgvInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
{
|
||||
@@ -269,14 +275,7 @@ class ArgvInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contain a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
*
|
||||
* @return bool true if the value is contained in the raw parameters
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasParameterOption($values)
|
||||
{
|
||||
@@ -294,15 +293,7 @@ class ArgvInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a raw option (not parsed).
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
* @param mixed $default The default value to return if no result is found
|
||||
*
|
||||
* @return mixed The option value
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParameterOption($values, $default = false)
|
||||
{
|
||||
|
||||
+6
-23
@@ -30,8 +30,8 @@ class ArrayInput extends Input
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
* @param array $parameters An array of parameters
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $parameters, InputDefinition $definition = null)
|
||||
{
|
||||
@@ -41,9 +41,7 @@ class ArrayInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
{
|
||||
@@ -57,14 +55,7 @@ class ArrayInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contain a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $values The values to look for in the raw parameters (can be an array)
|
||||
*
|
||||
* @return bool true if the value is contained in the raw parameters
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasParameterOption($values)
|
||||
{
|
||||
@@ -84,15 +75,7 @@ class ArrayInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of a raw option (not parsed).
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before they have been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
* @param mixed $default The default value to return if no result is found
|
||||
*
|
||||
* @return mixed The option value
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getParameterOption($values, $default = false)
|
||||
{
|
||||
@@ -131,7 +114,7 @@ class ArrayInput extends Input
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command line arguments.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function parse()
|
||||
{
|
||||
|
||||
+13
-55
@@ -38,7 +38,7 @@ abstract class Input implements InputInterface
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
* @param InputDefinition|null $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(InputDefinition $definition = null)
|
||||
{
|
||||
@@ -51,9 +51,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the current Input instance with the given arguments and options.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function bind(InputDefinition $definition)
|
||||
{
|
||||
@@ -70,9 +68,7 @@ abstract class Input implements InputInterface
|
||||
abstract protected function parse();
|
||||
|
||||
/**
|
||||
* Validates the input.
|
||||
*
|
||||
* @throws RuntimeException When not enough arguments are given
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function validate()
|
||||
{
|
||||
@@ -89,9 +85,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the input is interactive.
|
||||
*
|
||||
* @return bool Returns true if the input is interactive
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isInteractive()
|
||||
{
|
||||
@@ -99,9 +93,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the input interactivity.
|
||||
*
|
||||
* @param bool $interactive If the input should be interactive
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setInteractive($interactive)
|
||||
{
|
||||
@@ -109,9 +101,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument values.
|
||||
*
|
||||
* @return array An array of argument values
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
@@ -119,13 +109,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument value for a given argument name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
*
|
||||
* @return mixed The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getArgument($name)
|
||||
{
|
||||
@@ -137,12 +121,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an argument value by name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param string $value The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setArgument($name, $value)
|
||||
{
|
||||
@@ -154,11 +133,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputArgument object exists by name or position.
|
||||
*
|
||||
* @param string|int $name The InputArgument name or position
|
||||
*
|
||||
* @return bool true if the InputArgument object exists, false otherwise
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasArgument($name)
|
||||
{
|
||||
@@ -166,9 +141,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the options values.
|
||||
*
|
||||
* @return array An array of option values
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
@@ -176,13 +149,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the option value for a given option name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
*
|
||||
* @return mixed The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getOption($name)
|
||||
{
|
||||
@@ -194,12 +161,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an option value by name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string|bool $value The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setOption($name, $value)
|
||||
{
|
||||
@@ -211,11 +173,7 @@ abstract class Input implements InputInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return bool true if the InputOption object exists, false otherwise
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function hasOption($name)
|
||||
{
|
||||
|
||||
@@ -284,6 +284,9 @@ class InputDefinition
|
||||
/**
|
||||
* Returns true if an InputOption object exists by name.
|
||||
*
|
||||
* This method can't be used to check if the user included the option when
|
||||
* executing the command (use getOption() instead).
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return bool true if the InputOption object exists, false otherwise
|
||||
|
||||
+15
-10
@@ -11,6 +11,9 @@
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
use Symfony\Component\Console\Exception\InvalidArgumentException;
|
||||
use Symfony\Component\Console\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* InputInterface is the interface implemented by all input classes.
|
||||
*
|
||||
@@ -58,11 +61,9 @@ interface InputInterface
|
||||
public function bind(InputDefinition $definition);
|
||||
|
||||
/**
|
||||
* Validates if arguments given are correct.
|
||||
* Validates the input.
|
||||
*
|
||||
* Throws an exception when not enough arguments are given.
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
* @throws RuntimeException When not enough arguments are given
|
||||
*/
|
||||
public function validate();
|
||||
|
||||
@@ -74,11 +75,13 @@ interface InputInterface
|
||||
public function getArguments();
|
||||
|
||||
/**
|
||||
* Gets argument by name.
|
||||
* Returns the argument value for a given argument name.
|
||||
*
|
||||
* @param string $name The name of the argument
|
||||
* @param string $name The argument name
|
||||
*
|
||||
* @return mixed
|
||||
* @return mixed The argument value
|
||||
*
|
||||
* @throws InvalidArgumentException When argument given doesn't exist
|
||||
*/
|
||||
public function getArgument($name);
|
||||
|
||||
@@ -109,11 +112,13 @@ interface InputInterface
|
||||
public function getOptions();
|
||||
|
||||
/**
|
||||
* Gets an option by name.
|
||||
* Returns the option value for a given option name.
|
||||
*
|
||||
* @param string $name The name of the option
|
||||
* @param string $name The option name
|
||||
*
|
||||
* @return mixed
|
||||
* @return mixed The option value
|
||||
*
|
||||
* @throws InvalidArgumentException When option given doesn't exist
|
||||
*/
|
||||
public function getOption($name);
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2016 Fabien Potencier
|
||||
Copyright (c) 2004-2017 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
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ use Symfony\Component\Console\Output\ConsoleOutputInterface;
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*
|
||||
* @link http://www.php-fig.org/psr/psr-3/
|
||||
* @see http://www.php-fig.org/psr/psr-3/
|
||||
*/
|
||||
class ConsoleLogger extends AbstractLogger
|
||||
{
|
||||
|
||||
+12
@@ -73,21 +73,33 @@ class NullOutput implements OutputInterface
|
||||
return self::VERBOSITY_QUIET;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug()
|
||||
{
|
||||
return false;
|
||||
|
||||
+12
@@ -94,21 +94,33 @@ abstract class Output implements OutputInterface
|
||||
return $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isQuiet()
|
||||
{
|
||||
return self::VERBOSITY_QUIET === $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVerbose()
|
||||
{
|
||||
return self::VERBOSITY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isVeryVerbose()
|
||||
{
|
||||
return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isDebug()
|
||||
{
|
||||
return self::VERBOSITY_DEBUG <= $this->verbosity;
|
||||
|
||||
+7
-3
@@ -72,7 +72,7 @@ class StreamOutput extends Output
|
||||
*/
|
||||
protected function doWrite($message, $newline)
|
||||
{
|
||||
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : ''))) {
|
||||
if (false === @fwrite($this->stream, $message) || ($newline && (false === @fwrite($this->stream, PHP_EOL)))) {
|
||||
// should never happen
|
||||
throw new RuntimeException('Unable to write output.');
|
||||
}
|
||||
@@ -85,7 +85,7 @@ class StreamOutput extends Output
|
||||
*
|
||||
* Colorization is disabled if not supported by the stream:
|
||||
*
|
||||
* - Windows without Ansicon, ConEmu or Mintty
|
||||
* - Windows != 10.0.10586 without Ansicon, ConEmu or Mintty
|
||||
* - non tty consoles
|
||||
*
|
||||
* @return bool true if the stream supports colorization, false otherwise
|
||||
@@ -93,7 +93,11 @@ class StreamOutput extends Output
|
||||
protected function hasColorSupport()
|
||||
{
|
||||
if (DIRECTORY_SEPARATOR === '\\') {
|
||||
return false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI') || 'xterm' === getenv('TERM');
|
||||
return
|
||||
'10.0.10586' === PHP_WINDOWS_VERSION_MAJOR.'.'.PHP_WINDOWS_VERSION_MINOR.'.'.PHP_WINDOWS_VERSION_BUILD
|
||||
|| false !== getenv('ANSICON')
|
||||
|| 'ON' === getenv('ConEmuANSI')
|
||||
|| 'xterm' === getenv('TERM');
|
||||
}
|
||||
|
||||
return function_exists('posix_isatty') && @posix_isatty($this->stream);
|
||||
|
||||
+13
-3
@@ -58,7 +58,7 @@ class ChoiceQuestion extends Question
|
||||
*
|
||||
* @param bool $multiselect
|
||||
*
|
||||
* @return ChoiceQuestion The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setMultiselect($multiselect)
|
||||
{
|
||||
@@ -68,6 +68,16 @@ class ChoiceQuestion extends Question
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the choices are multiselect.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isMultiselect()
|
||||
{
|
||||
return $this->multiselect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the prompt for choices.
|
||||
*
|
||||
@@ -83,7 +93,7 @@ class ChoiceQuestion extends Question
|
||||
*
|
||||
* @param string $prompt
|
||||
*
|
||||
* @return ChoiceQuestion The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setPrompt($prompt)
|
||||
{
|
||||
@@ -99,7 +109,7 @@ class ChoiceQuestion extends Question
|
||||
*
|
||||
* @param string $errorMessage
|
||||
*
|
||||
* @return ChoiceQuestion The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setErrorMessage($errorMessage)
|
||||
{
|
||||
|
||||
+6
-6
@@ -77,7 +77,7 @@ class Question
|
||||
*
|
||||
* @param bool $hidden
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws LogicException In case the autocompleter is also used
|
||||
*/
|
||||
@@ -107,7 +107,7 @@ class Question
|
||||
*
|
||||
* @param bool $fallback
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setHiddenFallback($fallback)
|
||||
{
|
||||
@@ -131,7 +131,7 @@ class Question
|
||||
*
|
||||
* @param null|array|\Traversable $values
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
* @throws LogicException
|
||||
@@ -162,7 +162,7 @@ class Question
|
||||
*
|
||||
* @param null|callable $validator
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setValidator($validator)
|
||||
{
|
||||
@@ -188,7 +188,7 @@ class Question
|
||||
*
|
||||
* @param null|int $attempts
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException In case the number of attempts is invalid.
|
||||
*/
|
||||
@@ -222,7 +222,7 @@ class Question
|
||||
*
|
||||
* @param callable $normalizer
|
||||
*
|
||||
* @return Question The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setNormalizer($normalizer)
|
||||
{
|
||||
|
||||
+62
-42
@@ -65,40 +65,10 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function block($messages, $type = null, $style = null, $prefix = ' ', $padding = false)
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$messages = is_array($messages) ? array_values($messages) : array($messages);
|
||||
$lines = array();
|
||||
|
||||
// add type
|
||||
if (null !== $type) {
|
||||
$messages[0] = sprintf('[%s] %s', $type, $messages[0]);
|
||||
}
|
||||
|
||||
// wrap and add newlines for each element
|
||||
foreach ($messages as $key => $message) {
|
||||
$message = OutputFormatter::escape($message);
|
||||
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - Helper::strlen($prefix), PHP_EOL, true)));
|
||||
|
||||
if (count($messages) > 1 && $key < count($messages) - 1) {
|
||||
$lines[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
if ($padding && $this->isDecorated()) {
|
||||
array_unshift($lines, '');
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
foreach ($lines as &$line) {
|
||||
$line = sprintf('%s%s', $prefix, $line);
|
||||
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
|
||||
|
||||
if ($style) {
|
||||
$line = sprintf('<%s>%s</>', $style, $line);
|
||||
}
|
||||
}
|
||||
|
||||
$this->writeln($lines);
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, true));
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
@@ -109,7 +79,7 @@ class SymfonyStyle extends OutputStyle
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
sprintf('<comment>%s</>', $message),
|
||||
sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
|
||||
sprintf('<comment>%s</>', str_repeat('=', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
|
||||
));
|
||||
$this->newLine();
|
||||
@@ -122,7 +92,7 @@ class SymfonyStyle extends OutputStyle
|
||||
{
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln(array(
|
||||
sprintf('<comment>%s</>', $message),
|
||||
sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)),
|
||||
sprintf('<comment>%s</>', str_repeat('-', Helper::strlenWithoutDecoration($this->getFormatter(), $message))),
|
||||
));
|
||||
$this->newLine();
|
||||
@@ -156,16 +126,17 @@ class SymfonyStyle extends OutputStyle
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Formats a command comment.
|
||||
*
|
||||
* @param string|array $message
|
||||
*/
|
||||
public function comment($message)
|
||||
{
|
||||
$this->autoPrependText();
|
||||
|
||||
$messages = is_array($message) ? array_values($message) : array($message);
|
||||
foreach ($messages as $message) {
|
||||
$this->writeln(sprintf(' // %s', $message));
|
||||
}
|
||||
|
||||
$this->autoPrependBlock();
|
||||
$this->writeln($this->createBlock($messages, null, null, '<fg=default;bg=default> // </>'));
|
||||
$this->newLine();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,12 +184,13 @@ class SymfonyStyle extends OutputStyle
|
||||
*/
|
||||
public function table(array $headers, array $rows)
|
||||
{
|
||||
$headers = array_map(function ($value) { return sprintf('<info>%s</>', $value); }, $headers);
|
||||
$style = clone Table::getStyleDefinition('symfony-style-guide');
|
||||
$style->setCellHeaderFormat('<info>%s</info>');
|
||||
|
||||
$table = new Table($this);
|
||||
$table->setHeaders($headers);
|
||||
$table->setRows($rows);
|
||||
$table->setStyle('symfony-style-guide');
|
||||
$table->setStyle($style);
|
||||
|
||||
$table->render();
|
||||
$this->newLine();
|
||||
@@ -412,4 +384,52 @@ class SymfonyStyle extends OutputStyle
|
||||
return substr($value, -4);
|
||||
}, array_merge(array($this->bufferedOutput->fetch()), (array) $messages));
|
||||
}
|
||||
|
||||
private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false)
|
||||
{
|
||||
$indentLength = 0;
|
||||
$prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix);
|
||||
$lines = array();
|
||||
|
||||
if (null !== $type) {
|
||||
$type = sprintf('[%s] ', $type);
|
||||
$indentLength = strlen($type);
|
||||
$lineIndentation = str_repeat(' ', $indentLength);
|
||||
}
|
||||
|
||||
// wrap and add newlines for each element
|
||||
foreach ($messages as $key => $message) {
|
||||
if ($escape) {
|
||||
$message = OutputFormatter::escape($message);
|
||||
}
|
||||
|
||||
$lines = array_merge($lines, explode(PHP_EOL, wordwrap($message, $this->lineLength - $prefixLength - $indentLength, PHP_EOL, true)));
|
||||
|
||||
if (count($messages) > 1 && $key < count($messages) - 1) {
|
||||
$lines[] = '';
|
||||
}
|
||||
}
|
||||
|
||||
$firstLineIndex = 0;
|
||||
if ($padding && $this->isDecorated()) {
|
||||
$firstLineIndex = 1;
|
||||
array_unshift($lines, '');
|
||||
$lines[] = '';
|
||||
}
|
||||
|
||||
foreach ($lines as $i => &$line) {
|
||||
if (null !== $type) {
|
||||
$line = $firstLineIndex === $i ? $type.$line : $lineIndentation.$line;
|
||||
}
|
||||
|
||||
$line = $prefix.$line;
|
||||
$line .= str_repeat(' ', $this->lineLength - Helper::strlenWithoutDecoration($this->getFormatter(), $line));
|
||||
|
||||
if ($style) {
|
||||
$line = sprintf('<%s>%s</>', $style, $line);
|
||||
}
|
||||
}
|
||||
|
||||
return $lines;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ class ApplicationTester
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Application $application An Application instance to test.
|
||||
* @param Application $application An Application instance to test
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ class CommandTester
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param Command $command A Command instance to test.
|
||||
* @param Command $command A Command instance to test
|
||||
*/
|
||||
public function __construct(Command $command)
|
||||
{
|
||||
|
||||
Vendored
+2
-1
@@ -17,7 +17,8 @@
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.9",
|
||||
"symfony/polyfill-mbstring": "~1.0"
|
||||
"symfony/polyfill-mbstring": "~1.0",
|
||||
"symfony/debug": "^2.7.2|~3.0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/event-dispatcher": "~2.1|~3.0.0",
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\Debug;
|
||||
|
||||
use Psr\Log\AbstractLogger;
|
||||
|
||||
/**
|
||||
* A buffering logger that stacks logs for later.
|
||||
*
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class BufferingLogger extends AbstractLogger
|
||||
{
|
||||
private $logs = array();
|
||||
|
||||
public function log($level, $message, array $context = array())
|
||||
{
|
||||
$this->logs[] = array($level, $message, $context);
|
||||
}
|
||||
|
||||
public function cleanLogs()
|
||||
{
|
||||
$logs = $this->logs;
|
||||
$this->logs = array();
|
||||
|
||||
return $logs;
|
||||
}
|
||||
}
|
||||
Vendored
+7
@@ -1,6 +1,13 @@
|
||||
CHANGELOG
|
||||
=========
|
||||
|
||||
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
|
||||
|
||||
2.7.0
|
||||
-----
|
||||
|
||||
|
||||
Vendored
+5
-4
@@ -45,16 +45,17 @@ class Debug
|
||||
error_reporting(-1);
|
||||
}
|
||||
|
||||
if ('cli' !== php_sapi_name()) {
|
||||
if ('cli' !== PHP_SAPI) {
|
||||
ini_set('display_errors', 0);
|
||||
ExceptionHandler::register();
|
||||
} elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) {
|
||||
// CLI - display errors only if they're not already logged to STDERR
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
$handler = ErrorHandler::register();
|
||||
if (!$displayErrors) {
|
||||
$handler->throwAt(0, true);
|
||||
if ($displayErrors) {
|
||||
ErrorHandler::register(new ErrorHandler(new BufferingLogger()));
|
||||
} else {
|
||||
ErrorHandler::register()->throwAt(0, true);
|
||||
}
|
||||
|
||||
DebugClassLoader::enable();
|
||||
|
||||
+48
-8
@@ -51,7 +51,26 @@ class DebugClassLoader
|
||||
}
|
||||
|
||||
if (!isset(self::$caseCheck)) {
|
||||
self::$caseCheck = false !== stripos(PHP_OS, 'win') ? (false !== stripos(PHP_OS, 'darwin') ? 2 : 1) : 0;
|
||||
$file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR);
|
||||
$i = strrpos($file, DIRECTORY_SEPARATOR);
|
||||
$dir = substr($file, 0, 1 + $i);
|
||||
$file = substr($file, 1 + $i);
|
||||
$test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file);
|
||||
$test = realpath($dir.$test);
|
||||
|
||||
if (false === $test || false === $i) {
|
||||
// filesystem is case sensitive
|
||||
self::$caseCheck = 0;
|
||||
} elseif (substr($test, -strlen($file)) === $file) {
|
||||
// filesystem is case insensitive and realpath() normalizes the case of characters
|
||||
self::$caseCheck = 1;
|
||||
} elseif (false !== stripos(PHP_OS, 'darwin')) {
|
||||
// on MacOSX, HFS+ is case insensitive but realpath() doesn't normalize the case of characters
|
||||
self::$caseCheck = 2;
|
||||
} else {
|
||||
// filesystem case checks failed, fallback to disabling them
|
||||
self::$caseCheck = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +166,7 @@ class DebugClassLoader
|
||||
try {
|
||||
if ($this->isFinder) {
|
||||
if ($file = $this->classLoader[0]->findFile($class)) {
|
||||
require $file;
|
||||
require_once $file;
|
||||
}
|
||||
} else {
|
||||
call_user_func($this->classLoader, $class);
|
||||
@@ -156,6 +175,10 @@ class DebugClassLoader
|
||||
} catch (\Exception $e) {
|
||||
ErrorHandler::unstackErrors();
|
||||
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
ErrorHandler::unstackErrors();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -193,15 +216,32 @@ class DebugClassLoader
|
||||
break;
|
||||
}
|
||||
}
|
||||
$parent = $refl->getParentClass();
|
||||
$parent = get_parent_class($class);
|
||||
|
||||
if (!$parent || strncmp($ns, $parent->name, $len)) {
|
||||
if ($parent && isset(self::$deprecated[$parent->name]) && strncmp($ns, $parent->name, $len)) {
|
||||
@trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent->name, self::$deprecated[$parent->name]), E_USER_DEPRECATED);
|
||||
if (!$parent || strncmp($ns, $parent, $len)) {
|
||||
if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) {
|
||||
@trigger_error(sprintf('The %s class extends %s that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED);
|
||||
}
|
||||
|
||||
$parentInterfaces = array();
|
||||
$deprecatedInterfaces = array();
|
||||
if ($parent) {
|
||||
foreach (class_implements($parent) as $interface) {
|
||||
$parentInterfaces[$interface] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($refl->getInterfaceNames() as $interface) {
|
||||
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len) && !($parent && $parent->implementsInterface($interface))) {
|
||||
if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) {
|
||||
$deprecatedInterfaces[] = $interface;
|
||||
}
|
||||
foreach (class_implements($interface) as $interface) {
|
||||
$parentInterfaces[$interface] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($deprecatedInterfaces as $interface) {
|
||||
if (!isset($parentInterfaces[$interface])) {
|
||||
@trigger_error(sprintf('The %s %s %s that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +264,7 @@ class DebugClassLoader
|
||||
$i = count($tail) - 1;
|
||||
$j = count($real) - 1;
|
||||
|
||||
while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
|
||||
while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) {
|
||||
--$i;
|
||||
--$j;
|
||||
}
|
||||
|
||||
+116
-17
@@ -95,11 +95,14 @@ class ErrorHandler
|
||||
|
||||
private $loggedTraces = array();
|
||||
private $isRecursive = 0;
|
||||
private $isRoot = false;
|
||||
private $exceptionHandler;
|
||||
private $bootstrappingLogger;
|
||||
|
||||
private static $reservedMemory;
|
||||
private static $stackedErrors = array();
|
||||
private static $stackedErrorLevels = array();
|
||||
private static $toStringException = null;
|
||||
|
||||
/**
|
||||
* Same init value as thrownErrors.
|
||||
@@ -134,7 +137,12 @@ class ErrorHandler
|
||||
$handler = new static();
|
||||
}
|
||||
|
||||
$prev = set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
|
||||
if (null === $prev = set_error_handler(array($handler, 'handleError'))) {
|
||||
restore_error_handler();
|
||||
// Specifying the error types earlier would expose us to https://bugs.php.net/63206
|
||||
set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors);
|
||||
$handler->isRoot = true;
|
||||
}
|
||||
|
||||
if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) {
|
||||
$handler = $prev[0];
|
||||
@@ -151,6 +159,14 @@ class ErrorHandler
|
||||
return $handler;
|
||||
}
|
||||
|
||||
public function __construct(BufferingLogger $bootstrappingLogger = null)
|
||||
{
|
||||
if ($bootstrappingLogger) {
|
||||
$this->bootstrappingLogger = $bootstrappingLogger;
|
||||
$this->setDefaultLogger($bootstrappingLogger);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a logger to non assigned errors levels.
|
||||
*
|
||||
@@ -164,7 +180,7 @@ class ErrorHandler
|
||||
|
||||
if (is_array($levels)) {
|
||||
foreach ($levels as $type => $logLevel) {
|
||||
if (empty($this->loggers[$type][0]) || $replace) {
|
||||
if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) {
|
||||
$loggers[$type] = array($logger, $logLevel);
|
||||
}
|
||||
}
|
||||
@@ -173,7 +189,7 @@ class ErrorHandler
|
||||
$levels = E_ALL | E_STRICT;
|
||||
}
|
||||
foreach ($this->loggers as $type => $log) {
|
||||
if (($type & $levels) && (empty($log[0]) || $replace)) {
|
||||
if (($type & $levels) && (empty($log[0]) || $replace || $log[0] === $this->bootstrappingLogger)) {
|
||||
$log[0] = $logger;
|
||||
$loggers[$type] = $log;
|
||||
}
|
||||
@@ -196,6 +212,7 @@ class ErrorHandler
|
||||
{
|
||||
$prevLogged = $this->loggedErrors;
|
||||
$prev = $this->loggers;
|
||||
$flush = array();
|
||||
|
||||
foreach ($loggers as $type => $log) {
|
||||
if (!isset($prev[$type])) {
|
||||
@@ -214,9 +231,24 @@ class ErrorHandler
|
||||
throw new \InvalidArgumentException('Invalid logger provided');
|
||||
}
|
||||
$this->loggers[$type] = $log + $prev[$type];
|
||||
|
||||
if ($this->bootstrappingLogger && $prev[$type][0] === $this->bootstrappingLogger) {
|
||||
$flush[$type] = $type;
|
||||
}
|
||||
}
|
||||
$this->reRegister($prevLogged | $this->thrownErrors);
|
||||
|
||||
if ($flush) {
|
||||
foreach ($this->bootstrappingLogger->cleanLogs() as $log) {
|
||||
$type = $log[2]['type'];
|
||||
if (!isset($flush[$type])) {
|
||||
$this->bootstrappingLogger->log($log[0], $log[1], $log[2]);
|
||||
} elseif ($this->loggers[$type][0]) {
|
||||
$this->loggers[$type][0]->log($this->loggers[$type][1], $log[1], $log[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $prev;
|
||||
}
|
||||
|
||||
@@ -251,7 +283,7 @@ class ErrorHandler
|
||||
public function throwAt($levels, $replace = false)
|
||||
{
|
||||
$prev = $this->thrownErrors;
|
||||
$this->thrownErrors = (E_ALL | E_STRICT) & ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
|
||||
$this->thrownErrors = ($levels | E_RECOVERABLE_ERROR | E_USER_ERROR) & ~E_USER_DEPRECATED & ~E_DEPRECATED;
|
||||
if (!$replace) {
|
||||
$this->thrownErrors |= $prev;
|
||||
}
|
||||
@@ -326,12 +358,16 @@ class ErrorHandler
|
||||
private function reRegister($prev)
|
||||
{
|
||||
if ($prev !== $this->thrownErrors | $this->loggedErrors) {
|
||||
$handler = set_error_handler('var_dump', 0);
|
||||
$handler = set_error_handler('var_dump');
|
||||
$handler = is_array($handler) ? $handler[0] : null;
|
||||
restore_error_handler();
|
||||
if ($handler === $this) {
|
||||
restore_error_handler();
|
||||
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
|
||||
if ($this->isRoot) {
|
||||
set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors);
|
||||
} else {
|
||||
set_error_handler(array($this, 'handleError'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -340,17 +376,17 @@ class ErrorHandler
|
||||
* Handles errors by filtering then logging them according to the configured bit fields.
|
||||
*
|
||||
* @param int $type One of the E_* constants
|
||||
* @param string $message
|
||||
* @param string $file
|
||||
* @param int $line
|
||||
* @param array $context
|
||||
*
|
||||
* @return bool Returns false when no handling happens so that the PHP engine can handle the error itself.
|
||||
* @return bool Returns false when no handling happens so that the PHP engine can handle the error itself
|
||||
*
|
||||
* @throws \ErrorException When $this->thrownErrors requests so
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
public function handleError($type, $message, $file, $line, array $context, array $backtrace = null)
|
||||
public function handleError($type, $message, $file, $line)
|
||||
{
|
||||
$level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED;
|
||||
$log = $this->loggedErrors & $type;
|
||||
@@ -360,8 +396,17 @@ class ErrorHandler
|
||||
if (!$type || (!$log && !$throw)) {
|
||||
return $type && $log;
|
||||
}
|
||||
$scope = $this->scopedErrors & $type;
|
||||
|
||||
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) {
|
||||
if (4 < $numArgs = func_num_args()) {
|
||||
$context = $scope ? (func_get_arg(4) ?: array()) : array();
|
||||
$backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM
|
||||
} else {
|
||||
$context = array();
|
||||
$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;
|
||||
@@ -377,7 +422,10 @@ class ErrorHandler
|
||||
}
|
||||
|
||||
if ($throw) {
|
||||
if (($this->scopedErrors & $type) && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
||||
if (null !== self::$toStringException) {
|
||||
$throw = self::$toStringException;
|
||||
self::$toStringException = null;
|
||||
} elseif ($scope && class_exists('Symfony\Component\Debug\Exception\ContextErrorException')) {
|
||||
// Checking for class existence is a work around for https://bugs.php.net/42098
|
||||
$throw = new ContextErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line, $context);
|
||||
} else {
|
||||
@@ -392,6 +440,47 @@ class ErrorHandler
|
||||
$throw->errorHandlerCanary = new ErrorHandlerCanary();
|
||||
}
|
||||
|
||||
if (E_USER_ERROR & $type) {
|
||||
$backtrace = $backtrace ?: $throw->getTrace();
|
||||
|
||||
for ($i = 1; isset($backtrace[$i]); ++$i) {
|
||||
if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function'])
|
||||
&& '__toString' === $backtrace[$i]['function']
|
||||
&& '->' === $backtrace[$i]['type']
|
||||
&& !isset($backtrace[$i - 1]['class'])
|
||||
&& ('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.
|
||||
// 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.
|
||||
|
||||
foreach ($context as $e) {
|
||||
if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) {
|
||||
if (1 === $i) {
|
||||
// On HHVM
|
||||
$throw = $e;
|
||||
break;
|
||||
}
|
||||
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($throw);
|
||||
|
||||
// Stop the process by giving back the error to the native handler.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw $throw;
|
||||
}
|
||||
|
||||
@@ -408,7 +497,7 @@ class ErrorHandler
|
||||
$e = compact('type', 'file', 'line', 'level');
|
||||
|
||||
if ($type & $level) {
|
||||
if ($this->scopedErrors & $type) {
|
||||
if ($scope) {
|
||||
$e['scope_vars'] = $context;
|
||||
if ($trace) {
|
||||
$e['stack'] = $backtrace ?: debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT);
|
||||
@@ -437,6 +526,10 @@ class ErrorHandler
|
||||
} catch (\Exception $e) {
|
||||
$this->isRecursive = false;
|
||||
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
$this->isRecursive = false;
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
@@ -459,7 +552,7 @@ class ErrorHandler
|
||||
}
|
||||
$type = $exception instanceof FatalErrorException ? $exception->getSeverity() : E_ERROR;
|
||||
|
||||
if ($this->loggedErrors & $type) {
|
||||
if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) {
|
||||
$e = array(
|
||||
'type' => $type,
|
||||
'file' => $exception->getFile(),
|
||||
@@ -486,8 +579,12 @@ class ErrorHandler
|
||||
} else {
|
||||
$message = 'Uncaught Exception: '.$exception->getMessage();
|
||||
}
|
||||
if ($this->loggedErrors & $e['type']) {
|
||||
$this->loggers[$e['type']][0]->log($this->loggers[$e['type']][1], $message, $e);
|
||||
}
|
||||
if ($this->loggedErrors & $type) {
|
||||
try {
|
||||
$this->loggers[$type][0]->log($this->loggers[$type][1], $message, $e);
|
||||
} catch (\Exception $handlerException) {
|
||||
} catch (\Throwable $handlerException) {
|
||||
}
|
||||
}
|
||||
if ($exception instanceof FatalErrorException && !$exception instanceof OutOfMemoryException && $error) {
|
||||
@@ -527,7 +624,7 @@ class ErrorHandler
|
||||
|
||||
self::$reservedMemory = null;
|
||||
|
||||
$handler = set_error_handler('var_dump', 0);
|
||||
$handler = set_error_handler('var_dump');
|
||||
$handler = is_array($handler) ? $handler[0] : null;
|
||||
restore_error_handler();
|
||||
|
||||
@@ -545,6 +642,8 @@ class ErrorHandler
|
||||
}
|
||||
} catch (\Exception $exception) {
|
||||
// Handled below
|
||||
} catch (\Throwable $exception) {
|
||||
// Handled below
|
||||
}
|
||||
|
||||
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
|
||||
@@ -672,7 +771,7 @@ class ErrorHandler
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' static method is deprecated since version 2.6 and will be removed in 3.0. Use the setLoggers() or setDefaultLogger() methods instead.', E_USER_DEPRECATED);
|
||||
|
||||
$handler = set_error_handler('var_dump', 0);
|
||||
$handler = set_error_handler('var_dump');
|
||||
$handler = is_array($handler) ? $handler[0] : null;
|
||||
restore_error_handler();
|
||||
if (!$handler instanceof self) {
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@ class FatalThrowableError extends FatalErrorException
|
||||
$message = 'Type error: '.$e->getMessage();
|
||||
$severity = E_RECOVERABLE_ERROR;
|
||||
} else {
|
||||
$message = 'Fatal error: '.$e->getMessage();
|
||||
$message = $e->getMessage();
|
||||
$severity = E_ERROR;
|
||||
}
|
||||
|
||||
|
||||
+11
-6
@@ -94,8 +94,13 @@ class FlattenException extends LegacyFlattenException
|
||||
$e->setClass(get_class($exception));
|
||||
$e->setFile($exception->getFile());
|
||||
$e->setLine($exception->getLine());
|
||||
if ($exception->getPrevious()) {
|
||||
$e->setPrevious(static::create($exception->getPrevious()));
|
||||
|
||||
$previous = $exception->getPrevious();
|
||||
|
||||
if ($previous instanceof \Exception) {
|
||||
$e->setPrevious(static::create($previous));
|
||||
} elseif ($previous instanceof \Throwable) {
|
||||
$e->setPrevious(static::create(new FatalThrowableError($previous)));
|
||||
}
|
||||
|
||||
return $e;
|
||||
@@ -258,7 +263,10 @@ class FlattenException extends LegacyFlattenException
|
||||
if (++$count > 1e4) {
|
||||
return array('array', '*SKIPPED over 10000 entries*');
|
||||
}
|
||||
if (is_object($value)) {
|
||||
if ($value instanceof \__PHP_Incomplete_Class) {
|
||||
// is_object() returns false on PHP<=7.1
|
||||
$result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
|
||||
} elseif (is_object($value)) {
|
||||
$result[$key] = array('object', get_class($value));
|
||||
} elseif (is_array($value)) {
|
||||
if ($level > 10) {
|
||||
@@ -272,9 +280,6 @@ class FlattenException extends LegacyFlattenException
|
||||
$result[$key] = array('boolean', $value);
|
||||
} elseif (is_resource($value)) {
|
||||
$result[$key] = array('resource', get_resource_type($value));
|
||||
} elseif ($value instanceof \__PHP_Incomplete_Class) {
|
||||
// Special case of object, is_object will return false
|
||||
$result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value));
|
||||
} else {
|
||||
$result[$key] = array('string', (string) $value);
|
||||
}
|
||||
|
||||
+31
-7
@@ -39,6 +39,8 @@ class ExceptionHandler
|
||||
public function __construct($debug = true, $charset = null, $fileLinkFormat = null)
|
||||
{
|
||||
if (false !== strpos($charset, '%')) {
|
||||
@trigger_error('Providing $fileLinkFormat as second argument to '.__METHOD__.' is deprecated since version 2.8 and will be unsupported in 3.0. Please provide it as third argument, after $charset.', E_USER_DEPRECATED);
|
||||
|
||||
// Swap $charset and $fileLinkFormat for BC reasons
|
||||
$pivot = $fileLinkFormat;
|
||||
$fileLinkFormat = $charset;
|
||||
@@ -56,7 +58,7 @@ class ExceptionHandler
|
||||
* @param string|null $charset The charset used by exception messages
|
||||
* @param string|null $fileLinkFormat The IDE link template
|
||||
*
|
||||
* @return ExceptionHandler The registered exception handler
|
||||
* @return static
|
||||
*/
|
||||
public static function register($debug = true, $charset = null, $fileLinkFormat = null)
|
||||
{
|
||||
@@ -94,7 +96,7 @@ class ExceptionHandler
|
||||
*
|
||||
* @param string $format The format for links to source files
|
||||
*
|
||||
* @return string The previous file link format.
|
||||
* @return string The previous file link format
|
||||
*/
|
||||
public function setFileLinkFormat($format)
|
||||
{
|
||||
@@ -164,6 +166,7 @@ class ExceptionHandler
|
||||
$response = $this->createResponse($exception);
|
||||
$response->sendHeaders();
|
||||
$response->sendContent();
|
||||
@trigger_error(sprintf("The %s::createResponse method is deprecated since 2.8 and won't be called anymore when handling an exception in 3.0.", $reflector->class), E_USER_DEPRECATED);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -177,7 +180,7 @@ class ExceptionHandler
|
||||
* This method uses plain PHP functions like header() and echo to output
|
||||
* the response.
|
||||
*
|
||||
* @param \Exception|FlattenException $exception An \Exception instance
|
||||
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
|
||||
*/
|
||||
public function sendPhpResponse($exception)
|
||||
{
|
||||
@@ -199,17 +202,37 @@ class ExceptionHandler
|
||||
/**
|
||||
* Creates the error Response associated with the given Exception.
|
||||
*
|
||||
* @param \Exception|FlattenException $exception An \Exception instance
|
||||
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
|
||||
*
|
||||
* @return Response A Response instance
|
||||
*
|
||||
* @deprecated since 2.8, to be removed in 3.0.
|
||||
*/
|
||||
public function createResponse($exception)
|
||||
{
|
||||
@trigger_error('The '.__METHOD__.' method is deprecated since version 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
|
||||
|
||||
if (!$exception instanceof FlattenException) {
|
||||
$exception = FlattenException::create($exception);
|
||||
}
|
||||
|
||||
return Response::create($this->getHtml($exception), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the full HTML content associated with the given exception.
|
||||
*
|
||||
* @param \Exception|FlattenException $exception An \Exception or FlattenException instance
|
||||
*
|
||||
* @return string The HTML content as a string
|
||||
*/
|
||||
public function getHtml($exception)
|
||||
{
|
||||
if (!$exception instanceof FlattenException) {
|
||||
$exception = FlattenException::create($exception);
|
||||
}
|
||||
|
||||
return Response::create($this->decorate($this->getContent($exception), $this->getStylesheet($exception)), $exception->getStatusCode(), $exception->getHeaders())->setCharset($this->charset);
|
||||
return $this->decorate($this->getContent($exception), $this->getStylesheet($exception));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -238,7 +261,7 @@ class ExceptionHandler
|
||||
$ind = $count - $position + 1;
|
||||
$class = $this->formatClass($e['class']);
|
||||
$message = nl2br($this->escapeHtml($e['message']));
|
||||
$content .= sprintf(<<<EOF
|
||||
$content .= sprintf(<<<'EOF'
|
||||
<h2 class="block_exception clear_fix">
|
||||
<span class="exception_counter">%d/%d</span>
|
||||
<span class="exception_title">%s%s:</span>
|
||||
@@ -289,7 +312,7 @@ EOF;
|
||||
*/
|
||||
public function getStylesheet(FlattenException $exception)
|
||||
{
|
||||
return <<<EOF
|
||||
return <<<'EOF'
|
||||
.sf-reset { font: 11px Verdana, Arial, sans-serif; color: #333 }
|
||||
.sf-reset .clear { clear:both; height:0; font-size:0; line-height:0; }
|
||||
.sf-reset .clear_fix:after { display:block; height:0; clear:both; visibility:hidden; }
|
||||
@@ -319,6 +342,7 @@ EOF;
|
||||
border-bottom:1px solid #ccc;
|
||||
border-right:1px solid #ccc;
|
||||
border-left:1px solid #ccc;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.sf-reset .block_exception { background-color:#ddd; color: #333; padding:20px;
|
||||
-webkit-border-top-left-radius: 16px;
|
||||
|
||||
@@ -179,7 +179,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
);
|
||||
|
||||
if ($prefix) {
|
||||
$candidates = array_filter($candidates, function ($candidate) use ($prefix) {return 0 === strpos($candidate, $prefix);});
|
||||
$candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); });
|
||||
}
|
||||
|
||||
// We cannot use the autoloader here as most of them use require; but if the class
|
||||
|
||||
+7
-1
@@ -36,8 +36,13 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
|
||||
$message = sprintf('Attempted to call an undefined method named "%s" of class "%s".', $methodName, $className);
|
||||
|
||||
if (!class_exists($className) || null === $methods = get_class_methods($className)) {
|
||||
// failed to get the class or its methods on which an unknown method was called (for example on an anonymous class)
|
||||
return new UndefinedMethodException($message, $exception);
|
||||
}
|
||||
|
||||
$candidates = array();
|
||||
foreach (get_class_methods($className) as $definedMethodName) {
|
||||
foreach ($methods as $definedMethodName) {
|
||||
$lev = levenshtein($methodName, $definedMethodName);
|
||||
if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) {
|
||||
$candidates[] = $definedMethodName;
|
||||
@@ -52,6 +57,7 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface
|
||||
} else {
|
||||
$candidates = '"'.$last;
|
||||
}
|
||||
|
||||
$message .= "\nDid you mean to call ".$candidates;
|
||||
}
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2015 Fabien Potencier
|
||||
Copyright (c) 2004-2017 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
|
||||
|
||||
Vendored
+6
-36
@@ -1,43 +1,13 @@
|
||||
Debug Component
|
||||
===============
|
||||
|
||||
Debug provides tools to make debugging easier.
|
||||
|
||||
Enabling all debug tools is as easy as calling the `enable()` method on the
|
||||
main `Debug` class:
|
||||
|
||||
```php
|
||||
use Symfony\Component\Debug\Debug;
|
||||
|
||||
Debug::enable();
|
||||
```
|
||||
|
||||
You can also use the tools individually:
|
||||
|
||||
```php
|
||||
use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\Debug\ExceptionHandler;
|
||||
|
||||
if ('cli' !== php_sapi_name()) {
|
||||
ini_set('display_errors', 0);
|
||||
ExceptionHandler::register();
|
||||
} elseif (!ini_get('log_errors') || ini_get('error_log')) {
|
||||
ini_set('display_errors', 1);
|
||||
}
|
||||
ErrorHandler::register();
|
||||
```
|
||||
|
||||
Note that the `Debug::enable()` call also registers the debug class loader
|
||||
from the Symfony ClassLoader component when available.
|
||||
|
||||
This component can optionally take advantage of the features of the HttpKernel
|
||||
and HttpFoundation components.
|
||||
The Debug component provides tools to ease debugging PHP code.
|
||||
|
||||
Resources
|
||||
---------
|
||||
|
||||
You can run the unit tests with the following command:
|
||||
|
||||
$ cd path/to/Symfony/Component/Debug/
|
||||
$ composer install
|
||||
$ phpunit
|
||||
* [Documentation](https://symfony.com/doc/current/components/debug/index.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)
|
||||
|
||||
+4
-3
@@ -1,7 +1,9 @@
|
||||
Symfony Debug Extension
|
||||
=======================
|
||||
Symfony Debug Extension for PHP 5
|
||||
=================================
|
||||
|
||||
This extension publishes several functions to help building powerful debugging tools.
|
||||
It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes.
|
||||
It is not required thus not provided for PHP 7.
|
||||
|
||||
symfony_zval_info()
|
||||
-------------------
|
||||
@@ -122,7 +124,6 @@ array(3) {
|
||||
Usage
|
||||
-----
|
||||
|
||||
The extension is compatible with ZTS mode, and should be supported by PHP5.3, 5.4, 5.5 and 5.6.
|
||||
To enable the extension from source, run:
|
||||
|
||||
```
|
||||
|
||||
+14
-12
@@ -1,14 +1,14 @@
|
||||
--TEST--
|
||||
Test symfony_zval_info API
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("symfony_debug")) print "skip"; ?>
|
||||
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$int = 42;
|
||||
$float = 42.42;
|
||||
$str = "foobar";
|
||||
$object = new StdClass;
|
||||
$str = 'foobar';
|
||||
$object = new StdClass();
|
||||
$array = array('foo', 'bar');
|
||||
$resource = tmpfile();
|
||||
$null = null;
|
||||
@@ -17,15 +17,17 @@ $bool = true;
|
||||
$anotherint = 42;
|
||||
$refcount2 = &$anotherint;
|
||||
|
||||
$var = array('int' => $int,
|
||||
'float' => $float,
|
||||
'str' => $str,
|
||||
'object' => $object,
|
||||
'array' => $array,
|
||||
'resource' => $resource,
|
||||
'null' => $null,
|
||||
'bool' => $bool,
|
||||
'refcount' => &$refcount2);
|
||||
$var = array(
|
||||
'int' => $int,
|
||||
'float' => $float,
|
||||
'str' => $str,
|
||||
'object' => $object,
|
||||
'array' => $array,
|
||||
'resource' => $resource,
|
||||
'null' => $null,
|
||||
'bool' => $bool,
|
||||
'refcount' => &$refcount2,
|
||||
);
|
||||
|
||||
var_dump(symfony_zval_info('int', $var));
|
||||
var_dump(symfony_zval_info('float', $var));
|
||||
|
||||
+1
-2
@@ -1,7 +1,7 @@
|
||||
--TEST--
|
||||
Test symfony_debug_backtrace in case of fatal error
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("symfony_debug")) print "skip"; ?>
|
||||
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@@ -18,7 +18,6 @@ function foo()
|
||||
function bt()
|
||||
{
|
||||
print_r(symfony_debug_backtrace());
|
||||
|
||||
}
|
||||
|
||||
register_shutdown_function('bt');
|
||||
|
||||
+1
-2
@@ -1,7 +1,7 @@
|
||||
--TEST--
|
||||
Test symfony_debug_backtrace in case of non fatal error
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("symfony_debug")) print "skip"; ?>
|
||||
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
@@ -13,7 +13,6 @@ function bar()
|
||||
function bt()
|
||||
{
|
||||
print_r(symfony_debug_backtrace());
|
||||
|
||||
}
|
||||
|
||||
bar();
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
--TEST--
|
||||
Test ErrorHandler in case of fatal error
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("symfony_debug")) print "skip"; ?>
|
||||
<?php if (!extension_loaded('symfony_debug')) print 'skip'; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
||||
Vendored
+7
-4
@@ -23,16 +23,19 @@
|
||||
"symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/class-loader": "~2.2",
|
||||
"symfony/http-kernel": "~2.3.24|~2.5.9|~2.6,>=2.6.2"
|
||||
"symfony/class-loader": "~2.2|~3.0.0",
|
||||
"symfony/http-kernel": "~2.3.24|~2.5.9|^2.6.2|~3.0.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": { "Symfony\\Component\\Debug\\": "" }
|
||||
"psr-4": { "Symfony\\Component\\Debug\\": "" },
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7-dev"
|
||||
"dev-master": "2.8-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ class Alias
|
||||
private $public;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id Alias identifier
|
||||
* @param bool $public If this alias is public
|
||||
*/
|
||||
|
||||
+1
-3
@@ -34,8 +34,6 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
|
||||
private $onlyConstructorArguments;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
|
||||
*/
|
||||
public function __construct($onlyConstructorArguments = false)
|
||||
@@ -128,7 +126,7 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface
|
||||
/**
|
||||
* Returns a service definition given the full name or an alias.
|
||||
*
|
||||
* @param string $id A full id or alias for a service definition.
|
||||
* @param string $id A full id or alias for a service definition
|
||||
*
|
||||
* @return Definition|null The definition related to the supplied id
|
||||
*/
|
||||
|
||||
+76
-26
@@ -28,25 +28,49 @@ class AutowirePass implements CompilerPassInterface
|
||||
private $definedTypes = array();
|
||||
private $types;
|
||||
private $notGuessableTypes = array();
|
||||
private $usedTypes = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isAutowired()) {
|
||||
$this->completeDefinition($id, $definition);
|
||||
$throwingAutoloader = function ($class) { throw new \ReflectionException(sprintf('Class %s does not exist', $class)); };
|
||||
spl_autoload_register($throwingAutoloader);
|
||||
|
||||
try {
|
||||
$this->container = $container;
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
if ($definition->isAutowired()) {
|
||||
$this->completeDefinition($id, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->usedTypes as $type => $id) {
|
||||
if (isset($this->usedTypes[$type]) && isset($this->notGuessableTypes[$type])) {
|
||||
$classOrInterface = class_exists($type) ? 'class' : 'interface';
|
||||
$matchingServices = implode(', ', $this->types[$type]);
|
||||
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices));
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Throwable $e) {
|
||||
}
|
||||
|
||||
spl_autoload_unregister($throwingAutoloader);
|
||||
|
||||
// Free memory and remove circular reference to container
|
||||
$this->container = null;
|
||||
$this->reflectionClasses = array();
|
||||
$this->definedTypes = array();
|
||||
$this->types = null;
|
||||
$this->notGuessableTypes = array();
|
||||
$this->usedTypes = array();
|
||||
|
||||
if (isset($e)) {
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,8 +106,10 @@ class AutowirePass implements CompilerPassInterface
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
|
||||
}
|
||||
|
||||
// specifically pass the default value
|
||||
$arguments[$index] = $parameter->getDefaultValue();
|
||||
if (!array_key_exists($index, $arguments)) {
|
||||
// specifically pass the default value
|
||||
$arguments[$index] = $parameter->getDefaultValue();
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -92,11 +118,13 @@ class AutowirePass implements CompilerPassInterface
|
||||
$this->populateAvailableTypes();
|
||||
}
|
||||
|
||||
if (isset($this->types[$typeHint->name])) {
|
||||
if (isset($this->types[$typeHint->name]) && !isset($this->notGuessableTypes[$typeHint->name])) {
|
||||
$value = new Reference($this->types[$typeHint->name]);
|
||||
$this->usedTypes[$typeHint->name] = $id;
|
||||
} else {
|
||||
try {
|
||||
$value = $this->createAutowiredDefinition($typeHint, $id);
|
||||
$this->usedTypes[$typeHint->name] = $id;
|
||||
} catch (RuntimeException $e) {
|
||||
if ($parameter->allowsNull()) {
|
||||
$value = null;
|
||||
@@ -107,11 +135,11 @@ class AutowirePass implements CompilerPassInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\ReflectionException $reflectionException) {
|
||||
} catch (\ReflectionException $e) {
|
||||
// Typehint against a non-existing class
|
||||
|
||||
if (!$parameter->isDefaultValueAvailable()) {
|
||||
throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $reflectionException->getMessage()), 0, $reflectionException);
|
||||
throw new RuntimeException(sprintf('Cannot autowire argument %s for %s because the type-hinted class does not exist (%s).', $index + 1, $definition->getClass(), $e->getMessage()), 0, $e);
|
||||
}
|
||||
|
||||
$value = $parameter->getDefaultValue();
|
||||
@@ -154,6 +182,7 @@ class AutowirePass implements CompilerPassInterface
|
||||
foreach ($definition->getAutowiringTypes() as $type) {
|
||||
$this->definedTypes[$type] = true;
|
||||
$this->types[$type] = $id;
|
||||
unset($this->notGuessableTypes[$type]);
|
||||
}
|
||||
|
||||
if (!$reflectionClass = $this->getReflectionClass($id, $definition)) {
|
||||
@@ -177,22 +206,26 @@ class AutowirePass implements CompilerPassInterface
|
||||
*/
|
||||
private function set($type, $id)
|
||||
{
|
||||
if (isset($this->definedTypes[$type]) || isset($this->notGuessableTypes[$type])) {
|
||||
if (isset($this->definedTypes[$type])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isset($this->types[$type])) {
|
||||
if ($this->types[$type] === $id) {
|
||||
return;
|
||||
}
|
||||
if (!isset($this->types[$type])) {
|
||||
$this->types[$type] = $id;
|
||||
|
||||
unset($this->types[$type]);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->types[$type] === $id) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isset($this->notGuessableTypes[$type])) {
|
||||
$this->notGuessableTypes[$type] = true;
|
||||
|
||||
return;
|
||||
$this->types[$type] = (array) $this->types[$type];
|
||||
}
|
||||
|
||||
$this->types[$type] = $id;
|
||||
$this->types[$type][] = $id;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,8 +240,16 @@ class AutowirePass implements CompilerPassInterface
|
||||
*/
|
||||
private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
|
||||
{
|
||||
if (isset($this->notGuessableTypes[$typeHint->name]) || !$typeHint->isInstantiable()) {
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s".', $typeHint->name, $id));
|
||||
if (isset($this->notGuessableTypes[$typeHint->name])) {
|
||||
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
|
||||
$matchingServices = implode(', ', $this->types[$typeHint->name]);
|
||||
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $typeHint->name, $id, $classOrInterface, $matchingServices));
|
||||
}
|
||||
|
||||
if (!$typeHint->isInstantiable()) {
|
||||
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface));
|
||||
}
|
||||
|
||||
$argumentId = sprintf('autowired.%s', $typeHint->name);
|
||||
@@ -217,7 +258,14 @@ class AutowirePass implements CompilerPassInterface
|
||||
$argumentDefinition->setPublic(false);
|
||||
|
||||
$this->populateAvailableType($argumentId, $argumentDefinition);
|
||||
$this->completeDefinition($argumentId, $argumentDefinition);
|
||||
|
||||
try {
|
||||
$this->completeDefinition($argumentId, $argumentDefinition);
|
||||
} catch (RuntimeException $e) {
|
||||
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
|
||||
$message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface);
|
||||
throw new RuntimeException($message, 0, $e);
|
||||
}
|
||||
|
||||
return new Reference($argumentId);
|
||||
}
|
||||
@@ -228,7 +276,7 @@ class AutowirePass implements CompilerPassInterface
|
||||
* @param string $id
|
||||
* @param Definition $definition
|
||||
*
|
||||
* @return \ReflectionClass|null
|
||||
* @return \ReflectionClass|false
|
||||
*/
|
||||
private function getReflectionClass($id, Definition $definition)
|
||||
{
|
||||
@@ -238,15 +286,17 @@ class AutowirePass implements CompilerPassInterface
|
||||
|
||||
// Cannot use reflection if the class isn't set
|
||||
if (!$class = $definition->getClass()) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
$class = $this->container->getParameterBag()->resolveValue($class);
|
||||
|
||||
try {
|
||||
return $this->reflectionClasses[$id] = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $reflectionException) {
|
||||
// return null
|
||||
$reflector = new \ReflectionClass($class);
|
||||
} catch (\ReflectionException $e) {
|
||||
$reflector = false;
|
||||
}
|
||||
|
||||
return $this->reflectionClasses[$id] = $reflector;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-6
@@ -60,15 +60,18 @@ class CheckCircularReferencesPass implements CompilerPassInterface
|
||||
$id = $node->getId();
|
||||
|
||||
if (empty($this->checkedNodes[$id])) {
|
||||
$searchKey = array_search($id, $this->currentPath);
|
||||
$this->currentPath[] = $id;
|
||||
// don't check circular dependencies for lazy services
|
||||
if (!$node->getValue() || !$node->getValue()->isLazy()) {
|
||||
$searchKey = array_search($id, $this->currentPath);
|
||||
$this->currentPath[] = $id;
|
||||
|
||||
if (false !== $searchKey) {
|
||||
throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
|
||||
if (false !== $searchKey) {
|
||||
throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
|
||||
}
|
||||
|
||||
$this->checkOutEdges($node->getOutEdges());
|
||||
}
|
||||
|
||||
$this->checkOutEdges($node->getOutEdges());
|
||||
|
||||
$this->checkedNodes[$id] = true;
|
||||
array_pop($this->currentPath);
|
||||
}
|
||||
|
||||
@@ -25,9 +25,6 @@ class Compiler
|
||||
private $loggingFormatter;
|
||||
private $serviceReferenceGraph;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->passConfig = new PassConfig();
|
||||
|
||||
@@ -52,10 +52,14 @@ class DecoratorServicePass implements CompilerPassInterface
|
||||
$public = $alias->isPublic();
|
||||
$container->setAlias($renamedId, new Alias((string) $alias, false));
|
||||
} else {
|
||||
$definition = $container->getDefinition($inner);
|
||||
$public = $definition->isPublic();
|
||||
$definition->setPublic(false);
|
||||
$container->setDefinition($renamedId, $definition);
|
||||
$decoratedDefinition = $container->getDefinition($inner);
|
||||
$definition->setTags(array_merge($decoratedDefinition->getTags(), $definition->getTags()));
|
||||
$definition->setAutowiringTypes(array_merge($decoratedDefinition->getAutowiringTypes(), $definition->getAutowiringTypes()));
|
||||
$public = $decoratedDefinition->isPublic();
|
||||
$decoratedDefinition->setPublic(false);
|
||||
$decoratedDefinition->setTags(array());
|
||||
$decoratedDefinition->setAutowiringTypes(array());
|
||||
$container->setDefinition($renamedId, $decoratedDefinition);
|
||||
}
|
||||
|
||||
$container->setAlias($inner, new Alias($id, $public));
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* A pass to automatically process extensions if they implement
|
||||
* A pass to automatically process extensions if they implement
|
||||
* CompilerPassInterface.
|
||||
*
|
||||
* @author Wouter J <wouter@wouterj.nl>
|
||||
|
||||
+4
@@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
|
||||
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
|
||||
|
||||
/**
|
||||
@@ -47,6 +48,9 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
|
||||
$tmpContainer = new ContainerBuilder($container->getParameterBag());
|
||||
$tmpContainer->setResourceTracking($container->isTrackingResources());
|
||||
$tmpContainer->addObjectResource($extension);
|
||||
if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
|
||||
$tmpContainer->addObjectResource($configuration);
|
||||
}
|
||||
|
||||
foreach ($exprLangProviders as $provider) {
|
||||
$tmpContainer->addExpressionLanguageProvider($provider);
|
||||
|
||||
@@ -35,9 +35,6 @@ class PassConfig
|
||||
private $optimizationPasses;
|
||||
private $removingPasses;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->mergePass = new MergeExtensionConfigurationPass();
|
||||
@@ -58,8 +55,8 @@ class PassConfig
|
||||
|
||||
$this->removingPasses = array(
|
||||
new RemovePrivateAliasesPass(),
|
||||
new RemoveAbstractDefinitionsPass(),
|
||||
new ReplaceAliasByActualDefinitionPass(),
|
||||
new RemoveAbstractDefinitionsPass(),
|
||||
new RepeatedPass(array(
|
||||
new AnalyzeServiceReferencesPass(),
|
||||
new InlineServiceDefinitionsPass(),
|
||||
@@ -102,8 +99,7 @@ class PassConfig
|
||||
throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type));
|
||||
}
|
||||
|
||||
$passes = &$this->$property;
|
||||
$passes[] = $pass;
|
||||
$this->{$property}[] = $pass;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -157,9 +153,9 @@ class PassConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all passes for the Merge pass.
|
||||
* Gets the Merge pass.
|
||||
*
|
||||
* @return array An array of passes
|
||||
* @return CompilerPassInterface The merge pass
|
||||
*/
|
||||
public function getMergePass()
|
||||
{
|
||||
|
||||
@@ -32,8 +32,6 @@ class RepeatedPass implements CompilerPassInterface
|
||||
private $passes;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param RepeatablePassInterface[] $passes An array of RepeatablePassInterface objects
|
||||
*
|
||||
* @throws InvalidArgumentException when the passes don't implement RepeatablePassInterface
|
||||
@@ -58,14 +56,12 @@ class RepeatedPass implements CompilerPassInterface
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
$this->repeat = false;
|
||||
foreach ($this->passes as $pass) {
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
if ($this->repeat) {
|
||||
$this->process($container);
|
||||
}
|
||||
do {
|
||||
$this->repeat = false;
|
||||
foreach ($this->passes as $pass) {
|
||||
$pass->process($container);
|
||||
}
|
||||
} while ($this->repeat);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+70
-76
@@ -25,7 +25,6 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
|
||||
{
|
||||
private $compiler;
|
||||
private $formatter;
|
||||
private $sourceId;
|
||||
|
||||
/**
|
||||
* Process the Container to replace aliases with service definitions.
|
||||
@@ -36,113 +35,108 @@ class ReplaceAliasByActualDefinitionPass implements CompilerPassInterface
|
||||
*/
|
||||
public function process(ContainerBuilder $container)
|
||||
{
|
||||
// Setup
|
||||
$this->compiler = $container->getCompiler();
|
||||
$this->formatter = $this->compiler->getLoggingFormatter();
|
||||
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
$aliasId = (string) $alias;
|
||||
|
||||
try {
|
||||
$definition = $container->getDefinition($aliasId);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $id, $alias), null, $e);
|
||||
// First collect all alias targets that need to be replaced
|
||||
$seenAliasTargets = array();
|
||||
$replacements = array();
|
||||
foreach ($container->getAliases() as $definitionId => $target) {
|
||||
$targetId = (string) $target;
|
||||
// Special case: leave this target alone
|
||||
if ('service_container' === $targetId) {
|
||||
continue;
|
||||
}
|
||||
// Check if target needs to be replaces
|
||||
if (isset($replacements[$targetId])) {
|
||||
$container->setAlias($definitionId, $replacements[$targetId]);
|
||||
}
|
||||
// No need to process the same target twice
|
||||
if (isset($seenAliasTargets[$targetId])) {
|
||||
continue;
|
||||
}
|
||||
// Process new target
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($definition->isPublic()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Remove private definition and schedule for replacement
|
||||
$definition->setPublic(true);
|
||||
$container->setDefinition($id, $definition);
|
||||
$container->removeDefinition($aliasId);
|
||||
$container->setDefinition($definitionId, $definition);
|
||||
$container->removeDefinition($targetId);
|
||||
$replacements[$targetId] = $definitionId;
|
||||
}
|
||||
|
||||
$this->updateReferences($container, $aliasId, $id);
|
||||
|
||||
// we have to restart the process due to concurrent modification of
|
||||
// the container
|
||||
$this->process($container);
|
||||
|
||||
break;
|
||||
// Now replace target instances in all definitions
|
||||
foreach ($container->getDefinitions() as $definitionId => $definition) {
|
||||
$definition->setArguments($this->updateArgumentReferences($replacements, $definitionId, $definition->getArguments()));
|
||||
$definition->setMethodCalls($this->updateArgumentReferences($replacements, $definitionId, $definition->getMethodCalls()));
|
||||
$definition->setProperties($this->updateArgumentReferences($replacements, $definitionId, $definition->getProperties()));
|
||||
$definition->setFactoryService($this->updateFactoryReferenceId($replacements, $definition->getFactoryService(false)), false);
|
||||
$definition->setFactory($this->updateFactoryReference($replacements, $definition->getFactory()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates references to remove aliases.
|
||||
* Recursively updates references in an array.
|
||||
*
|
||||
* @param ContainerBuilder $container The container
|
||||
* @param string $currentId The alias identifier being replaced
|
||||
* @param string $newId The id of the service the alias points to
|
||||
*/
|
||||
private function updateReferences($container, $currentId, $newId)
|
||||
{
|
||||
foreach ($container->getAliases() as $id => $alias) {
|
||||
if ($currentId === (string) $alias) {
|
||||
$container->setAlias($id, $newId);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($container->getDefinitions() as $id => $definition) {
|
||||
$this->sourceId = $id;
|
||||
|
||||
$definition->setArguments(
|
||||
$this->updateArgumentReferences($definition->getArguments(), $currentId, $newId)
|
||||
);
|
||||
|
||||
$definition->setMethodCalls(
|
||||
$this->updateArgumentReferences($definition->getMethodCalls(), $currentId, $newId)
|
||||
);
|
||||
|
||||
$definition->setProperties(
|
||||
$this->updateArgumentReferences($definition->getProperties(), $currentId, $newId)
|
||||
);
|
||||
|
||||
$definition->setFactoryService($this->updateFactoryServiceReference($definition->getFactoryService(false), $currentId, $newId), false);
|
||||
$definition->setFactory($this->updateFactoryReference($definition->getFactory(), $currentId, $newId));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates argument references.
|
||||
*
|
||||
* @param array $arguments An array of Arguments
|
||||
* @param string $currentId The alias identifier
|
||||
* @param string $newId The identifier the alias points to
|
||||
* @param array $replacements Table of aliases to replace
|
||||
* @param string $definitionId Identifier of this definition
|
||||
* @param array $arguments Where to replace the aliases
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function updateArgumentReferences(array $arguments, $currentId, $newId)
|
||||
private function updateArgumentReferences(array $replacements, $definitionId, array $arguments)
|
||||
{
|
||||
foreach ($arguments as $k => $argument) {
|
||||
// Handle recursion step
|
||||
if (is_array($argument)) {
|
||||
$arguments[$k] = $this->updateArgumentReferences($argument, $currentId, $newId);
|
||||
} elseif ($argument instanceof Reference) {
|
||||
if ($currentId === (string) $argument) {
|
||||
$arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
|
||||
$this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $this->sourceId, $currentId, $newId));
|
||||
}
|
||||
$arguments[$k] = $this->updateArgumentReferences($replacements, $definitionId, $argument);
|
||||
continue;
|
||||
}
|
||||
// Skip arguments that don't need replacement
|
||||
if (!$argument instanceof Reference) {
|
||||
continue;
|
||||
}
|
||||
$referenceId = (string) $argument;
|
||||
if (!isset($replacements[$referenceId])) {
|
||||
continue;
|
||||
}
|
||||
// Perform the replacement
|
||||
$newId = $replacements[$referenceId];
|
||||
$arguments[$k] = new Reference($newId, $argument->getInvalidBehavior());
|
||||
$this->compiler->addLogMessage($this->formatter->formatUpdateReference($this, $definitionId, $referenceId, $newId));
|
||||
}
|
||||
|
||||
return $arguments;
|
||||
}
|
||||
|
||||
private function updateFactoryServiceReference($factoryService, $currentId, $newId)
|
||||
/**
|
||||
* Returns the updated reference for the factory service.
|
||||
*
|
||||
* @param array $replacements Table of aliases to replace
|
||||
* @param string|null $referenceId Factory service reference identifier
|
||||
*
|
||||
* @return string|null
|
||||
*/
|
||||
private function updateFactoryReferenceId(array $replacements, $referenceId)
|
||||
{
|
||||
if (null === $factoryService) {
|
||||
if (null === $referenceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
return $currentId === $factoryService ? $newId : $factoryService;
|
||||
return isset($replacements[$referenceId]) ? $replacements[$referenceId] : $referenceId;
|
||||
}
|
||||
|
||||
private function updateFactoryReference($factory, $currentId, $newId)
|
||||
private function updateFactoryReference(array $replacements, $factory)
|
||||
{
|
||||
if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) {
|
||||
return $factory;
|
||||
}
|
||||
|
||||
if ($currentId === (string) $factory[0]) {
|
||||
$factory[0] = new Reference($newId, $factory[0]->getInvalidBehavior());
|
||||
if (is_array($factory) && $factory[0] instanceof Reference && isset($replacements[$referenceId = (string) $factory[0]])) {
|
||||
$factory[0] = new Reference($replacements[$referenceId], $factory[0]->getInvalidBehavior());
|
||||
}
|
||||
|
||||
return $factory;
|
||||
|
||||
+5
-1
@@ -136,6 +136,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
|
||||
$def->setFile($parentDef->getFile());
|
||||
$def->setPublic($parentDef->isPublic());
|
||||
$def->setLazy($parentDef->isLazy());
|
||||
$def->setAutowired($parentDef->isAutowired());
|
||||
|
||||
// overwrite with values specified in the decorator
|
||||
$changes = $definition->getChanges();
|
||||
@@ -169,12 +170,15 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
|
||||
if (isset($changes['deprecated'])) {
|
||||
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
|
||||
}
|
||||
if (isset($changes['autowire'])) {
|
||||
$def->setAutowired($definition->isAutowired());
|
||||
}
|
||||
if (isset($changes['decorated_service'])) {
|
||||
$decoratedService = $definition->getDecoratedService();
|
||||
if (null === $decoratedService) {
|
||||
$def->setDecoratedService($decoratedService);
|
||||
} else {
|
||||
$def->setDecoratedService($decoratedService[0], $decoratedService[1]);
|
||||
$def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -12,7 +12,6 @@
|
||||
namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Alias;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
@@ -45,7 +45,7 @@ class ServiceReferenceGraph
|
||||
*
|
||||
* @param string $id The id to retrieve
|
||||
*
|
||||
* @return ServiceReferenceGraphNode The node matching the supplied identifier
|
||||
* @return ServiceReferenceGraphNode
|
||||
*
|
||||
* @throws InvalidArgumentException if no node matches the supplied identifier
|
||||
*/
|
||||
@@ -61,7 +61,7 @@ class ServiceReferenceGraph
|
||||
/**
|
||||
* Returns all nodes.
|
||||
*
|
||||
* @return ServiceReferenceGraphNode[] An array of all ServiceReferenceGraphNode objects
|
||||
* @return ServiceReferenceGraphNode[]
|
||||
*/
|
||||
public function getNodes()
|
||||
{
|
||||
|
||||
@@ -25,8 +25,6 @@ class ServiceReferenceGraphEdge
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ServiceReferenceGraphNode $sourceNode
|
||||
* @param ServiceReferenceGraphNode $destNode
|
||||
* @param string $value
|
||||
@@ -41,7 +39,7 @@ class ServiceReferenceGraphEdge
|
||||
/**
|
||||
* Returns the value of the edge.
|
||||
*
|
||||
* @return ServiceReferenceGraphNode
|
||||
* @return string
|
||||
*/
|
||||
public function getValue()
|
||||
{
|
||||
|
||||
@@ -29,8 +29,6 @@ class ServiceReferenceGraphNode
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id The node identifier
|
||||
* @param mixed $value The node value
|
||||
*/
|
||||
|
||||
+9
-6
@@ -78,8 +78,6 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
|
||||
private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_');
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ParameterBagInterface $parameterBag A ParameterBagInterface instance
|
||||
*/
|
||||
public function __construct(ParameterBagInterface $parameterBag = null)
|
||||
@@ -297,10 +295,10 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
|
||||
}
|
||||
|
||||
$alternatives = array();
|
||||
foreach ($this->services as $key => $associatedService) {
|
||||
$lev = levenshtein($id, $key);
|
||||
if ($lev <= strlen($id) / 3 || false !== strpos($key, $id)) {
|
||||
$alternatives[] = $key;
|
||||
foreach ($this->getServiceIds() as $knownId) {
|
||||
$lev = levenshtein($id, $knownId);
|
||||
if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) {
|
||||
$alternatives[] = $knownId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +320,11 @@ class Container implements IntrospectableContainerInterface, ResettableContainer
|
||||
return;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
unset($this->loading[$id]);
|
||||
unset($this->services[$id]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
|
||||
+1
-3
@@ -26,9 +26,7 @@ abstract class ContainerAware implements ContainerAwareInterface
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Sets the container.
|
||||
*
|
||||
* @param ContainerInterface|null $container A ContainerInterface instance or null
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setContainer(ContainerInterface $container = null)
|
||||
{
|
||||
|
||||
+31
-30
@@ -201,7 +201,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*
|
||||
* @param ResourceInterface $resource A resource instance
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addResource(ResourceInterface $resource)
|
||||
{
|
||||
@@ -219,7 +219,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*
|
||||
* @param ResourceInterface[] $resources An array of resources
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setResources(array $resources)
|
||||
{
|
||||
@@ -237,7 +237,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*
|
||||
* @param object $object An object instance
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addObjectResource($object)
|
||||
{
|
||||
@@ -253,7 +253,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*
|
||||
* @param \ReflectionClass $class
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addClassResource(\ReflectionClass $class)
|
||||
{
|
||||
@@ -276,7 +276,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
* @param string $extension The extension alias or namespace
|
||||
* @param array $values An array of values that customizes the extension
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws BadMethodCallException When this ContainerBuilder is frozen
|
||||
* @throws \LogicException if the container is frozen
|
||||
@@ -300,7 +300,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
* @param CompilerPassInterface $pass A compiler pass
|
||||
* @param string $type The type of compiler pass
|
||||
*
|
||||
* @return ContainerBuilder The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION)
|
||||
{
|
||||
@@ -354,7 +354,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
/**
|
||||
* Returns all Scope children.
|
||||
*
|
||||
* @return array An array of scope children.
|
||||
* @return array An array of scope children
|
||||
*
|
||||
* @deprecated since version 2.8, to be removed in 3.0.
|
||||
*/
|
||||
@@ -381,21 +381,14 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
public function set($id, $service, $scope = self::SCOPE_CONTAINER)
|
||||
{
|
||||
$id = strtolower($id);
|
||||
$set = isset($this->definitions[$id]);
|
||||
|
||||
if ($this->isFrozen()) {
|
||||
if ($this->isFrozen() && ($set || isset($this->obsoleteDefinitions[$id])) && !$this->{$set ? 'definitions' : 'obsoleteDefinitions'}[$id]->isSynthetic()) {
|
||||
// setting a synthetic service on a frozen container is alright
|
||||
if (
|
||||
(!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id]))
|
||||
||
|
||||
(isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())
|
||||
||
|
||||
(isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic())
|
||||
) {
|
||||
throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
|
||||
}
|
||||
throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
|
||||
}
|
||||
|
||||
if (isset($this->definitions[$id])) {
|
||||
if ($set) {
|
||||
$this->obsoleteDefinitions[$id] = $this->definitions[$id];
|
||||
}
|
||||
|
||||
@@ -456,7 +449,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
}
|
||||
|
||||
if (!array_key_exists($id, $this->definitions) && isset($this->aliasDefinitions[$id])) {
|
||||
return $this->get($this->aliasDefinitions[$id]);
|
||||
return $this->get((string) $this->aliasDefinitions[$id], $invalidBehavior);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -480,6 +473,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
return;
|
||||
}
|
||||
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
unset($this->loading[$id]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
@@ -506,7 +503,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
* parameter, the value will still be 'bar' as defined in the ContainerBuilder
|
||||
* constructor.
|
||||
*
|
||||
* @param ContainerBuilder $container The ContainerBuilder instance to merge.
|
||||
* @param ContainerBuilder $container The ContainerBuilder instance to merge
|
||||
*
|
||||
* @throws BadMethodCallException When this ContainerBuilder is frozen
|
||||
*/
|
||||
@@ -862,6 +859,10 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*/
|
||||
public function createService(Definition $definition, $id, $tryProxy = true)
|
||||
{
|
||||
if ($definition instanceof DefinitionDecorator) {
|
||||
throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
|
||||
}
|
||||
|
||||
if ($definition->isSynthetic()) {
|
||||
throw new RuntimeException(sprintf('You have requested a synthetic service ("%s"). The DIC does not know how to construct this service.', $id));
|
||||
}
|
||||
@@ -936,15 +937,15 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
$this->shareService($definition, $service, $id);
|
||||
}
|
||||
|
||||
foreach ($definition->getMethodCalls() as $call) {
|
||||
$this->callMethod($service, $call);
|
||||
}
|
||||
|
||||
$properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())));
|
||||
foreach ($properties as $name => $value) {
|
||||
$service->$name = $value;
|
||||
}
|
||||
|
||||
foreach ($definition->getMethodCalls() as $call) {
|
||||
$this->callMethod($service, $call);
|
||||
}
|
||||
|
||||
if ($callable = $definition->getConfigurator()) {
|
||||
if (is_array($callable)) {
|
||||
$callable[0] = $parameterBag->resolveValue($callable[0]);
|
||||
@@ -1007,7 +1008,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
*
|
||||
* @param string $name The tag name
|
||||
*
|
||||
* @return array An array of tags with the tagged service as key, holding a list of attribute arrays.
|
||||
* @return array An array of tags with the tagged service as key, holding a list of attribute arrays
|
||||
*/
|
||||
public function findTaggedServiceIds($name)
|
||||
{
|
||||
@@ -1063,7 +1064,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
/**
|
||||
* Returns the Service Conditionals.
|
||||
*
|
||||
* @param mixed $value An array of conditionals to return.
|
||||
* @param mixed $value An array of conditionals to return
|
||||
*
|
||||
* @return array An array of Service conditionals
|
||||
*/
|
||||
@@ -1144,15 +1145,15 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
|
||||
/**
|
||||
* Shares a given service in the container.
|
||||
*
|
||||
* @param Definition $definition
|
||||
* @param mixed $service
|
||||
* @param string $id
|
||||
* @param Definition $definition
|
||||
* @param mixed $service
|
||||
* @param string|null $id
|
||||
*
|
||||
* @throws InactiveScopeException
|
||||
*/
|
||||
private function shareService(Definition $definition, $service, $id)
|
||||
{
|
||||
if ($definition->isShared() && self::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
|
||||
if (null !== $id && $definition->isShared() && self::SCOPE_PROTOTYPE !== $scope = $definition->getScope(false)) {
|
||||
if (self::SCOPE_CONTAINER !== $scope && !isset($this->scopedServices[$scope])) {
|
||||
throw new InactiveScopeException($id, $scope);
|
||||
}
|
||||
|
||||
+36
-34
@@ -47,8 +47,6 @@ class Definition
|
||||
protected $arguments;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string|null $class The service class
|
||||
* @param array $arguments An array of arguments to pass to the service constructor
|
||||
*/
|
||||
@@ -63,7 +61,7 @@ class Definition
|
||||
*
|
||||
* @param string|array $factory A PHP function or an array containing a class/Reference and a method to call
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setFactory($factory)
|
||||
{
|
||||
@@ -92,7 +90,7 @@ class Definition
|
||||
*
|
||||
* @param string $factoryClass The factory class name
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0.
|
||||
*/
|
||||
@@ -126,7 +124,7 @@ class Definition
|
||||
*
|
||||
* @param string $factoryMethod The factory method name
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0.
|
||||
*/
|
||||
@@ -146,7 +144,7 @@ class Definition
|
||||
* @param null|string $renamedId The new decorated service id
|
||||
* @param int $priority The priority of decoration
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
|
||||
*/
|
||||
@@ -166,7 +164,7 @@ class Definition
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service that decorates this service.
|
||||
* Gets the service that this service is decorating.
|
||||
*
|
||||
* @return null|array An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated
|
||||
*/
|
||||
@@ -196,7 +194,7 @@ class Definition
|
||||
*
|
||||
* @param string $factoryService The factory service id
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.6, to be removed in 3.0.
|
||||
*/
|
||||
@@ -232,7 +230,7 @@ class Definition
|
||||
*
|
||||
* @param string $class The service class
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setClass($class)
|
||||
{
|
||||
@@ -256,7 +254,7 @@ class Definition
|
||||
*
|
||||
* @param array $arguments An array of arguments
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setArguments(array $arguments)
|
||||
{
|
||||
@@ -289,7 +287,7 @@ class Definition
|
||||
*
|
||||
* @param mixed $argument An argument
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addArgument($argument)
|
||||
{
|
||||
@@ -304,12 +302,16 @@ class Definition
|
||||
* @param int $index
|
||||
* @param mixed $argument
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws OutOfBoundsException When the replaced argument does not exist
|
||||
*/
|
||||
public function replaceArgument($index, $argument)
|
||||
{
|
||||
if (0 === count($this->arguments)) {
|
||||
throw new OutOfBoundsException('Cannot replace arguments if none have been configured yet.');
|
||||
}
|
||||
|
||||
if ($index < 0 || $index > count($this->arguments) - 1) {
|
||||
throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, count($this->arguments) - 1));
|
||||
}
|
||||
@@ -352,7 +354,7 @@ class Definition
|
||||
*
|
||||
* @param array $calls An array of method calls
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setMethodCalls(array $calls = array())
|
||||
{
|
||||
@@ -370,7 +372,7 @@ class Definition
|
||||
* @param string $method The method name to call
|
||||
* @param array $arguments An array of arguments to pass to the method call
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException on empty $method param
|
||||
*/
|
||||
@@ -389,7 +391,7 @@ class Definition
|
||||
*
|
||||
* @param string $method The method name to remove
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function removeMethodCall($method)
|
||||
{
|
||||
@@ -436,7 +438,7 @@ class Definition
|
||||
*
|
||||
* @param array $tags
|
||||
*
|
||||
* @return Definition the current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setTags(array $tags)
|
||||
{
|
||||
@@ -473,7 +475,7 @@ class Definition
|
||||
* @param string $name The tag name
|
||||
* @param array $attributes An array of attributes
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addTag($name, array $attributes = array())
|
||||
{
|
||||
@@ -499,7 +501,7 @@ class Definition
|
||||
*
|
||||
* @param string $name The tag name
|
||||
*
|
||||
* @return Definition
|
||||
* @return $this
|
||||
*/
|
||||
public function clearTag($name)
|
||||
{
|
||||
@@ -511,7 +513,7 @@ class Definition
|
||||
/**
|
||||
* Clears the tags for this definition.
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function clearTags()
|
||||
{
|
||||
@@ -525,7 +527,7 @@ class Definition
|
||||
*
|
||||
* @param string $file A full pathname to include
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setFile($file)
|
||||
{
|
||||
@@ -549,7 +551,7 @@ class Definition
|
||||
*
|
||||
* @param bool $shared Whether the service must be shared or not
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setShared($shared)
|
||||
{
|
||||
@@ -573,7 +575,7 @@ class Definition
|
||||
*
|
||||
* @param string $scope Whether the service must be shared or not
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.8, to be removed in 3.0.
|
||||
*/
|
||||
@@ -613,7 +615,7 @@ class Definition
|
||||
*
|
||||
* @param bool $boolean
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setPublic($boolean)
|
||||
{
|
||||
@@ -637,7 +639,7 @@ class Definition
|
||||
*
|
||||
* @param bool $boolean
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*
|
||||
* @deprecated since version 2.7, will be removed in 3.0.
|
||||
*/
|
||||
@@ -673,7 +675,7 @@ class Definition
|
||||
*
|
||||
* @param bool $lazy
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setLazy($lazy)
|
||||
{
|
||||
@@ -698,7 +700,7 @@ class Definition
|
||||
*
|
||||
* @param bool $boolean
|
||||
*
|
||||
* @return Definition the current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setSynthetic($boolean)
|
||||
{
|
||||
@@ -724,7 +726,7 @@ class Definition
|
||||
*
|
||||
* @param bool $boolean
|
||||
*
|
||||
* @return Definition the current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setAbstract($boolean)
|
||||
{
|
||||
@@ -751,7 +753,7 @@ class Definition
|
||||
* @param bool $status
|
||||
* @param string $template Template message to use if the definition is deprecated
|
||||
*
|
||||
* @return Definition the current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException When the message template is invalid.
|
||||
*/
|
||||
@@ -802,7 +804,7 @@ class Definition
|
||||
*
|
||||
* @param callable $callable A PHP callable
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setConfigurator($callable)
|
||||
{
|
||||
@@ -826,7 +828,7 @@ class Definition
|
||||
*
|
||||
* @param string[] $types
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutowiringTypes(array $types)
|
||||
{
|
||||
@@ -852,9 +854,9 @@ class Definition
|
||||
/**
|
||||
* Sets autowired.
|
||||
*
|
||||
* @param $autowired
|
||||
* @param bool $autowired
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function setAutowired($autowired)
|
||||
{
|
||||
@@ -878,7 +880,7 @@ class Definition
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function addAutowiringType($type)
|
||||
{
|
||||
@@ -892,7 +894,7 @@ class Definition
|
||||
*
|
||||
* @param string $type
|
||||
*
|
||||
* @return Definition The current instance
|
||||
* @return $this
|
||||
*/
|
||||
public function removeAutowiringType($type)
|
||||
{
|
||||
|
||||
+12
-4
@@ -25,9 +25,7 @@ class DefinitionDecorator extends Definition
|
||||
private $changes = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $parent The id of Definition instance to decorate.
|
||||
* @param string $parent The id of Definition instance to decorate
|
||||
*/
|
||||
public function __construct($parent)
|
||||
{
|
||||
@@ -166,6 +164,16 @@ class DefinitionDecorator extends Definition
|
||||
return parent::setDeprecated($boolean, $template);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setAutowired($autowired)
|
||||
{
|
||||
$this->changes['autowire'] = true;
|
||||
|
||||
return parent::setAutowired($autowired);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an argument to pass to the service constructor/factory method.
|
||||
*
|
||||
@@ -204,7 +212,7 @@ class DefinitionDecorator extends Definition
|
||||
* @param int $index
|
||||
* @param mixed $value
|
||||
*
|
||||
* @return DefinitionDecorator the current instance
|
||||
* @return $this
|
||||
*
|
||||
* @throws InvalidArgumentException when $index isn't an integer
|
||||
*/
|
||||
|
||||
@@ -23,8 +23,6 @@ abstract class Dumper implements DumperInterface
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ContainerBuilder $container The service container to dump
|
||||
*/
|
||||
public function __construct(ContainerBuilder $container)
|
||||
|
||||
@@ -130,7 +130,7 @@ class GraphvizDumper extends Dumper
|
||||
*
|
||||
* @return array An array of edges
|
||||
*/
|
||||
private function findEdges($id, $arguments, $required, $name)
|
||||
private function findEdges($id, array $arguments, $required, $name)
|
||||
{
|
||||
$edges = array();
|
||||
foreach ($arguments as $argument) {
|
||||
@@ -246,7 +246,7 @@ class GraphvizDumper extends Dumper
|
||||
*
|
||||
* @return string A comma separated list of attributes
|
||||
*/
|
||||
private function addAttributes($attributes)
|
||||
private function addAttributes(array $attributes)
|
||||
{
|
||||
$code = array();
|
||||
foreach ($attributes as $k => $v) {
|
||||
@@ -263,7 +263,7 @@ class GraphvizDumper extends Dumper
|
||||
*
|
||||
* @return string A space separated list of options
|
||||
*/
|
||||
private function addOptions($options)
|
||||
private function addOptions(array $options)
|
||||
{
|
||||
$code = array();
|
||||
foreach ($options as $k => $v) {
|
||||
|
||||
+57
-33
@@ -144,6 +144,7 @@ class PhpDumper extends Dumper
|
||||
if ($this->container->isFrozen()) {
|
||||
$code .= $this->addFrozenConstructor();
|
||||
$code .= $this->addFrozenCompile();
|
||||
$code .= $this->addIsFrozenMethod();
|
||||
} else {
|
||||
$code .= $this->addConstructor();
|
||||
}
|
||||
@@ -334,8 +335,8 @@ class PhpDumper extends Dumper
|
||||
$code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = ');
|
||||
|
||||
if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) {
|
||||
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
|
||||
$code .= $this->addServiceProperties(null, $sDefinition, $name);
|
||||
$code .= $this->addServiceMethodCalls(null, $sDefinition, $name);
|
||||
$code .= $this->addServiceConfigurator(null, $sDefinition, $name);
|
||||
}
|
||||
|
||||
@@ -374,7 +375,7 @@ class PhpDumper extends Dumper
|
||||
* @throws InvalidArgumentException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
private function addServiceInstance($id, $definition)
|
||||
private function addServiceInstance($id, Definition $definition)
|
||||
{
|
||||
$class = $definition->getClass();
|
||||
|
||||
@@ -424,7 +425,7 @@ class PhpDumper extends Dumper
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function isSimpleInstance($id, $definition)
|
||||
private function isSimpleInstance($id, Definition $definition)
|
||||
{
|
||||
foreach (array_merge(array($definition), $this->getInlinedDefinitions($definition)) as $sDefinition) {
|
||||
if ($definition !== $sDefinition && !$this->hasReference($id, $sDefinition->getMethodCalls())) {
|
||||
@@ -448,7 +449,7 @@ class PhpDumper extends Dumper
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function addServiceMethodCalls($id, $definition, $variableName = 'instance')
|
||||
private function addServiceMethodCalls($id, Definition $definition, $variableName = 'instance')
|
||||
{
|
||||
$calls = '';
|
||||
foreach ($definition->getMethodCalls() as $call) {
|
||||
@@ -463,7 +464,7 @@ class PhpDumper extends Dumper
|
||||
return $calls;
|
||||
}
|
||||
|
||||
private function addServiceProperties($id, $definition, $variableName = 'instance')
|
||||
private function addServiceProperties($id, Definition $definition, $variableName = 'instance')
|
||||
{
|
||||
$code = '';
|
||||
foreach ($definition->getProperties() as $name => $value) {
|
||||
@@ -483,7 +484,7 @@ class PhpDumper extends Dumper
|
||||
*
|
||||
* @throws ServiceCircularReferenceException when the container contains a circular reference
|
||||
*/
|
||||
private function addServiceInlinedDefinitionsSetup($id, $definition)
|
||||
private function addServiceInlinedDefinitionsSetup($id, Definition $definition)
|
||||
{
|
||||
$this->referenceVariables[$id] = new Variable('instance');
|
||||
|
||||
@@ -506,8 +507,8 @@ class PhpDumper extends Dumper
|
||||
}
|
||||
|
||||
$name = (string) $this->definitionVariables->offsetGet($iDefinition);
|
||||
$code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
|
||||
$code .= $this->addServiceProperties(null, $iDefinition, $name);
|
||||
$code .= $this->addServiceMethodCalls(null, $iDefinition, $name);
|
||||
$code .= $this->addServiceConfigurator(null, $iDefinition, $name);
|
||||
}
|
||||
|
||||
@@ -527,7 +528,7 @@ class PhpDumper extends Dumper
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function addServiceConfigurator($id, $definition, $variableName = 'instance')
|
||||
private function addServiceConfigurator($id, Definition $definition, $variableName = 'instance')
|
||||
{
|
||||
if (!$callable = $definition->getConfigurator()) {
|
||||
return '';
|
||||
@@ -559,7 +560,7 @@ class PhpDumper extends Dumper
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function addService($id, $definition)
|
||||
private function addService($id, Definition $definition)
|
||||
{
|
||||
$this->definitionVariables = new \SplObjectStorage();
|
||||
$this->referenceVariables = array();
|
||||
@@ -570,22 +571,22 @@ class PhpDumper extends Dumper
|
||||
if ($definition->isSynthetic()) {
|
||||
$return[] = '@throws RuntimeException always since this service is expected to be injected dynamically';
|
||||
} elseif ($class = $definition->getClass()) {
|
||||
$return[] = sprintf('@return %s A %s instance.', 0 === strpos($class, '%') ? 'object' : '\\'.ltrim($class, '\\'), ltrim($class, '\\'));
|
||||
$return[] = sprintf('@return %s A %s instance', 0 === strpos($class, '%') ? 'object' : '\\'.ltrim($class, '\\'), ltrim($class, '\\'));
|
||||
} elseif ($definition->getFactory()) {
|
||||
$factory = $definition->getFactory();
|
||||
if (is_string($factory)) {
|
||||
$return[] = sprintf('@return object An instance returned by %s().', $factory);
|
||||
$return[] = sprintf('@return object An instance returned by %s()', $factory);
|
||||
} elseif (is_array($factory) && (is_string($factory[0]) || $factory[0] instanceof Definition || $factory[0] instanceof Reference)) {
|
||||
if (is_string($factory[0]) || $factory[0] instanceof Reference) {
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s().', (string) $factory[0], $factory[1]);
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s()', (string) $factory[0], $factory[1]);
|
||||
} elseif ($factory[0] instanceof Definition) {
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s().', $factory[0]->getClass(), $factory[1]);
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s()', $factory[0]->getClass(), $factory[1]);
|
||||
}
|
||||
}
|
||||
} elseif ($definition->getFactoryClass(false)) {
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryClass(false), $definition->getFactoryMethod(false));
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryClass(false), $definition->getFactoryMethod(false));
|
||||
} elseif ($definition->getFactoryService(false)) {
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s().', $definition->getFactoryService(false), $definition->getFactoryMethod(false));
|
||||
$return[] = sprintf('@return object An instance returned by %s::%s()', $definition->getFactoryService(false), $definition->getFactoryMethod(false));
|
||||
}
|
||||
|
||||
$scope = $definition->getScope(false);
|
||||
@@ -682,8 +683,8 @@ EOF;
|
||||
$this->addServiceInlinedDefinitions($id, $definition).
|
||||
$this->addServiceInstance($id, $definition).
|
||||
$this->addServiceInlinedDefinitionsSetup($id, $definition).
|
||||
$this->addServiceMethodCalls($id, $definition).
|
||||
$this->addServiceProperties($id, $definition).
|
||||
$this->addServiceMethodCalls($id, $definition).
|
||||
$this->addServiceConfigurator($id, $definition).
|
||||
$this->addServiceReturn($id, $definition)
|
||||
;
|
||||
@@ -977,6 +978,26 @@ EOF;
|
||||
throw new LogicException('You cannot compile a dumped frozen container.');
|
||||
}
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the isFrozen method for a frozen container.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function addIsFrozenMethod()
|
||||
{
|
||||
return <<<EOF
|
||||
|
||||
/*{$this->docStar}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isFrozen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
EOF;
|
||||
}
|
||||
|
||||
@@ -1008,11 +1029,7 @@ EOF;
|
||||
private function addAliases()
|
||||
{
|
||||
if (!$aliases = $this->container->getAliases()) {
|
||||
if ($this->container->isFrozen()) {
|
||||
return "\n \$this->aliases = array();\n";
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
return $this->container->isFrozen() ? "\n \$this->aliases = array();\n" : '';
|
||||
}
|
||||
|
||||
$code = " \$this->aliases = array(\n";
|
||||
@@ -1123,7 +1140,7 @@ EOF;
|
||||
*
|
||||
* @throws InvalidArgumentException
|
||||
*/
|
||||
private function exportParameters($parameters, $path = '', $indent = 12)
|
||||
private function exportParameters(array $parameters, $path = '', $indent = 12)
|
||||
{
|
||||
$php = array();
|
||||
foreach ($parameters as $key => $value) {
|
||||
@@ -1288,10 +1305,17 @@ EOF;
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($deep && !isset($visited[$argumentId])) {
|
||||
if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
|
||||
$visited[$argumentId] = true;
|
||||
|
||||
$service = $this->container->getDefinition($argumentId);
|
||||
|
||||
// if the proxy manager is enabled, disable searching for references in lazy services,
|
||||
// as these services will be instantiated lazily and don't have direct related references.
|
||||
if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
|
||||
|
||||
if ($this->hasReference($id, $arguments, $deep, $visited)) {
|
||||
@@ -1374,9 +1398,9 @@ EOF;
|
||||
$service = $this->dumpValue($value->getFactoryService(false));
|
||||
|
||||
return sprintf('%s->%s(%s)', 0 === strpos($service, '$') ? sprintf('$this->get(%s)', $service) : $this->getServiceCall($value->getFactoryService(false)), $value->getFactoryMethod(false), implode(', ', $arguments));
|
||||
} else {
|
||||
throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
|
||||
}
|
||||
|
||||
throw new RuntimeException('Cannot dump definitions which have factory method without factory service or factory class.');
|
||||
}
|
||||
|
||||
$class = $value->getClass();
|
||||
@@ -1414,9 +1438,9 @@ EOF;
|
||||
}
|
||||
} elseif (is_object($value) || is_resource($value)) {
|
||||
throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.');
|
||||
} else {
|
||||
return $this->export($value);
|
||||
}
|
||||
|
||||
return $this->export($value);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1485,13 +1509,13 @@ EOF;
|
||||
|
||||
if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
|
||||
return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id);
|
||||
} else {
|
||||
if ($this->container->hasAlias($id)) {
|
||||
$id = (string) $this->container->getAlias($id);
|
||||
}
|
||||
|
||||
return sprintf('$this->get(\'%s\')', $id);
|
||||
}
|
||||
|
||||
if ($this->container->hasAlias($id)) {
|
||||
$id = (string) $this->container->getAlias($id);
|
||||
}
|
||||
|
||||
return sprintf('$this->get(\'%s\')', $id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -286,7 +286,7 @@ class XmlDumper extends Dumper
|
||||
* @param \DOMElement $parent
|
||||
* @param string $keyAttribute
|
||||
*/
|
||||
private function convertParameters($parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
|
||||
private function convertParameters(array $parameters, $type, \DOMElement $parent, $keyAttribute = 'key')
|
||||
{
|
||||
$withKeys = array_keys($parameters) !== range(0, count($parameters) - 1);
|
||||
foreach ($parameters as $key => $value) {
|
||||
@@ -335,7 +335,7 @@ class XmlDumper extends Dumper
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function escape($arguments)
|
||||
private function escape(array $arguments)
|
||||
{
|
||||
$args = array();
|
||||
foreach ($arguments as $k => $v) {
|
||||
|
||||
@@ -188,7 +188,7 @@ class YamlDumper extends Dumper
|
||||
return sprintf(" %s: '@%s'\n", $alias, $id);
|
||||
}
|
||||
|
||||
return sprintf(" %s:\n alias: %s\n public: false", $alias, $id);
|
||||
return sprintf(" %s:\n alias: %s\n public: false\n", $alias, $id);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,7 +327,7 @@ class YamlDumper extends Dumper
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function prepareParameters($parameters, $escape = true)
|
||||
private function prepareParameters(array $parameters, $escape = true)
|
||||
{
|
||||
$filtered = array();
|
||||
foreach ($parameters as $key => $value) {
|
||||
@@ -350,7 +350,7 @@ class YamlDumper extends Dumper
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function escape($arguments)
|
||||
private function escape(array $arguments)
|
||||
{
|
||||
$args = array();
|
||||
foreach ($arguments as $k => $v) {
|
||||
|
||||
@@ -24,8 +24,6 @@ class ParameterNotFoundException extends InvalidArgumentException
|
||||
private $alternatives;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $key The requested parameter key
|
||||
* @param string $sourceId The service id that references the non-existent parameter
|
||||
* @param string $sourceKey The parameter key that references the non-existent parameter
|
||||
|
||||
@@ -27,9 +27,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface;
|
||||
abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Returns the base path for the XSD files.
|
||||
*
|
||||
* @return string The XSD base path
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getXsdValidationBasePath()
|
||||
{
|
||||
@@ -37,9 +35,7 @@ abstract class Extension implements ExtensionInterface, ConfigurationExtensionIn
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the namespace to be used for this extension (XML namespace).
|
||||
*
|
||||
* @return string The XML namespace
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2004-2016 Fabien Potencier
|
||||
Copyright (c) 2004-2017 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
|
||||
|
||||
@@ -26,8 +26,6 @@ class ClosureLoader extends Loader
|
||||
private $container;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
*/
|
||||
public function __construct(ContainerBuilder $container)
|
||||
|
||||
@@ -25,8 +25,6 @@ abstract class FileLoader extends BaseFileLoader
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param ContainerBuilder $container A ContainerBuilder instance
|
||||
* @param FileLocatorInterface $locator A FileLocator instance
|
||||
*/
|
||||
|
||||
+22
-23
@@ -187,7 +187,7 @@ class XmlFileLoader extends FileLoader
|
||||
}
|
||||
|
||||
if ($deprecated = $this->getChildren($service, 'deprecated')) {
|
||||
$definition->setDeprecated(true, $deprecated[0]->nodeValue);
|
||||
$definition->setDeprecated(true, $deprecated[0]->nodeValue ?: null);
|
||||
}
|
||||
|
||||
$definition->setArguments($this->getArgumentsAsPhp($service, 'argument'));
|
||||
@@ -315,6 +315,10 @@ class XmlFileLoader extends FileLoader
|
||||
if ($services = $this->getChildren($node, 'service')) {
|
||||
$definitions[$id] = array($services[0], $file, false);
|
||||
$services[0]->setAttribute('id', $id);
|
||||
|
||||
// anonymous services are always private
|
||||
// we could not use the constant false here, because of XML parsing
|
||||
$services[0]->setAttribute('public', 'false');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,11 +329,7 @@ class XmlFileLoader extends FileLoader
|
||||
// give it a unique name
|
||||
$id = sprintf('%s_%d', hash('sha256', $file), ++$count);
|
||||
$node->setAttribute('id', $id);
|
||||
|
||||
if ($services = $this->getChildren($node, 'service')) {
|
||||
$definitions[$id] = array($node, $file, true);
|
||||
$services[0]->setAttribute('id', $id);
|
||||
}
|
||||
$definitions[$id] = array($node, $file, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,10 +338,6 @@ class XmlFileLoader extends FileLoader
|
||||
foreach ($definitions as $id => $def) {
|
||||
list($domElement, $file, $wild) = $def;
|
||||
|
||||
// anonymous services are always private
|
||||
// we could not use the constant false here, because of XML parsing
|
||||
$domElement->setAttribute('public', 'false');
|
||||
|
||||
if (null !== $definition = $this->parseDefinition($domElement, $file)) {
|
||||
$this->container->setDefinition($id, $definition);
|
||||
}
|
||||
@@ -373,21 +369,22 @@ class XmlFileLoader extends FileLoader
|
||||
$arg->setAttribute('key', $arg->getAttribute('name'));
|
||||
}
|
||||
|
||||
if (!$arg->hasAttribute('key')) {
|
||||
$key = !$arguments ? 0 : max(array_keys($arguments)) + 1;
|
||||
} else {
|
||||
$key = $arg->getAttribute('key');
|
||||
}
|
||||
|
||||
// parameter keys are case insensitive
|
||||
if ('parameter' == $name && $lowercase) {
|
||||
$key = strtolower($key);
|
||||
}
|
||||
|
||||
// this is used by DefinitionDecorator to overwrite a specific
|
||||
// argument of the parent definition
|
||||
if ($arg->hasAttribute('index')) {
|
||||
$key = 'index_'.$arg->getAttribute('index');
|
||||
} elseif (!$arg->hasAttribute('key')) {
|
||||
// Append an empty argument, then fetch its key to overwrite it later
|
||||
$arguments[] = null;
|
||||
$keys = array_keys($arguments);
|
||||
$key = array_pop($keys);
|
||||
} else {
|
||||
$key = $arg->getAttribute('key');
|
||||
|
||||
// parameter keys are case insensitive
|
||||
if ('parameter' == $name && $lowercase) {
|
||||
$key = strtolower($key);
|
||||
}
|
||||
}
|
||||
|
||||
switch ($arg->getAttribute('type')) {
|
||||
@@ -418,7 +415,7 @@ class XmlFileLoader extends FileLoader
|
||||
$arguments[$key] = $arg->nodeValue;
|
||||
break;
|
||||
case 'constant':
|
||||
$arguments[$key] = constant($arg->nodeValue);
|
||||
$arguments[$key] = constant(trim($arg->nodeValue));
|
||||
break;
|
||||
default:
|
||||
$arguments[$key] = XmlUtils::phpize($arg->nodeValue);
|
||||
@@ -511,7 +508,9 @@ $imports
|
||||
EOF
|
||||
;
|
||||
|
||||
$disableEntities = libxml_disable_entity_loader(false);
|
||||
$valid = @$dom->schemaValidateSource($source);
|
||||
libxml_disable_entity_loader($disableEntities);
|
||||
|
||||
foreach ($tmpfiles as $tmpfile) {
|
||||
@unlink($tmpfile);
|
||||
@@ -589,7 +588,7 @@ EOF
|
||||
*
|
||||
* @return array A PHP array
|
||||
*/
|
||||
public static function convertDomElementToArray(\DomElement $element)
|
||||
public static function convertDomElementToArray(\DOMElement $element)
|
||||
{
|
||||
return XmlUtils::convertDomElementToArray($element);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class YamlFileLoader extends FileLoader
|
||||
* @param array $content
|
||||
* @param string $file
|
||||
*/
|
||||
private function parseImports($content, $file)
|
||||
private function parseImports(array $content, $file)
|
||||
{
|
||||
if (!isset($content['imports'])) {
|
||||
return;
|
||||
@@ -112,7 +112,7 @@ class YamlFileLoader extends FileLoader
|
||||
* @param array $content
|
||||
* @param string $file
|
||||
*/
|
||||
private function parseDefinitions($content, $file)
|
||||
private function parseDefinitions(array $content, $file)
|
||||
{
|
||||
if (!isset($content['services'])) {
|
||||
return;
|
||||
@@ -130,9 +130,9 @@ class YamlFileLoader extends FileLoader
|
||||
/**
|
||||
* Parses a definition.
|
||||
*
|
||||
* @param string $id
|
||||
* @param array $service
|
||||
* @param string $file
|
||||
* @param string $id
|
||||
* @param array|string $service
|
||||
* @param string $file
|
||||
*
|
||||
* @throws InvalidArgumentException When tags are invalid
|
||||
*/
|
||||
@@ -420,9 +420,9 @@ class YamlFileLoader extends FileLoader
|
||||
{
|
||||
if (is_array($value)) {
|
||||
$value = array_map(array($this, 'resolveServices'), $value);
|
||||
} elseif (is_string($value) && 0 === strpos($value, '@=')) {
|
||||
} elseif (is_string($value) && 0 === strpos($value, '@=')) {
|
||||
return new Expression(substr($value, 2));
|
||||
} elseif (is_string($value) && 0 === strpos($value, '@')) {
|
||||
} elseif (is_string($value) && 0 === strpos($value, '@')) {
|
||||
if (0 === strpos($value, '@@')) {
|
||||
$value = substr($value, 1);
|
||||
$invalidBehavior = null;
|
||||
@@ -454,7 +454,7 @@ class YamlFileLoader extends FileLoader
|
||||
*
|
||||
* @param array $content
|
||||
*/
|
||||
private function loadFromExtensions($content)
|
||||
private function loadFromExtensions(array $content)
|
||||
{
|
||||
foreach ($content as $namespace => $values) {
|
||||
if (in_array($namespace, array('imports', 'parameters', 'services'))) {
|
||||
|
||||
+21
-7
@@ -24,14 +24,28 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:element name="imports" type="imports" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="parameters" type="parameters" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:element name="services" type="services" minOccurs="0" maxOccurs="1" />
|
||||
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xsd:group ref="foreign" />
|
||||
<xsd:sequence minOccurs="0">
|
||||
<xsd:element name="imports" type="imports" />
|
||||
<xsd:group ref="foreign" />
|
||||
</xsd:sequence>
|
||||
<xsd:sequence minOccurs="0">
|
||||
<xsd:element name="parameters" type="parameters" />
|
||||
<xsd:group ref="foreign" />
|
||||
</xsd:sequence>
|
||||
<xsd:sequence minOccurs="0">
|
||||
<xsd:element name="services" type="services" />
|
||||
<xsd:group ref="foreign" />
|
||||
</xsd:sequence>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:group name="foreign">
|
||||
<xsd:sequence>
|
||||
<xsd:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xsd:sequence>
|
||||
</xsd:group>
|
||||
|
||||
<xsd:complexType name="services">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
@@ -139,7 +153,7 @@
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
<xsd:attribute name="key" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="on-invalid" type="xsd:string" />
|
||||
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
||||
<xsd:attribute name="strict" type="boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
@@ -152,7 +166,7 @@
|
||||
<xsd:attribute name="id" type="xsd:string" />
|
||||
<xsd:attribute name="key" type="xsd:string" />
|
||||
<xsd:attribute name="index" type="xsd:integer" />
|
||||
<xsd:attribute name="on-invalid" type="xsd:string" />
|
||||
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
||||
<xsd:attribute name="strict" type="boolean" />
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
@@ -21,8 +21,6 @@ class Parameter
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $id The parameter key
|
||||
*/
|
||||
public function __construct($id)
|
||||
@@ -31,8 +29,6 @@ class Parameter
|
||||
}
|
||||
|
||||
/**
|
||||
* __toString.
|
||||
*
|
||||
* @return string The parameter key
|
||||
*/
|
||||
public function __toString()
|
||||
|
||||
@@ -21,8 +21,6 @@ use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||
class FrozenParameterBag extends ParameterBag
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* For performance reasons, the constructor assumes that
|
||||
* all keys are already lowercased.
|
||||
*
|
||||
|
||||
@@ -26,8 +26,6 @@ class ParameterBag implements ParameterBagInterface
|
||||
protected $resolved = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $parameters An array of parameters
|
||||
*/
|
||||
public function __construct(array $parameters = array())
|
||||
@@ -56,9 +54,7 @@ class ParameterBag implements ParameterBagInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service container parameters.
|
||||
*
|
||||
* @return array An array of parameters
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function all()
|
||||
{
|
||||
@@ -66,13 +62,7 @@ class ParameterBag implements ParameterBagInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a service container parameter.
|
||||
*
|
||||
* @param string $name The parameter name
|
||||
*
|
||||
* @return mixed The parameter value
|
||||
*
|
||||
* @throws ParameterNotFoundException if the parameter is not defined
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
@@ -109,11 +99,7 @@ class ParameterBag implements ParameterBagInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a parameter name is defined.
|
||||
*
|
||||
* @param string $name The parameter name
|
||||
*
|
||||
* @return bool true if the parameter name is defined, false otherwise
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
@@ -131,7 +117,7 @@ class ParameterBag implements ParameterBagInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces parameter placeholders (%name%) by their values for all parameters.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function resolve()
|
||||
{
|
||||
@@ -266,6 +252,9 @@ class ParameterBag implements ParameterBagInterface
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function unescapeValue($value)
|
||||
{
|
||||
if (is_string($value)) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user