Update to Drupal 8.2.6. For more information, see https://www.drupal.org/project/drupal/releases/8.2.6

This commit is contained in:
Pantheon Automation 2017-02-02 16:28:38 -08:00 committed by Greg Anderson
parent db56c09587
commit f1e72395cb
588 changed files with 26857 additions and 2777 deletions

View file

@ -68,6 +68,16 @@ abstract class Client
$this->followRedirects = (bool) $followRedirect;
}
/**
* Returns whether client automatically follows redirects or not.
*
* @return bool
*/
public function isFollowingRedirects()
{
return $this->followRedirects;
}
/**
* Sets the maximum number of requests that crawler can follow.
*
@ -79,6 +89,16 @@ abstract class Client
$this->followRedirects = -1 != $this->maxRedirects;
}
/**
* Returns the maximum number of requests that crawler can follow.
*
* @return int
*/
public function getMaxRedirects()
{
return $this->maxRedirects;
}
/**
* Sets the insulated flag.
*
@ -103,7 +123,6 @@ abstract class Client
public function setServerParameters(array $server)
{
$this->server = array_merge(array(
'HTTP_HOST' => 'localhost',
'HTTP_USER_AGENT' => 'Symfony2 BrowserKit',
), $server);
}
@ -129,7 +148,7 @@ abstract class Client
*/
public function getServerParameter($key, $default = '')
{
return (isset($this->server[$key])) ? $this->server[$key] : $default;
return isset($this->server[$key]) ? $this->server[$key] : $default;
}
/**
@ -266,21 +285,20 @@ abstract class Client
$uri = $this->getAbsoluteUri($uri);
if (!empty($server['HTTP_HOST'])) {
$uri = preg_replace('{^(https?\://)'.preg_quote($this->extractHost($uri)).'}', '${1}'.$server['HTTP_HOST'], $uri);
}
$server = array_merge($this->server, $server);
if (isset($server['HTTPS'])) {
$uri = preg_replace('{^'.parse_url($uri, PHP_URL_SCHEME).'}', $server['HTTPS'] ? 'https' : 'http', $uri);
}
$server = array_merge($this->server, $server);
if (!$this->history->isEmpty()) {
$server['HTTP_REFERER'] = $this->history->current()->getUri();
}
$server['HTTP_HOST'] = $this->extractHost($uri);
if (empty($server['HTTP_HOST'])) {
$server['HTTP_HOST'] = $this->extractHost($uri);
}
$server['HTTPS'] = 'https' == parse_url($uri, PHP_URL_SCHEME);
$this->internalRequest = new Request($uri, $method, $parameters, $files, $this->cookieJar->allValues($uri), $server, $content);
@ -457,7 +475,7 @@ abstract class Client
$request = $this->internalRequest;
if (in_array($this->internalResponse->getStatus(), array(302, 303))) {
$method = 'get';
$method = 'GET';
$files = array();
$content = null;
} else {
@ -466,7 +484,7 @@ abstract class Client
$content = $request->getContent();
}
if ('get' === strtolower($method)) {
if ('GET' === strtoupper($method)) {
// Don't forward parameters for GET request as it should reach the redirection URI
$parameters = array();
} else {
@ -524,9 +542,9 @@ abstract class Client
return parse_url($currentUri, PHP_URL_SCHEME).':'.$uri;
}
// anchor?
if (!$uri || '#' == $uri[0]) {
return preg_replace('/#.*?$/', '', $currentUri).$uri;
// anchor or query string parameters?
if (!$uri || '#' == $uri[0] || '?' == $uri[0]) {
return preg_replace('/[#?].*?$/', '', $currentUri).$uri;
}
if ('/' !== $uri[0]) {

View file

@ -76,7 +76,7 @@ class Cookie
throw new \UnexpectedValueException(sprintf('The cookie expiration time "%s" is not valid.', $expires));
}
$this->expires = $timestampAsDateTime->getTimestamp();
$this->expires = $timestampAsDateTime->format('U');
}
}
@ -121,7 +121,7 @@ class Cookie
* @param string $cookie A Set-Cookie header value
* @param string $url The base URL
*
* @return Cookie A Cookie instance
* @return static
*
* @throws \InvalidArgumentException
*/
@ -205,13 +205,13 @@ class Cookie
foreach (self::$dateFormats as $dateFormat) {
if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) {
return $date->getTimestamp();
return $date->format('U');
}
}
// attempt a fallback for unusual formatting
if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) {
return $date->getTimestamp();
return $date->format('U');
}
throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue));
@ -304,6 +304,6 @@ class Cookie
*/
public function isExpired()
{
return null !== $this->expires && 0 !== $this->expires && $this->expires < time();
return null !== $this->expires && 0 != $this->expires && $this->expires < time();
}
}

View file

@ -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

View file

@ -1,23 +1,14 @@
BrowserKit Component
====================
BrowserKit simulates the behavior of a web browser.
The component only provides an abstract client and does not provide any
"default" backend for the HTTP layer.
The BrowserKit component simulates the behavior of a web browser, allowing you
to make requests, click on links and submit forms programmatically.
Resources
---------
For a simple implementation of a browser based on an HTTP layer, have a look
at [Goutte](https://github.com/FriendsOfPHP/Goutte).
For an implementation based on HttpKernelInterface, have a look at the
[Client](https://github.com/symfony/symfony/blob/master/src/Symfony/Component/HttpKernel/Client.php)
provided by the HttpKernel component.
You can run the unit tests with the following command:
$ cd path/to/Symfony/Component/BrowserKit/
$ composer install
$ phpunit
* [Documentation](https://symfony.com/doc/current/components/browser_kit/introduction.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)

View file

@ -111,7 +111,7 @@ class Request
/**
* Gets the request raw body data.
*
* @return string The request raw body data.
* @return string The request raw body data
*/
public function getContent()
{

View file

@ -17,22 +17,25 @@
],
"require": {
"php": ">=5.3.9",
"symfony/dom-crawler": "~2.0,>=2.0.5"
"symfony/dom-crawler": "~2.1|~3.0.0"
},
"require-dev": {
"symfony/process": "~2.3.34|~2.7,>=2.7.6",
"symfony/css-selector": "~2.0,>=2.0.5"
"symfony/process": "~2.3.34|~2.7,>=2.7.6|~3.0.0",
"symfony/css-selector": "~2.0,>=2.0.5|~3.0.0"
},
"suggest": {
"symfony/process": ""
},
"autoload": {
"psr-4": { "Symfony\\Component\\BrowserKit\\": "" }
"psr-4": { "Symfony\\Component\\BrowserKit\\": "" },
"exclude-from-classmap": [
"/Tests/"
]
},
"minimum-stability": "dev",
"extra": {
"branch-alias": {
"dev-master": "2.7-dev"
"dev-master": "2.8-dev"
}
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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());

View file

@ -64,7 +64,7 @@ class ClassMapGenerator
continue;
}
$path = $file->getRealPath();
$path = $file->getRealPath() ?: $file->getPathname();
if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') {
continue;

View file

@ -89,7 +89,7 @@ class DebugClassLoader
*/
public function findFile($class)
{
return $this->classFinder->findFile($class);
return $this->classFinder->findFile($class) ?: null;
}
/**

View file

@ -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

View file

@ -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;

View file

@ -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);
}

View file

@ -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
@ -857,17 +864,25 @@ class Application
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 +980,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 +1039,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 +1138,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)
{

View file

@ -205,8 +205,6 @@ class Command
*
* @return int The command exit code
*
* @throws \Exception
*
* @see setCode()
* @see execute()
*/
@ -232,7 +230,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 +275,7 @@ class Command
*
* @param callable $code A callable(InputInterface $input, OutputInterface $output)
*
* @return Command The current instance
* @return $this
*
* @throws InvalidArgumentException
*
@ -285,7 +290,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 +320,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 +339,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 +387,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 +405,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 +424,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 +447,7 @@ class Command
*
* @param string $title The process title
*
* @return Command The current instance
* @return $this
*/
public function setProcessTitle($title)
{
@ -458,7 +471,7 @@ class Command
*
* @param string $description The description for the command
*
* @return Command The current instance
* @return $this
*/
public function setDescription($description)
{
@ -482,7 +495,7 @@ class Command
*
* @param string $help The help for the command
*
* @return Command The current instance
* @return $this
*/
public function setHelp($help)
{
@ -528,7 +541,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 +592,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 +623,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);
}

View file

@ -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']) {

View file

@ -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;

View file

@ -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()
{

View file

@ -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)
{

View file

@ -104,7 +104,7 @@ class OutputFormatterStyleStack
/**
* @param OutputFormatterStyleInterface $emptyStyle
*
* @return OutputFormatterStyleStack
* @return $this
*/
public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
{

View file

@ -78,7 +78,7 @@ class DescriptorHelper extends Helper
* @param string $format
* @param DescriptorInterface $descriptor
*
* @return DescriptorHelper
* @return $this
*/
public function register($format, DescriptorInterface $descriptor)
{

View file

@ -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];
}
}

View file

@ -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);

View file

@ -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()

View file

@ -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 {

View file

@ -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()

View file

@ -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
*
@ -397,6 +399,8 @@ class QuestionHelper extends Helper
try {
return call_user_func($question->getValidator(), $interviewer());
} catch (RuntimeException $e) {
throw $e;
} catch (\Exception $error) {
}
}

View file

@ -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);

View file

@ -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,7 +436,7 @@ 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()));
@ -569,6 +558,18 @@ class Table
continue;
}
foreach ($row as $i => $cell) {
if ($cell instanceof TableCell) {
$textLength = strlen($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 +600,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 +648,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));
}
}

View file

@ -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)
{

View file

@ -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())
{

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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()
{

View file

@ -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)
{

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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
{

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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)
{

View file

@ -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)
{

View file

@ -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;
}
}

View file

@ -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)
{

View file

@ -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)
{

View file

@ -17,7 +17,8 @@
],
"require": {
"php": ">=5.3.9",
"symfony/polyfill-mbstring": "~1.0"
"symfony/polyfill-mbstring": "~1.0",
"symfony/debug": "~2.7,>=2.7.2|~3.0.0"
},
"require-dev": {
"symfony/event-dispatcher": "~2.1|~3.0.0",

View file

@ -68,8 +68,8 @@ class CssSelector
* Optionally, a prefix can be added to the resulting XPath
* expression with the $prefix parameter.
*
* @param mixed $cssExpr The CSS expression.
* @param string $prefix An optional prefix for the XPath expression.
* @param mixed $cssExpr The CSS expression
* @param string $prefix An optional prefix for the XPath expression
*
* @return string
*/

View file

@ -29,7 +29,7 @@ class CssSelectorConverter
private $translator;
/**
* @param bool $html Whether HTML support should be enabled. Disable it for XML documents.
* @param bool $html Whether HTML support should be enabled. Disable it for XML documents
*/
public function __construct($html = true)
{
@ -53,8 +53,8 @@ class CssSelectorConverter
* Optionally, a prefix can be added to the resulting XPath
* expression with the $prefix parameter.
*
* @param string $cssExpr The CSS expression.
* @param string $prefix An optional prefix for the XPath expression.
* @param string $cssExpr The CSS expression
* @param string $prefix An optional prefix for the XPath expression
*
* @return string
*/

View file

@ -27,7 +27,7 @@ class SyntaxErrorException extends ParseException
* @param string $expectedValue
* @param Token $foundToken
*
* @return SyntaxErrorException
* @return self
*/
public static function unexpectedToken($expectedValue, Token $foundToken)
{
@ -38,7 +38,7 @@ class SyntaxErrorException extends ParseException
* @param string $pseudoElement
* @param string $unexpectedLocation
*
* @return SyntaxErrorException
* @return self
*/
public static function pseudoElementFound($pseudoElement, $unexpectedLocation)
{
@ -48,7 +48,7 @@ class SyntaxErrorException extends ParseException
/**
* @param int $position
*
* @return SyntaxErrorException
* @return self
*/
public static function unclosedString($position)
{
@ -56,7 +56,7 @@ class SyntaxErrorException extends ParseException
}
/**
* @return SyntaxErrorException
* @return self
*/
public static function nestedNot()
{
@ -64,7 +64,7 @@ class SyntaxErrorException extends ParseException
}
/**
* @return SyntaxErrorException
* @return self
*/
public static function stringAsFunctionArgument()
{

View file

@ -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

View file

@ -61,7 +61,7 @@ class Specificity
/**
* @param Specificity $specificity
*
* @return Specificity
* @return self
*/
public function plus(Specificity $specificity)
{

View file

@ -58,9 +58,9 @@ class Parser implements ParserInterface
*
* @param Token[] $tokens
*
* @throws SyntaxErrorException
*
* @return array
*
* @throws SyntaxErrorException
*/
public static function parseSeries(array $tokens)
{
@ -133,9 +133,9 @@ class Parser implements ParserInterface
*
* @param TokenStream $stream
*
* @throws SyntaxErrorException
*
* @return Node\SelectorNode
*
* @throws SyntaxErrorException
*/
private function parserSelectorNode(TokenStream $stream)
{
@ -173,9 +173,9 @@ class Parser implements ParserInterface
* @param TokenStream $stream
* @param bool $insideNegation
*
* @throws SyntaxErrorException
*
* @return array
*
* @throws SyntaxErrorException
*/
private function parseSimpleSelector(TokenStream $stream, $insideNegation = false)
{
@ -330,9 +330,9 @@ class Parser implements ParserInterface
* @param Node\NodeInterface $selector
* @param TokenStream $stream
*
* @throws SyntaxErrorException
*
* @return Node\AttributeNode
*
* @throws SyntaxErrorException
*/
private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream)
{

View file

@ -118,8 +118,6 @@ class Reader
$this->position += $length;
}
/**
*/
public function moveToEnd()
{
$this->position = $this->length;

View file

@ -61,7 +61,7 @@ class TokenStream
*
* @param Token $token
*
* @return TokenStream
* @return $this
*/
public function push(Token $token)
{
@ -73,7 +73,7 @@ class TokenStream
/**
* Freezes stream.
*
* @return TokenStream
* @return $this
*/
public function freeze()
{
@ -85,9 +85,9 @@ class TokenStream
/**
* Returns next token.
*
* @throws InternalErrorException If there is no more token
*
* @return Token
*
* @throws InternalErrorException If there is no more token
*/
public function getNext()
{
@ -133,9 +133,9 @@ class TokenStream
/**
* Returns nex identifier token.
*
* @throws SyntaxErrorException If next token is not an identifier
*
* @return string The identifier token value
*
* @throws SyntaxErrorException If next token is not an identifier
*/
public function getNextIdentifier()
{
@ -151,9 +151,9 @@ class TokenStream
/**
* Returns nex identifier or star delimiter token.
*
* @throws SyntaxErrorException If next token is not an identifier or a star delimiter
*
* @return null|string The identifier token value or null if star found
*
* @throws SyntaxErrorException If next token is not an identifier or a star delimiter
*/
public function getNextIdentifierOrStar()
{

View file

@ -50,7 +50,7 @@ class NodeExtension extends AbstractExtension
* @param int $flag
* @param bool $on
*
* @return NodeExtension
* @return $this
*/
public function setFlag($flag, $on)
{

View file

@ -70,9 +70,6 @@ class Translator implements TranslatorInterface
*/
private $attributeMatchingTranslators = array();
/**
* Constructor.
*/
public function __construct(ParserInterface $parser = null)
{
$this->mainParser = $parser ?: new Parser();
@ -149,7 +146,7 @@ class Translator implements TranslatorInterface
*
* @param Extension\ExtensionInterface $extension
*
* @return Translator
* @return $this
*/
public function registerExtension(Extension\ExtensionInterface $extension)
{
@ -185,7 +182,7 @@ class Translator implements TranslatorInterface
*
* @param ParserInterface $shortcut
*
* @return Translator
* @return $this
*/
public function registerParserShortcut(ParserInterface $shortcut)
{
@ -268,9 +265,9 @@ class Translator implements TranslatorInterface
* @param string $attribute
* @param string $value
*
* @throws ExpressionErrorException
*
* @return XPathExpr
*
* @throws ExpressionErrorException
*/
public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value)
{

View file

@ -66,7 +66,7 @@ class XPathExpr
/**
* @param $condition
*
* @return XPathExpr
* @return $this
*/
public function addCondition($condition)
{
@ -84,7 +84,7 @@ class XPathExpr
}
/**
* @return XPathExpr
* @return $this
*/
public function addNameTest()
{
@ -97,7 +97,7 @@ class XPathExpr
}
/**
* @return XPathExpr
* @return $this
*/
public function addStarPrefix()
{
@ -112,7 +112,7 @@ class XPathExpr
* @param string $combiner
* @param XPathExpr $expr
*
* @return XPathExpr
* @return $this
*/
public function join($combiner, XPathExpr $expr)
{

View file

@ -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;
}
}

View file

@ -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
-----

View file

@ -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();

View file

@ -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;
}

View file

@ -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'));
}
}
}
}
@ -339,12 +375,14 @@ class ErrorHandler
/**
* Handles errors by filtering then logging them according to the configured bit fields.
*
* @param int $type One of the E_* constants
* @param int $type One of the E_* constants
* @param string $message
* @param string $file
* @param int $line
* @param array $context
* @param array $backtrace
*
* @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
*
@ -361,7 +399,7 @@ class ErrorHandler
return $type && $log;
}
if (PHP_VERSION_ID < 50400 && isset($context['GLOBALS']) && ($this->scopedErrors & $type)) {
if (isset($context['GLOBALS']) && ($this->scopedErrors & $type)) {
$e = $context; // Whatever the signature of the method,
unset($e['GLOBALS'], $context); // $context is always a reference in 5.3
$context = $e;
@ -377,7 +415,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 (($this->scopedErrors & $type) && 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 +433,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;
}
@ -437,6 +519,10 @@ class ErrorHandler
} catch (\Exception $e) {
$this->isRecursive = false;
throw $e;
} catch (\Throwable $e) {
$this->isRecursive = false;
throw $e;
}
}
@ -459,7 +545,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 +572,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 +617,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 +635,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 +764,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) {

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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

View file

@ -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)

View file

@ -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:
```

View file

@ -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));

View file

@ -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');

View file

@ -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();

View file

@ -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

View file

@ -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.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"
}
}
}

View file

@ -17,8 +17,6 @@ class Alias
private $public;
/**
* Constructor.
*
* @param string $id Alias identifier
* @param bool $public If this alias is public
*/

View file

@ -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
*/

View file

@ -34,19 +34,32 @@ class AutowirePass implements CompilerPassInterface
*/
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);
}
}
} 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();
if (isset($e)) {
throw $e;
}
}
/**
@ -92,7 +105,7 @@ 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]);
} else {
try {
@ -107,11 +120,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();
@ -177,22 +190,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 +224,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 +242,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 +260,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 +270,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;
}
}

View file

@ -60,15 +60,19 @@ class CheckCircularReferencesPass implements CompilerPassInterface
$id = $node->getId();
if (empty($this->checkedNodes[$id])) {
$searchKey = array_search($id, $this->currentPath);
$this->currentPath[] = $id;
if (false !== $searchKey) {
throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
// 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));
}
$this->checkOutEdges($node->getOutEdges());
}
$this->checkOutEdges($node->getOutEdges());
$this->checkedNodes[$id] = true;
array_pop($this->currentPath);
}

View file

@ -25,9 +25,6 @@ class Compiler
private $loggingFormatter;
private $serviceReferenceGraph;
/**
* Constructor.
*/
public function __construct()
{
$this->passConfig = new PassConfig();

View file

@ -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));

View file

@ -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>

View file

@ -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()
{

View file

@ -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);
}
/**

View file

@ -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 neeed 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;

View file

@ -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]);
}
}

View file

@ -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;

View file

@ -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()
{

View file

@ -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()
{

View file

@ -29,8 +29,6 @@ class ServiceReferenceGraphNode
private $value;
/**
* Constructor.
*
* @param string $id The node identifier
* @param mixed $value The node value
*/

View file

@ -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;
}

View file

@ -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)
{

View file

@ -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);
}

View file

@ -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.
*/
@ -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,7 +302,7 @@ class Definition
* @param int $index
* @param mixed $argument
*
* @return Definition The current instance
* @return $this
*
* @throws OutOfBoundsException When the replaced argument does not exist
*/
@ -352,7 +350,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 +368,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 +387,7 @@ class Definition
*
* @param string $method The method name to remove
*
* @return Definition The current instance
* @return $this
*/
public function removeMethodCall($method)
{
@ -436,7 +434,7 @@ class Definition
*
* @param array $tags
*
* @return Definition the current instance
* @return $this
*/
public function setTags(array $tags)
{
@ -473,7 +471,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 +497,7 @@ class Definition
*
* @param string $name The tag name
*
* @return Definition
* @return $this
*/
public function clearTag($name)
{
@ -511,7 +509,7 @@ class Definition
/**
* Clears the tags for this definition.
*
* @return Definition The current instance
* @return $this
*/
public function clearTags()
{
@ -525,7 +523,7 @@ class Definition
*
* @param string $file A full pathname to include
*
* @return Definition The current instance
* @return $this
*/
public function setFile($file)
{
@ -549,7 +547,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 +571,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 +611,7 @@ class Definition
*
* @param bool $boolean
*
* @return Definition The current instance
* @return $this
*/
public function setPublic($boolean)
{
@ -637,7 +635,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 +671,7 @@ class Definition
*
* @param bool $lazy
*
* @return Definition The current instance
* @return $this
*/
public function setLazy($lazy)
{
@ -698,7 +696,7 @@ class Definition
*
* @param bool $boolean
*
* @return Definition the current instance
* @return $this
*/
public function setSynthetic($boolean)
{
@ -724,7 +722,7 @@ class Definition
*
* @param bool $boolean
*
* @return Definition the current instance
* @return $this
*/
public function setAbstract($boolean)
{
@ -751,7 +749,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 +800,7 @@ class Definition
*
* @param callable $callable A PHP callable
*
* @return Definition The current instance
* @return $this
*/
public function setConfigurator($callable)
{
@ -826,7 +824,7 @@ class Definition
*
* @param string[] $types
*
* @return Definition The current instance
* @return $this
*/
public function setAutowiringTypes(array $types)
{
@ -852,9 +850,9 @@ class Definition
/**
* Sets autowired.
*
* @param $autowired
* @param bool $autowired
*
* @return Definition The current instance
* @return $this
*/
public function setAutowired($autowired)
{
@ -878,7 +876,7 @@ class Definition
*
* @param string $type
*
* @return Definition The current instance
* @return $this
*/
public function addAutowiringType($type)
{
@ -892,7 +890,7 @@ class Definition
*
* @param string $type
*
* @return Definition The current instance
* @return $this
*/
public function removeAutowiringType($type)
{

View file

@ -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
*/

View file

@ -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)

View file

@ -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) {

View file

@ -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;
}
@ -1123,7 +1144,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 +1309,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)) {

Some files were not shown because too many files have changed in this diff Show more