8000 Merge branch '2.8' into 3.2 · symfony/symfony@ccbbff2 · GitHub
[go: up one dir, main page]

Skip to content

Commit ccbbff2

Browse files
Merge branch '2.8' into 3.2
* 2.8: [DI] Autowiring and factories are incompatible with each others [DI] Don't use auto-registered services to populate type-candidates Lighten tests output by removing composer suggestions support nullable array or collection Complete the injection of the expression in all syntax errors CS: Remove invisible chars Disable resource tracking if the config component is missing [EventDispatcher] Remove unneded count() Fix tests expecting a valid date Avoid forcing to define the choices_as_values option when using choice_loader add expression text to SyntaxError [Console] Fix table cell styling [Console] Revised exception rendering [WebProfilerBundle] Normalize whitespace in exceptions passed in headers Disable color support detection for tests [Form] Improve the exceptions when trying to get the data in a PRE_SET_DATA listener and the data has not already been set
2 parents 924337f + 6b862e8 commit ccbbff2

30 files changed

+297
-90
lines changed

.travis.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ install:
8686
- export COMPOSER_ROOT_VERSION=$SYMFONY_VERSION.x-dev
8787
- if [[ ! $skip && $deps ]]; then export SYMFONY_DEPRECATIONS_HELPER=weak; fi
8888
- if [[ ! $skip && $deps ]]; then mv composer.json.phpunit composer.json; fi
89-
- if [[ ! $skip ]]; then composer update; fi
89+
- if [[ ! $skip ]]; then composer update --no-suggest; fi
9090
- if [[ ! $skip ]]; then ./phpunit install; fi
9191
- if [[ ! $skip && ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi
9292

@@ -97,8 +97,8 @@ script:
9797
- if [[ ! $deps && ! $PHP = hhvm* ]]; then echo -e "\\nRunning tests requiring tty"; $PHPUNIT --group tty; fi
9898
- if [[ ! $deps && $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data; fi
9999
- if [[ ! $deps && $PHP = ${MIN_PHP%.*} ]]; then echo -e "1\\n0" | xargs -I{} sh -c 'echo "\\nPHP --enable-sigchild enhanced={}" && ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/'; fi
100-
- if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY"$REPORT"; fi
101-
- if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'"$REPORT"; fi
100+
- if [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --no-suggest --ansi; $PHPUNIT --exclude-group tty,benchmark,intl-data'$LEGACY"$REPORT"; fi
101+
- if [[ $deps = low ]]; then echo "$COMPONENTS" | parallel --gnu -j10% 'cd {}; composer update --no-progress --no-suggest --ansi --prefer-lowest --prefer-stable; $PHPUNIT --exclude-group tty,benchmark,intl-data'"$REPORT"; fi
102102
# Test the PhpUnit bridge using the original phpunit script
103103
- if [[ $deps = low ]]; then (cd src/Symfony/Bridge/PhpUnit && wget https://phar.phpunit.de/phpunit-4.8.phar); fi
104104
- if [[ $deps = low ]]; then (cd src/Symfony/Bridge/PhpUnit && phpenv global 5.3 && php --version && composer update && php phpunit-4.8.phar); fi

appveyor.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ install:
5151
- copy /Y .composer\* %APPDATA%\Composer\
5252
- php .github/build-packages.php "HEAD^" src\Symfony\Bridge\PhpUnit
5353
- IF %APPVEYOR_REPO_BRANCH%==master (SET COMPOSER_ROOT_VERSION=dev-master) ELSE (SET COMPOSER_ROOT_VERSION=%APPVEYOR_REPO_BRANCH%.x-dev)
54-
- php composer.phar update --no-progress --ansi
54+
- php composer.phar update --no-progress --no-suggest --ansi
5555
- php phpunit install
5656

5757
test_script:

src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public function onKernelResponse(FilterResponseEvent $event)
7171
$this->urlGenerator->generate('_profiler', array('token' => $response->headers->get('X-Debug-Token')), UrlGeneratorInterface::ABSOLUTE_URL)
7272
);
7373
} catch (\Exception $e) {
74-
$response->headers->set('X-Debug-Error', get_class($e).': '.$e->getMessage());
74+
$response->headers->set('X-Debug-Error', get_class($e).': '.preg_replace('/\s+/', ' ', $e->getMessage()));
7575
}
7676
}
7777

src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,27 @@ public function testThrowingUrlGenerator()
246246
$this->assertEquals('Exception: foo', $response->headers->get('X-Debug-Error'));
247247
}
248248

249+
public function testThrowingErrorCleanup()
250+
{
251+
$response = new Response();
252+
$response->headers->set('X-Debug-Token', 'xxxxxxxx');
253+
254+
$urlGenerator = $this->getUrlGeneratorMock();
255+
$urlGenerator
256+
->expects($this->once())
257+
->method('generate')
258+
->with('_profiler', array('token' => 'xxxxxxxx'))
259+
->will($this->throwException(new \Exception("This\nmultiline\r\ntabbed text should\tcome out\r on\n \ta single plain\r\nline")))
260+
;
261+
262+
$event = new FilterResponseEvent($this->getKernelMock(), $this->getRequestMock(), HttpKernelInterface::MASTER_REQUEST, $response);
263+
264+
$listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, 'bottom', $urlGenerator);
265+
$listener->onKernelResponse($event);
266+
267+
$this->assertEquals('Exception: This multiline tabbed text should come out on a single plain line', $response->headers->get('X-Debug-Error'));
268+
}
269+
249270
protected function getRequestMock($isXmlHttpRequest = false, $requestFormat = 'html', $hasSession = true)
250271
{
251272
$request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->setMethods(array('getSession', 'isXmlHttpRequest', 'getRequestFormat'))->disableOriginalConstructor()->getMock();

src/Symfony/Component/Console/Application.php

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -635,28 +635,27 @@ public function renderException(\Exception $e, OutputInterface $output)
635635
if (defined('HHVM_VERSION') && $width > 1 << 31) {
636636
$width = 1 << 31;
637637
}
638-
$formatter = $output->getFormatter();
639638
$lines = array();
640-
foreach (preg_split('/\r?\n/', OutputFormatter::escape($e->getMessage())) as $line) {
639+
foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) {
641640
foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
642641
// pre-format lines to get the right string length
643-
$lineLength = $this->stringWidth(preg_replace('/\[[^m]*m/', '', $formatter->format($line))) + 4;
642+
$lineLength = $this->stringWidth($line) + 4;
644643
$lines[] = array($line, $lineLength);
645644

646645
$len = max($lineLength, $len);
647646
}
648647
}
649648

650649
$messages = array();
651-
$messages[] = $emptyLine = $formatter->format(sprintf('<error>%s</error>', str_repeat(' ', $len)));
652-
$messages[] = $formatter->format(sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title)))));
650+
$messages[] = $emptyLine = sprintf('<error>%s</error>', str_repeat(' ', $len));
651+
$messages[] = sprintf('<error>%s%s</error>', $title, str_repeat(' ', max(0, $len - $this->stringWidth($title))));
653652
foreach ($lines as $line) {
654-
$messages[] = $formatter->format(sprintf('<error> %s %s</error>', $line[0], str_repeat(' ', $len - $line[1])));
653+
$messages[] = sprintf('<error> %s %s</error>', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1]));
655654
}
656655
$messages[] = $emptyLine;
657656
$messages[] = '';
658657

659-
$output->writeln($messages, OutputInterface::OUTPUT_RAW | OutputInterface::VERBOSITY_QUIET);
658+
$output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
660659

661660
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
662661
$output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);

src/Symfony/Component/Console/Helper/Helper.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,11 @@ public static function formatMemory($memory)
105105
}
106106

107107
public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, $string)
108+
{
109+
return self::strlen(self::removeDecoration($formatter, $string));
110+
}
111+
112+
public static function removeDecoration(OutputFormatterInterface $formatter, $string)
108113
{
109114
$isDecorated = $formatter->isDecorated();
110115
$formatter->setDecorated(false);
@@ -114,6 +119,6 @@ public static function strlenWithoutDecoration(OutputFormatterInterface $formatt
114119
$string = preg_replace("/\033\[[^m]*m/", '', $string);
115120
$formatter->setDecorated($isDecorated);
116121

117-
return self::strlen($string);
122+
return $string;
118123
}
119124
}

src/Symfony/Component/Console/Helper/Table.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ private function buildTableRows($rows)
426426
if (!strstr($cell, "\n")) {
427427
continue;
428428
}
429-
$lines = explode("\n", $cell);
429+
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
430430
foreach ($lines as $lineKey => $line) {
431431
if ($cell instanceof TableCell) {
432432
$line = new TableCell($line, array('colspan' => $cell->getColspan()));
@@ -467,7 +467,7 @@ private function fillNextRows($rows, $line)
467467
$nbLines = $cell->getRowspan() - 1;
468468
$lines = array($cell);
469469
if (strstr($cell, "\n")) {
470-
$lines = explode("\n", $cell);
470+
$lines = explode("\n", str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
471471
$nbLines = count($lines) > $nbLines ? substr_count($cell, "\n") : $nbLines;
472472

473473
$rows[$line][$column] = new TableCell($lines[0], array('colspan' => $cell->getColspan()));
@@ -602,9 +602,10 @@ private function calculateColumnsWidth($rows)
602602

603603
foreach ($row as $i => $cell) {
604604
if ($cell instanceof TableCell) {
605-
$textLength = Helper::strlenWithoutDecoration($this->output->getFormatter(), $cell);
605+
$textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
606+
$textLength = Helper::strlen($textContent);
606607
if ($textLength > 0) {
607-
$contentColumns = str_split($cell, ceil($textLength / $cell->getColspan()));
608+
$contentColumns = str_split($textContent, ceil($textLength / $cell->getColspan()));
608609
foreach ($contentColumns as $position => $content) {
609610
$row[$i + $position] = $content;
610611
}

src/Symfony/Component/Console/Tester/CommandTester.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ public function execute(array $input, array $options = array())
7676
}
7777

7878
$this->output = new StreamOutput(fopen('php://memory', 'w', false));
79-
if (isset($options['decorated'])) {
80-
$this->output->setDecorated($options['decorated']);
81-
}
79+
$this->output->setDecorated(isset($options['decorated']) ? $options['decorated'] : false);
8280
if (isset($options['verbosity'])) {
8381
$this->output->setVerbosity($options['verbosity']);
8482
}

src/Symfony/Component/Console/Tests/ApplicationTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,22 @@ public function testRenderExceptionWithDoubleWidthCharacters()
586586
putenv('COLUMNS=120');
587587
}
588588

589+
public function testRenderExceptionEscapesLines()
590+
{
591+
$application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock();
592+
$application->setAutoExit(false);
593+
$application->expects($this->any())
594+
->method('getTerminalWidth')
595+
->will($this->returnValue(22));
596+
$application->register('foo')->setCode(function () {
597+
throw new \Exception('dont break here <info>!</info>');
598+
});
599+
$tester = new ApplicationTester($application);
600+
601+
$tester->run(array('command' => 'foo'), array('decorated' => false));
602+
$this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting');
603+
}
604+
589605
public function testRun()
590606
{
591607
$application = new Application();
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
3+
[Exception]
4+
dont break here <
5+
info>!</info>
6+
7+
8+
foo
9+

src/Symfony/Component/Console/Tests/Helper/TableTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,35 @@ public function renderProvider()
511511
| Dante Alighieri | J. R. R. Tolkien | J. R. R |
512512
+-----------------+------------------+---------+
513513
514+
TABLE
515+
,
516+
true,
517+
),
518+
'Row with formatted cells containing a newline' => array(
519+
array(),
520+
array(
521+
array(
522+
new TableCell('<error>Dont break'."\n".'here</error>', array('colspan' => 2)),
523+
),
524+
new TableSeparator(),
525+
array(
526+
'foo',
527+
new TableCell('<error>Dont break'."\n".'here</error>', array('rowspan' => 2)),
528+
),
529+
array(
530+
'bar',
531+
),
532+
),
533+
'default',
534+
<<<'TABLE'
535+
+-------+------------+
536+
| Dont break |
537+
| here |
538+
+-------+------------+
539+
| foo | Dont break |
540+
| bar | here |
541+
+-------+------------+
542+
514543
TABLE
515544
,
516545
true,

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class AutowirePass implements CompilerPassInterface
2929
private $definedTypes = array();
3030
private $types;
3131
private $ambiguousServiceTypes = array();
32-
private $usedTypes = array();
32+
private $autowired = array();
3333

3434
/**
3535
* {@inheritdoc}
@@ -46,25 +46,15 @@ public function process(ContainerBuilder $container)
4646
$this->completeDefinition($id, $definition);
4747
}
4848
}
49-
50-
foreach ($this->usedTypes as $type => $id) {
51-
if (isset($this->usedTypes[$type]) && isset($this->ambiguousServiceTypes[$type])) {
52-
$classOrInterface = class_exists($type) ? 'class' : 'interface';
53-
$matchingServices = implode(', ', $this->ambiguousServiceTypes[$type]);
54-
55-
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices));
56-
}
57-
}
5849
} finally {
5950
spl_autoload_unregister($throwingAutoloader);
6051

6152
// Free memory and remove circular reference to container
62-
$this->container = null;
6353
$this->reflectionClasses = array();
6454
$this->definedTypes = array();
6555
$this->types = null;
6656
$this->ambiguousServiceTypes = array();
67-
$this->usedTypes = array();
57+
$this->autowired = array();
6858
}
6959
}
7060

@@ -100,6 +90,10 @@ public static function createResourceForClass(\ReflectionClass $reflectionClass)
10090
*/
10191
private function completeDefinition($id, Definition $definition)
10292
{
93+
if ($definition->getFactory()) {
94+
throw new RuntimeException(sprintf('Service "%s" can use either autowiring or a factory, not both.', $id));
95+
}
96+
10397
if (!$reflectionClass = $this->getReflectionClass($id, $definition)) {
10498
return;
10599
}
@@ -111,47 +105,56 @@ private function completeDefinition($id, Definition $definition)
111105
if (!$constructor = $reflectionClass->getConstructor()) {
112106
return;
113107
}
108+
$parameters = $constructor->getParameters();
109+
if (method_exists('ReflectionMethod', 'isVariadic') && $constructor->isVariadic()) {
110+
array_pop($parameters);
111+
}
114112

115113
$arguments = $definition->getArguments();
116-
foreach ($constructor->getParameters() as $index => $parameter) {
114+
foreach ($parameters as $index => $parameter) {
117115
if (array_key_exists($index, $arguments) && '' !== $arguments[$index]) {
118116
continue;
119117
}
120118

121119
try {
122120
if (!$typeHint = $parameter->getClass()) {
121+
if (isset($arguments[$index])) {
122+
continue;
123+
}
124+
123125
// no default value? Then fail
124126
if (!$parameter->isOptional()) {
125127
throw new RuntimeException(sprintf('Unable to autowire argument index %d ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
126128
}
127129

128-
if (!array_key_exists($index, $arguments)) {
129-
// specifically pass the default value
130-
$arguments[$index] = $parameter->getDefaultValue();
131-
}
130+
// specifically pass the default value
131+
$arguments[$index] = $parameter->getDefaultValue();
132132

133133
continue;
134134
}
135135

136+
if (isset($this->autowired[$typeHint->name])) {
137+
return $this->autowired[$typeHint->name] ? new Reference($this->autowired[$typeHint->name]) : null;
138+
}
139+
136140
if (null === $this->types) {
137141
$this->populateAvailableTypes();
138142
}
139143

140144
if (isset($this->types[$typeHint->name])) {
141145
$value = new Reference($this->types[$typeHint->name]);
142-
$this->usedTypes[$typeHint->name] = $id;
143146
} else {
144147
try {
145148
$value = $this->createAutowiredDefinition($typeHint, $id);
146-
$this->usedTypes[$typeHint->name] = $id;
147149
} catch (RuntimeException $e) {
148-
if ($parameter->allowsNull()) {
149-
$value = null;
150-
} elseif ($parameter->isDefaultValueAvailable()) {
150+
if ($parameter->isDefaultValueAvailable()) {
151151
$value = $parameter->getDefaultValue();
152+
} elseif ($parameter->allowsNull()) {
153+
$value = null;
152154
} else {
153155
throw $e;
154156
}
157+
$this->autowired[$typeHint->name] = false;
155158
}
156159
}
157160
} catch (\ReflectionException $e) {
@@ -167,6 +170,16 @@ private function completeDefinition($id, Definition $definition)
167170
$arguments[$index] = $value;
168171
}
169172

173+
if ($parameters && !isset($arguments[++$index])) {
174+
while (0 <= --$index) {
175+
$parameter = $parameters[$index];
176+
if (!$parameter->isDefaultValueAvailable() || $parameter->getDefaultValue() !== $arguments[$index]) {
177+
break;
178+
}
179+
unset($arguments[$index]);
180+
}
181+
}
182+
170183
// it's possible index 1 was set, then index 0, then 2, etc
171184
// make sure that we re-order so they're injected as expected
172185
ksort($arguments);
@@ -275,13 +288,11 @@ private function createAutowiredDefinition(\ReflectionClass $typeHint, $id)
275288
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));
276289
}
277290

278-
$argumentId = sprintf('autowired.%s', $typeHint->name);
291+
$this->autowired[$typeHint->name] = $argumentId = sprintf('autowired.%s', $typeHint->name);
279292

280293
$argumentDefinition = $this->container->register($argumentId, $typeHint->name);
281294
$argumentDefinition->setPublic(false);
282295

283-
$this->populateAvailableType($argumentId, $argumentDefinition);
284-
285296
try {
286297
$this->completeDefinition($argumentId, $argumentDefinition);
287298
} catch (RuntimeException $e) {

0 commit comments

Comments
 (0)
0