Merge branch '2.7' into 2.8

* 2.7:
  Permit empty suffix on Windows
  [Console][Table] fixed render when using multiple rowspans.
  add docblocks for Twig url and path function to improve ide completion
  check for circular refs caused by method calls
  [Serializer] fix upper camel case conversion (see #21399)
  [DI] Auto register extension configuration classes as a resource
  [Console] Updated phpdoc on return types
This commit is contained in:
Fabien Potencier 2017-02-16 06:06:24 -08:00
commit e103e1d1db
17 changed files with 118 additions and 52 deletions

View File

@ -40,11 +40,25 @@ class RoutingExtension extends \Twig_Extension
);
}
/**
* @param string $name
* @param array $parameters
* @param bool $relative
*
* @return string
*/
public function getPath($name, $parameters = array(), $relative = false)
{
return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH);
}
/**
* @param string $name
* @param array $parameters
* @param bool $schemeRelative
*
* @return string
*/
public function getUrl($name, $parameters = array(), $schemeRelative = false)
{
return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL);

View File

@ -38,7 +38,7 @@ class QuestionHelper extends Helper
* @param OutputInterface $output An OutputInterface instance
* @param Question $question The question to ask
*
* @return string The user answer
* @return mixed The user answer
*
* @throws RuntimeException If there is no data to read in the input stream
*/
@ -384,7 +384,7 @@ class QuestionHelper extends Helper
* @param OutputInterface $output An Output instance
* @param Question $question A Question instance
*
* @return string The validated response
* @return mixed The validated response
*
* @throws \Exception In case the max number of attempts has been reached and no valid response has been given
*/

View File

@ -440,6 +440,9 @@ class Table
foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
$value = isset($lines[$unmergedRowKey - $line]) ? $lines[$unmergedRowKey - $line] : '';
$unmergedRows[$unmergedRowKey][$column] = new TableCell($value, array('colspan' => $cell->getColspan()));
if ($nbLines === $unmergedRowKey - $line) {
break;
}
}
}
}

View File

@ -298,10 +298,10 @@ TABLE
array(
array(
new TableCell('9971-5-0210-0', array('rowspan' => 3)),
'Divine Comedy',
new TableCell('Divine Comedy', array('rowspan' => 2)),
'Dante Alighieri',
),
array('A Tale of Two Cities', 'Charles Dickens'),
array(),
array("The Lord of \nthe Rings", "J. R. \nR. Tolkien"),
new TableSeparator(),
array('80-902734-1-6', new TableCell("And Then \nThere \nWere None", array('rowspan' => 3)), 'Agatha Christie'),
@ -309,18 +309,18 @@ TABLE
),
'default',
<<<'TABLE'
+---------------+----------------------+-----------------+
| ISBN | Title | Author |
+---------------+----------------------+-----------------+
| 9971-5-0210-0 | Divine Comedy | Dante Alighieri |
| | A Tale of Two Cities | Charles Dickens |
| | The Lord of | J. R. |
| | the Rings | R. Tolkien |
+---------------+----------------------+-----------------+
| 80-902734-1-6 | And Then | Agatha Christie |
| 80-902734-1-7 | There | Test |
| | Were None | |
+---------------+----------------------+-----------------+
+---------------+---------------+-----------------+
| ISBN | Title | Author |
+---------------+---------------+-----------------+
| 9971-5-0210-0 | Divine Comedy | Dante Alighieri |
| | | |
| | The Lord of | J. R. |
| | the Rings | R. Tolkien |
+---------------+---------------+-----------------+
| 80-902734-1-6 | And Then | Agatha Christie |
| 80-902734-1-7 | There | Test |
| | Were None | |
+---------------+---------------+-----------------+
TABLE
),

View File

@ -12,6 +12,7 @@
namespace Symfony\Component\DependencyInjection\Compiler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface;
use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface;
/**
@ -47,6 +48,9 @@ class MergeExtensionConfigurationPass implements CompilerPassInterface
$tmpContainer = new ContainerBuilder($container->getParameterBag());
$tmpContainer->setResourceTracking($container->isTrackingResources());
$tmpContainer->addObjectResource($extension);
if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) {
$tmpContainer->addObjectResource($configuration);
}
foreach ($exprLangProviders as $provider) {
$tmpContainer->addExpressionLanguageProvider($provider);

View File

@ -64,6 +64,7 @@ class PassConfig
new RemoveUnusedDefinitionsPass(),
)),
new CheckExceptionOnInvalidReferenceBehaviorPass(),
new CheckCircularReferencesPass(),
);
}

View File

@ -113,4 +113,30 @@ class IntegrationTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($container->hasDefinition('b'));
$this->assertFalse($container->hasDefinition('c'), 'Service C was not inlined.');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
*/
public function testCircularReferencesCausedByMethodCallsAreDetectedDuringCompilation()
{
$container = new ContainerBuilder();
$container->setResourceTracking(false);
$container
->register('foobar', '\stdClass')
->addArgument(new Reference('foo'))
;
$container
->register('foo', '\stdClass')
->addArgument(new Reference('bar'))
;
$container
->register('foo', '\stdClass')
->addMethodCall('addFoobar', array(new Reference('foobar')))
;
$container->compile();
}
}

View File

@ -11,6 +11,9 @@
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
use Symfony\Component\Config\Definition\ConfigurationInterface;
use Symfony\Component\Config\Resource\FileResource;
use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@ -48,4 +51,32 @@ class MergeExtensionConfigurationPassTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array($provider), $tmpProviders);
}
public function testExtensionConfigurationIsTrackedByDefault()
{
$extension = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Extension\\Extension')->getMock();
$extension->expects($this->once())
->method('getConfiguration')
->will($this->returnValue(new FooConfiguration()));
$extension->expects($this->any())
->method('getAlias')
->will($this->returnValue('foo'));
$container = new ContainerBuilder(new ParameterBag());
$container->registerExtension($extension);
$container->prependExtensionConfig('foo', array('bar' => true));
$pass = new MergeExtensionConfigurationPass();
$pass->process($container);
$this->assertContains(new FileResource(__FILE__), $container->getResources(), '', false, false);
}
}
class FooConfiguration implements ConfigurationInterface
{
public function getConfigTreeBuilder()
{
return new TreeBuilder();
}
}

View File

@ -63,7 +63,6 @@ $container
;
$container
->register('baz', 'Baz')
->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
;
$container
->register('request', 'Request')

View File

@ -37,6 +37,5 @@ digraph sc {
node_method_call1 -> node_foobaz [label="setBar()" style="dashed"];
node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"];
node_inlined -> node_baz [label="setBaz()" style="dashed"];
node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
node_configurator_service -> node_baz [label="setFoo()" style="dashed"];
}

View File

@ -81,11 +81,7 @@ class ProjectServiceContainer extends Container
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \Baz();
$instance->setFoo($this->get('foo_with_inline'));
return $instance;
return $this->services['baz'] = new \Baz();
}
/**

View File

@ -100,11 +100,7 @@ class ProjectServiceContainer extends Container
*/
protected function getBazService()
{
$this->services['baz'] = $instance = new \Baz();
$instance->setFoo($this->get('foo_with_inline'));
return $instance;
return $this->services['baz'] = new \Baz();
}
/**
@ -245,12 +241,11 @@ class ProjectServiceContainer extends Container
protected function getFooWithInlineService()
{
$a = new \Bar();
$this->services['foo_with_inline'] = $instance = new \Foo();
$a->pub = 'pub';
$a->setBaz($this->get('baz'));
$this->services['foo_with_inline'] = $instance = new \Foo();
$instance->setBar($a);
return $instance;

View File

@ -70,11 +70,7 @@
<argument type="service" id="baz"/>
</call>
</service>
<service id="baz" class="Baz">
<call method="setFoo">
<argument type="service" id="foo_with_inline"/>
</call>
</service>
<service id="baz" class="Baz"/>
<service id="request" class="Request" synthetic="true"/>
<service id="configurator_service" class="ConfClass" public="false">
<call method="setFoo">

View File

@ -52,8 +52,6 @@ services:
baz:
class: Baz
calls:
- [setFoo, ['@foo_with_inline']]
request:
class: Request

View File

@ -75,7 +75,7 @@ class ExecutableFinder
$suffixes = array('');
if ('\\' === DIRECTORY_SEPARATOR) {
$pathExt = getenv('PATHEXT');
$suffixes = $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes;
$suffixes = array_merge($suffixes, $pathExt ? explode(PATH_SEPARATOR, $pathExt) : $this->suffixes);
}
foreach ($suffixes as $suffix) {
foreach ($dirs as $dir) {

View File

@ -44,14 +44,15 @@ class CamelCaseToSnakeCaseNameConverter implements NameConverterInterface
public function normalize($propertyName)
{
if (null === $this->attributes || in_array($propertyName, $this->attributes)) {
$lcPropertyName = lcfirst($propertyName);
$snakeCasedName = '';
$len = strlen($propertyName);
$len = strlen($lcPropertyName);
for ($i = 0; $i < $len; ++$i) {
if (ctype_upper($propertyName[$i])) {
$snakeCasedName .= '_'.strtolower($propertyName[$i]);
if (ctype_upper($lcPropertyName[$i])) {
$snakeCasedName .= '_'.strtolower($lcPropertyName[$i]);
} else {
$snakeCasedName .= strtolower($propertyName[$i]);
$snakeCasedName .= strtolower($lcPropertyName[$i]);
}
}

View File

@ -27,27 +27,30 @@ class CamelCaseToSnakeCaseNameConverterTest extends \PHPUnit_Framework_TestCase
/**
* @dataProvider attributeProvider
*/
public function testNormalize($underscored, $lowerCamelCased)
public function testNormalize($underscored, $camelCased, $useLowerCamelCase)
{
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
$this->assertEquals($nameConverter->normalize($lowerCamelCased), $underscored);
$nameConverter = new CamelCaseToSnakeCaseNameConverter(null, $useLowerCamelCase);
$this->assertEquals($nameConverter->normalize($camelCased), $underscored);
}
/**
* @dataProvider attributeProvider
*/
public function testDenormalize($underscored, $lowerCamelCased)
public function testDenormalize($underscored, $camelCased, $useLowerCamelCase)
{
$nameConverter = new CamelCaseToSnakeCaseNameConverter();
$this->assertEquals($nameConverter->denormalize($underscored), $lowerCamelCased);
$nameConverter = new CamelCaseToSnakeCaseNameConverter(null, $useLowerCamelCase);
$this->assertEquals($nameConverter->denormalize($underscored), $camelCased);
}
public function attributeProvider()
{
return array(
array('coop_tilleuls', 'coopTilleuls'),
array('_kevin_dunglas', '_kevinDunglas'),
array('this_is_a_test', 'thisIsATest'),
array('coop_tilleuls', 'coopTilleuls', true),
array('_kevin_dunglas', '_kevinDunglas', true),
array('this_is_a_test', 'thisIsATest', true),
array('coop_tilleuls', 'CoopTilleuls', false),
array('_kevin_dunglas', '_kevinDunglas', false),
array('this_is_a_test', 'ThisIsATest', false),
);
}
}