Merge branch '3.3' into 3.4

* 3.3:
  [DI] prepare for signature change in 4.0
  [DI] Add missing deprecation on Extension::getClassesToCompile
  [Routing] remove an unused routing fixture
  [Yaml] fix multiline block handling
  [WebProfilerBundle] Fix sub-requests display in time profiler panel
  [FrameworkBundle] Handle project dir in cache:clear command
  [WebServerBundle] Mark ServerCommand as internal
  [DI] Fix autowire error for inlined services
  Close PHP code in phpt file
  [Profiler][VarDumper] Fix searchbar css when in toolbar
  Prevent auto-registration of UserPasswordEncoderCommand
  [Process] Fixed incorrectly escaping arguments on Windows when inheritEnvironmentVariables is set to false
  avoid double blanks while rendering form attributes
  use getProjectDir() when possible
  [PhpUnitBridge] add a changelog file
  [FrameworkBundle][Validator] Deprecate passing validator instances/aliases over using the service locator
This commit is contained in:
Nicolas Grekas 2017-05-24 13:37:21 +02:00
commit e2689d42fc
34 changed files with 292 additions and 66 deletions

View File

@ -244,6 +244,10 @@ FrameworkBundle
class has been deprecated and will be removed in 4.0. Use the class has been deprecated and will be removed in 4.0. Use the
`Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` class instead. `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` class instead.
* Passing an array of validators or validator aliases as the second argument of
`ConstraintValidatorFactory::__construct()` is deprecated since 3.3 and will
be removed in 4.0. Use the service locator instead.
HttpFoundation HttpFoundation
-------------- --------------
@ -262,7 +266,7 @@ HttpKernel
* Deprecated the `Kernel::getRootDir()` method. Use the new `Kernel::getProjectDir()` * Deprecated the `Kernel::getRootDir()` method. Use the new `Kernel::getProjectDir()`
method instead. method instead.
* The `Extension::addClassesToCompile()` method has been deprecated and will be removed in 4.0. * The `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` methods have been deprecated and will be removed in 4.0.
* The `Psr6CacheClearer::addPool()` method has been deprecated. Pass an array * The `Psr6CacheClearer::addPool()` method has been deprecated. Pass an array
of pools indexed by name to the constructor instead. of pools indexed by name to the constructor instead.

View File

@ -301,6 +301,10 @@ FrameworkBundle
* Extending `ConstraintValidatorFactory` is not supported anymore. * Extending `ConstraintValidatorFactory` is not supported anymore.
* Passing an array of validators or validator aliases as the second argument of
`ConstraintValidatorFactory::__construct()` has been removed.
Use the service locator instead.
* Class parameters related to routing have been removed * Class parameters related to routing have been removed
* router.options.generator_class * router.options.generator_class
* router.options.generator_base_class * router.options.generator_base_class
@ -374,7 +378,7 @@ HttpKernel
* Removed the `Kernel::getRootDir()` method. Use the `Kernel::getProjectDir()` * Removed the `Kernel::getRootDir()` method. Use the `Kernel::getProjectDir()`
method instead. method instead.
* The `Extension::addClassesToCompile()` method has been removed. * The `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` methods have been removed.
* Possibility to pass non-scalar values as URI attributes to the ESI and SSI * Possibility to pass non-scalar values as URI attributes to the ESI and SSI
renderers has been removed. The inline fragment renderer should be used with renderers has been removed. The inline fragment renderer should be used with

View File

@ -8,3 +8,9 @@ CHANGELOG
deprecated, use the `@group legacy` notation instead deprecated, use the `@group legacy` notation instead
* using the `Legacy` prefix in class names to mark a test as legacy is deprecated, * using the `Legacy` prefix in class names to mark a test as legacy is deprecated,
use the `@group legacy` notation instead use the `@group legacy` notation instead
3.1.0
-----
* passing a numerically indexed array to the constructor of the `SymfonyTestsListenerTrait`
is deprecated, pass an array of namespaces indexed by the mocked feature instead

View File

@ -17,6 +17,8 @@ require PHPUNIT_COMPOSER_INSTALL;
require_once __DIR__.'/../../bootstrap.php'; require_once __DIR__.'/../../bootstrap.php';
require __DIR__.'/fake_vendor/autoload.php'; require __DIR__.'/fake_vendor/autoload.php';
require __DIR__.'/fake_vendor/acme/lib/deprecation_riddled.php'; require __DIR__.'/fake_vendor/acme/lib/deprecation_riddled.php';
?>
--EXPECTF-- --EXPECTF--
Unsilenced deprecation notices (2) Unsilenced deprecation notices (2)

View File

@ -79,7 +79,7 @@
{{- block('choice_widget_options') -}} {{- block('choice_widget_options') -}}
</optgroup> </optgroup>
{%- else -%} {%- else -%}
<option value="{{ choice.value }}"{% if choice.attr %} {% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option> <option value="{{ choice.value }}"{% if choice.attr %}{% with { attr: choice.attr } %}{{ block('attributes') }}{% endwith %}{% endif %}{% if choice is selectedchoice(value) %} selected="selected"{% endif %}>{{ choice_translation_domain is same as(false) ? choice.label : choice.label|trans({}, choice_translation_domain) }}</option>
{%- endif -%} {%- endif -%}
{% endfor %} {% endfor %}
{%- endblock choice_widget_options -%} {%- endblock choice_widget_options -%}
@ -259,7 +259,7 @@
{% set label = name|humanize %} {% set label = name|humanize %}
{%- endif -%} {%- endif -%}
{%- endif -%} {%- endif -%}
<label{% if label_attr %} {% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}</label> <label{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}</label>
{%- endif -%} {%- endif -%}
{%- endblock form_label -%} {%- endblock form_label -%}

View File

@ -49,6 +49,7 @@ CHANGELOG
`Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead
* Deprecated `ValidateWorkflowsPass`, use * Deprecated `ValidateWorkflowsPass`, use
`Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead
* Deprecated `ConstraintValidatorFactory::__construct()` second argument.
3.2.0 3.2.0
----- -----

View File

@ -46,7 +46,6 @@ class AboutCommand extends ContainerAwareCommand
/** @var $kernel KernelInterface */ /** @var $kernel KernelInterface */
$kernel = $this->getContainer()->get('kernel'); $kernel = $this->getContainer()->get('kernel');
$baseDir = realpath($kernel->getRootDir().DIRECTORY_SEPARATOR.'..');
$io->table(array(), array( $io->table(array(), array(
array('<info>Symfony</>'), array('<info>Symfony</>'),
@ -62,9 +61,9 @@ class AboutCommand extends ContainerAwareCommand
array('Environment', $kernel->getEnvironment()), array('Environment', $kernel->getEnvironment()),
array('Debug', $kernel->isDebug() ? 'true' : 'false'), array('Debug', $kernel->isDebug() ? 'true' : 'false'),
array('Charset', $kernel->getCharset()), array('Charset', $kernel->getCharset()),
array('Root directory', self::formatPath($kernel->getRootDir(), $baseDir)), array('Root directory', self::formatPath($kernel->getRootDir(), $kernel->getProjectDir())),
array('Cache directory', self::formatPath($kernel->getCacheDir(), $baseDir).' (<comment>'.self::formatFileSize($kernel->getCacheDir()).'</>)'), array('Cache directory', self::formatPath($kernel->getCacheDir(), $kernel->getProjectDir()).' (<comment>'.self::formatFileSize($kernel->getCacheDir()).'</>)'),
array('Log directory', self::formatPath($kernel->getLogDir(), $baseDir).' (<comment>'.self::formatFileSize($kernel->getLogDir()).'</>)'), array('Log directory', self::formatPath($kernel->getLogDir(), $kernel->getProjectDir()).' (<comment>'.self::formatFileSize($kernel->getLogDir()).'</>)'),
new TableSeparator(), new TableSeparator(),
array('<info>PHP</>'), array('<info>PHP</>'),
new TableSeparator(), new TableSeparator(),

View File

@ -82,9 +82,7 @@ EOT
$targetArg = rtrim($input->getArgument('target'), '/'); $targetArg = rtrim($input->getArgument('target'), '/');
if (!is_dir($targetArg)) { if (!is_dir($targetArg)) {
$appRoot = $this->getContainer()->getParameter('kernel.root_dir').'/..'; $targetArg = $this->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg;
$targetArg = $appRoot.'/'.$targetArg;
if (!is_dir($targetArg)) { if (!is_dir($targetArg)) {
throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));

View File

@ -201,6 +201,7 @@ EOF
{ {
$cacheDir = var_export($warmupDir, true); $cacheDir = var_export($warmupDir, true);
$rootDir = var_export(realpath($parent->getRootDir()), true); $rootDir = var_export(realpath($parent->getRootDir()), true);
$projectDir = var_export(realpath($parent->getProjectDir()), true);
$logDir = var_export(realpath($parent->getLogDir()), true); $logDir = var_export(realpath($parent->getLogDir()), true);
// the temp kernel class name must have the same length than the real one // the temp kernel class name must have the same length than the real one
// to avoid the many problems in serialized resources files // to avoid the many problems in serialized resources files
@ -224,6 +225,11 @@ namespace $namespace
return $rootDir; return $rootDir;
} }
public function getProjectDir()
{
return $projectDir;
}
public function getLogDir() public function getLogDir()
{ {
return $logDir; return $logDir;

View File

@ -14,7 +14,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Validator;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory; use Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory;
use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\Constraints\Blank as BlankConstraint; use Symfony\Component\Validator\Constraints\Blank as BlankConstraint;
use Symfony\Component\Validator\ConstraintValidator;
class ConstraintValidatorFactoryTest extends TestCase class ConstraintValidatorFactoryTest extends TestCase
{ {
@ -41,6 +44,38 @@ class ConstraintValidatorFactoryTest extends TestCase
} }
public function testGetInstanceReturnsService() public function testGetInstanceReturnsService()
{
$service = 'validator_constraint_service';
$validator = $this->getMockForAbstractClass(ConstraintValidator::class);
// mock ContainerBuilder b/c it implements TaggedContainerInterface
$container = $this->getMockBuilder(ContainerBuilder::class)->setMethods(array('get', 'has'))->getMock();
$container
->expects($this->once())
->method('get')
->with($service)
->willReturn($validator);
$container
->expects($this->once())
->method('has')
->with($service)
->willReturn(true);
$constraint = $this->getMockBuilder(Constraint::class)->getMock();
$constraint
->expects($this->once())
->method('validatedBy')
->will($this->returnValue($service));
$factory = new ConstraintValidatorFactory($container);
$this->assertSame($validator, $factory->getInstance($constraint));
}
/**
* @group legacy
* @expectedDeprecation Passing an array of validators or validator aliases as the second argument of "Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory::__construct" is deprecated since 3.3 and will be removed in 4.0. Use the service locator instead.
*/
public function testGetInstanceReturnsServiceWithAlias()
{ {
$service = 'validator_constraint_service'; $service = 'validator_constraint_service';
$alias = 'validator_constraint_alias'; $alias = 'validator_constraint_alias';

View File

@ -45,15 +45,16 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
protected $container; protected $container;
protected $validators; protected $validators;
/** public function __construct(ContainerInterface $container, array $validators = null)
* Constructor.
*
* @param ContainerInterface $container The service container
* @param array $validators An array of validators
*/
public function __construct(ContainerInterface $container, array $validators = array())
{ {
$this->container = $container; $this->container = $container;
if (null !== $validators) {
@trigger_error(sprintf('Passing an array of validators or validator aliases as the second argument of "%s" is deprecated since 3.3 and will be removed in 4.0. Use the service locator instead.', __METHOD__), E_USER_DEPRECATED);
} else {
$validators = array();
}
$this->validators = $validators; $this->validators = $validators;
} }
@ -82,6 +83,7 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface
$this->validators[$name] = new $name(); $this->validators[$name] = new $name();
} }
} elseif (is_string($this->validators[$name])) { } elseif (is_string($this->validators[$name])) {
// To be removed in 4.0
$this->validators[$name] = $this->container->get($this->validators[$name]); $this->validators[$name] = $this->container->get($this->validators[$name]);
} }

View File

@ -98,11 +98,11 @@ class SecurityExtension extends Extension
if ($config['encoders']) { if ($config['encoders']) {
$this->createEncoders($config['encoders'], $container); $this->createEncoders($config['encoders'], $container);
}
if (class_exists(Application::class)) { if (class_exists(Application::class)) {
$loader->load('console.xml'); $loader->load('console.xml');
$container->getDefinition('security.console.user_password_encoder_command')->replaceArgument(1, array_keys($config['encoders'])); $container->getDefinition('security.console.user_password_encoder_command')->replaceArgument(1, array_keys($config['encoders']));
}
} }
// load ACL // load ACL

View File

@ -345,6 +345,11 @@ abstract class CompleteConfigurationTest extends TestCase
$this->assertEquals('security.user_checker', $this->getContainer('container1')->getAlias('security.user_checker.secure')); $this->assertEquals('security.user_checker', $this->getContainer('container1')->getAlias('security.user_checker.secure'));
} }
public function testUserPasswordEncoderCommandIsRegistered()
{
$this->assertTrue($this->getContainer('remember_me_options')->has('security.console.user_password_encoder_command'));
}
protected function getContainer($file) protected function getContainer($file)
{ {
$file = $file.'.'.$this->getFileExtension(); $file = $file.'.'.$this->getFileExtension();

View File

@ -107,8 +107,8 @@
</form> </form>
{% if profile.parent %} {% if profile.parent %}
<h3> <h3 class="dump-inline">
Sub-Request {{ profile.getcollector('request').requestattributes.get('_controller') }} Sub-Request {{ profiler_dump(profile.getcollector('request').requestattributes.get('_controller')) }}
<small> <small>
{{ collector.events.__section__.duration }} ms {{ collector.events.__section__.duration }} ms
<a class="newline" href="{{ path('_profiler', { token: profile.parent.token, panel: 'time' }) }}">Return to parent request</a> <a class="newline" href="{{ path('_profiler', { token: profile.parent.token, panel: 'time' }) }}">Return to parent request</a>

View File

@ -382,6 +382,9 @@
.sf-toolbar-block-dump pre.sf-dump:last-child { .sf-toolbar-block-dump pre.sf-dump:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
.sf-toolbar-block-dump pre.sf-dump .sf-dump-search-wrapper {
margin-bottom: 5px;
}
.sf-toolbar-block-dump pre.sf-dump span.sf-dump-search-count { .sf-toolbar-block-dump pre.sf-dump span.sf-dump-search-count {
color: #333; color: #333;
font-size: 12px; font-size: 12px;

View File

@ -17,6 +17,8 @@ use Symfony\Component\Console\Command\Command;
* Base methods for commands related to a local web server. * Base methods for commands related to a local web server.
* *
* @author Christian Flothmann <christian.flothmann@xabbuh.de> * @author Christian Flothmann <christian.flothmann@xabbuh.de>
*
* @internal
*/ */
abstract class ServerCommand extends Command abstract class ServerCommand extends Command
{ {

View File

@ -8,13 +8,13 @@
<defaults public="false" /> <defaults public="false" />
<service id="web_server.command.server_run" class="Symfony\Bundle\WebServerBundle\Command\ServerRunCommand"> <service id="web_server.command.server_run" class="Symfony\Bundle\WebServerBundle\Command\ServerRunCommand">
<argument>%kernel.root_dir%/../web</argument> <argument>%kernel.project_dir%/web</argument>
<argument>%kernel.environment%</argument> <argument>%kernel.environment%</argument>
<tag name="console.command" /> <tag name="console.command" />
</service> </service>
<service id="web_server.command.server_start" class="Symfony\Bundle\WebServerBundle\Command\ServerStartCommand"> <service id="web_server.command.server_start" class="Symfony\Bundle\WebServerBundle\Command\ServerStartCommand">
<argument>%kernel.root_dir%/../web</argument> <argument>%kernel.project_dir%/web</argument>
<argument>%kernel.environment%</argument> <argument>%kernel.environment%</argument>
<tag name="console.command" /> <tag name="console.command" />
</service> </service>

View File

@ -18,7 +18,7 @@
"require": { "require": {
"php": ">=5.5.9", "php": ">=5.5.9",
"symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0.0", "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0.0",
"symfony/http-kernel": "~2.8|~3.0|~4.0.0", "symfony/http-kernel": "~3.3|~4.0.0",
"symfony/process": "~2.8|~3.0|~4.0.0" "symfony/process": "~2.8|~3.0|~4.0.0"
}, },
"autoload": { "autoload": {

View File

@ -21,16 +21,30 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
class AutowireExceptionPass implements CompilerPassInterface class AutowireExceptionPass implements CompilerPassInterface
{ {
private $autowirePass; private $autowirePass;
private $inlineServicePass;
public function __construct(AutowirePass $autowirePass) public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass)
{ {
$this->autowirePass = $autowirePass; $this->autowirePass = $autowirePass;
$this->inlineServicePass = $inlineServicePass;
} }
public function process(ContainerBuilder $container) public function process(ContainerBuilder $container)
{ {
foreach ($this->autowirePass->getAutowiringExceptions() as $exception) { // the pass should only be run once
if ($container->hasDefinition($exception->getServiceId())) { if (null === $this->autowirePass || null === $this->inlineServicePass) {
return;
}
$inlinedIds = $this->inlineServicePass->getInlinedServiceIds();
$exceptions = $this->autowirePass->getAutowiringExceptions();
// free up references
$this->autowirePass = null;
$this->inlineServicePass = null;
foreach ($exceptions as $exception) {
if ($container->hasDefinition($exception->getServiceId()) || in_array($exception->getServiceId(), $inlinedIds)) {
throw $exception; throw $exception;
} }
} }

View File

@ -23,6 +23,7 @@ use Symfony\Component\DependencyInjection\Reference;
class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
{ {
private $repeatedPass; private $repeatedPass;
private $inlinedServiceIds = array();
/** /**
* {@inheritdoc} * {@inheritdoc}
@ -32,6 +33,16 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
$this->repeatedPass = $repeatedPass; $this->repeatedPass = $repeatedPass;
} }
/**
* Returns an array of all services inlined by this pass.
*
* @return array Service id strings
*/
public function getInlinedServiceIds()
{
return $this->inlinedServiceIds;
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -46,6 +57,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) { if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
$this->inlinedServiceIds[] = $id;
if ($definition->isShared()) { if ($definition->isShared()) {
return $definition; return $definition;

View File

@ -73,11 +73,11 @@ class PassConfig
new RemoveAbstractDefinitionsPass(), new RemoveAbstractDefinitionsPass(),
new RepeatedPass(array( new RepeatedPass(array(
new AnalyzeServiceReferencesPass(), new AnalyzeServiceReferencesPass(),
new InlineServiceDefinitionsPass(), $inlinedServicePass = new InlineServiceDefinitionsPass(),
new AnalyzeServiceReferencesPass(), new AnalyzeServiceReferencesPass(),
new RemoveUnusedDefinitionsPass(), new RemoveUnusedDefinitionsPass(),
)), )),
new AutowireExceptionPass($autowirePass), new AutowireExceptionPass($autowirePass, $inlinedServicePass),
new CheckExceptionOnInvalidReferenceBehaviorPass(), new CheckExceptionOnInvalidReferenceBehaviorPass(),
)); ));
} }

View File

@ -17,6 +17,8 @@ use Symfony\Component\DependencyInjection\Definition;
* Null dumper, negates any proxy code generation for any given service definition. * Null dumper, negates any proxy code generation for any given service definition.
* *
* @author Marco Pivetta <ocramius@gmail.com> * @author Marco Pivetta <ocramius@gmail.com>
*
* @final since version 3.3
*/ */
class NullDumper implements DumperInterface class NullDumper implements DumperInterface
{ {
@ -31,7 +33,7 @@ class NullDumper implements DumperInterface
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
public function getProxyFactoryCode(Definition $definition, $id) public function getProxyFactoryCode(Definition $definition, $id, $methodName = null)
{ {
return ''; return '';
} }

View File

@ -14,6 +14,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Compiler\AutowireExceptionPass; use Symfony\Component\DependencyInjection\Compiler\AutowireExceptionPass;
use Symfony\Component\DependencyInjection\Compiler\AutowirePass; use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass;
use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
@ -29,10 +30,45 @@ class AutowireExceptionPassTest extends TestCase
->method('getAutowiringExceptions') ->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException))); ->will($this->returnValue(array($autowireException)));
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array()));
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$container->register('foo_service_id'); $container->register('foo_service_id');
$pass = new AutowireExceptionPass($autowirePass); $pass = new AutowireExceptionPass($autowirePass, $inlinePass);
try {
$pass->process($container);
$this->fail('->process() should throw the exception if the service id exists');
} catch (\Exception $e) {
$this->assertSame($autowireException, $e);
}
}
public function testThrowExceptionIfServiceInlined()
{
$autowirePass = $this->getMockBuilder(AutowirePass::class)
->getMock();
$autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message');
$autowirePass->expects($this->any())
->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException)));
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array('foo_service_id')));
// don't register the foo_service_id service
$container = new ContainerBuilder();
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
try { try {
$pass->process($container); $pass->process($container);
@ -52,9 +88,15 @@ class AutowireExceptionPassTest extends TestCase
->method('getAutowiringExceptions') ->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException))); ->will($this->returnValue(array($autowireException)));
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array()));
$container = new ContainerBuilder(); $container = new ContainerBuilder();
$pass = new AutowireExceptionPass($autowirePass); $pass = new AutowireExceptionPass($autowirePass, $inlinePass);
$pass->process($container); $pass->process($container);
// mark the test as passed // mark the test as passed

View File

@ -252,6 +252,30 @@ class InlineServiceDefinitionsPassTest extends TestCase
$this->assertSame('inline', (string) $values[0]); $this->assertSame('inline', (string) $values[0]);
} }
public function testGetInlinedServiceIds()
{
$container = new ContainerBuilder();
$container
->register('inlinable.service')
->setPublic(false)
;
$container
->register('non_inlinable.service')
->setPublic(true)
;
$container
->register('service')
->setArguments(array(new Reference('inlinable.service')))
;
$inlinePass = new InlineServiceDefinitionsPass();
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass));
$repeatedPass->process($container);
$this->assertEquals(array('inlinable.service'), $inlinePass->getInlinedServiceIds());
}
protected function process(ContainerBuilder $container) protected function process(ContainerBuilder $container)
{ {
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass())); $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));

View File

@ -88,7 +88,7 @@ class DummyProxyDumper implements ProxyDumper
return false; return false;
} }
public function getProxyFactoryCode(Definition $definition, $id) public function getProxyFactoryCode(Definition $definition, $id, $methodName = null)
{ {
return ''; return '';
} }

View File

@ -10,7 +10,7 @@ CHANGELOG
* deprecated the special `SYMFONY__` environment variables * deprecated the special `SYMFONY__` environment variables
* added the possibility to change the query string parameter used by `UriSigner` * added the possibility to change the query string parameter used by `UriSigner`
* deprecated `LazyLoadingFragmentHandler::addRendererService()` * deprecated `LazyLoadingFragmentHandler::addRendererService()`
* deprecated `Extension::addClassesToCompile()` * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()`
* deprecated `Psr6CacheClearer::addPool()` * deprecated `Psr6CacheClearer::addPool()`
3.2.0 3.2.0

View File

@ -27,9 +27,15 @@ abstract class Extension extends BaseExtension
* Gets the classes to cache. * Gets the classes to cache.
* *
* @return array An array of classes * @return array An array of classes
*
* @deprecated since version 3.3, to be removed in 4.0.
*/ */
public function getClassesToCompile() public function getClassesToCompile()
{ {
if (PHP_VERSION_ID >= 70000) {
@trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
}
return $this->classes; return $this->classes;
} }

View File

@ -320,7 +320,7 @@ class Process implements \IteratorAggregate
} }
if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) {
$this->options['bypass_shell'] = true; $this->options['bypass_shell'] = true;
$commandline = $this->prepareWindowsCommandLine($commandline, $envBackup); $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env);
} elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) {
// last exit code is output on the fourth pipe and caught to work around --enable-sigchild // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
$descriptors[3] = array('pipe', 'w'); $descriptors[3] = array('pipe', 'w');
@ -1627,7 +1627,7 @@ class Process implements \IteratorAggregate
return true; return true;
} }
private function prepareWindowsCommandLine($cmd, array &$envBackup) private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env = null)
{ {
$uid = uniqid('', true); $uid = uniqid('', true);
$varCount = 0; $varCount = 0;
@ -1640,7 +1640,7 @@ class Process implements \IteratorAggregate
[^"%!^]*+ [^"%!^]*+
)++ )++
)"/x', )"/x',
function ($m) use (&$envBackup, &$varCache, &$varCount, $uid) { function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) {
if (isset($varCache[$m[0]])) { if (isset($varCache[$m[0]])) {
return $varCache[$m[0]]; return $varCache[$m[0]];
} }
@ -1652,10 +1652,15 @@ class Process implements \IteratorAggregate
} }
$value = str_replace(array('!LF!', '"^!"', '"^%"', '"^^"', '""'), array("\n", '!', '%', '^', '"'), $value); $value = str_replace(array('!LF!', '"^!"', '"^%"', '"^^"', '""'), array("\n", '!', '%', '^', '"'), $value);
$value = preg_replace('/(\\\\*)"/', '$1$1\\"', $value); $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"';
$var = $uid.++$varCount; $var = $uid.++$varCount;
putenv("$var=\"$value\"");
if (null === $env) {
putenv("$var=$value");
} else {
$env[$var] = $value;
}
$envBackup[$var] = false; $envBackup[$var] = false;
return $varCache[$m[0]] = '!'.$var.'!'; return $varCache[$m[0]] = '!'.$var.'!';

View File

@ -1465,6 +1465,19 @@ class ProcessTest extends TestCase
$this->assertSame($arg, $p->getOutput()); $this->assertSame($arg, $p->getOutput());
} }
/**
* @dataProvider provideEscapeArgument
* @group legacy
*/
public function testEscapeArgumentWhenInheritEnvDisabled($arg)
{
$p = new Process(array(self::$phpBin, '-r', 'echo $argv[1];', $arg), null, array('BAR' => 'BAZ'));
$p->inheritEnvironmentVariables(false);
$p->run();
$this->assertSame($arg, $p->getOutput());
}
public function provideEscapeArgument() public function provideEscapeArgument()
{ {
yield array('a"b%c%'); yield array('a"b%c%');

View File

@ -11,14 +11,5 @@
<condition>context.getMethod() == "GET"</condition> <condition>context.getMethod() == "GET"</condition>
</route> </route>
<route id="blog_show_legacy" path="/blog/{slug}" host="{locale}.example.com">
<default key="_controller">MyBundle:Blog:show</default>
<requirement key="_method">GET|POST|put|OpTiOnS</requirement>
<requirement key="_scheme">hTTps</requirement>
<requirement key="locale">\w+</requirement>
<option key="compiler_class">RouteCompiler</option>
<condition>context.getMethod() == "GET"</condition>
</route>
<route id="blog_show_inherited" path="/blog/{slug}" /> <route id="blog_show_inherited" path="/blog/{slug}" />
</routes> </routes>

View File

@ -70,7 +70,7 @@ class XmlFileLoaderTest extends TestCase
$routeCollection = $loader->load('validresource.xml'); $routeCollection = $loader->load('validresource.xml');
$routes = $routeCollection->all(); $routes = $routeCollection->all();
$this->assertCount(3, $routes, 'Two routes are loaded'); $this->assertCount(2, $routes, 'Two routes are loaded');
$this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes);
foreach ($routes as $route) { foreach ($routes as $route) {

View File

@ -655,17 +655,17 @@ pre.sf-dump code {
border: 1px solid #ffa500; border: 1px solid #ffa500;
border-radius: 3px; border-radius: 3px;
} }
.sf-dump-search-hidden { pre.sf-dump .sf-dump-search-hidden {
display: none; display: none;
} }
.sf-dump-search-wrapper { pre.sf-dump .sf-dump-search-wrapper {
float: right; float: right;
font-size: 0; font-size: 0;
white-space: nowrap; white-space: nowrap;
max-width: 100%; max-width: 100%;
text-align: right; text-align: right;
} }
.sf-dump-search-wrapper > * { pre.sf-dump .sf-dump-search-wrapper > * {
vertical-align: top; vertical-align: top;
box-sizing: border-box; box-sizing: border-box;
height: 21px; height: 21px;
@ -675,7 +675,7 @@ pre.sf-dump code {
color: #757575; color: #757575;
border: 1px solid #BBB; border: 1px solid #BBB;
} }
.sf-dump-search-wrapper > input.sf-dump-search-input { pre.sf-dump .sf-dump-search-wrapper > input.sf-dump-search-input {
padding: 3px; padding: 3px;
height: 21px; height: 21px;
font-size: 12px; font-size: 12px;
@ -685,25 +685,25 @@ pre.sf-dump code {
border-bottom-left-radius: 3px; border-bottom-left-radius: 3px;
color: #000; color: #000;
} }
.sf-dump-search-wrapper > .sf-dump-search-input-next, pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next,
.sf-dump-search-wrapper > .sf-dump-search-input-previous { pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous {
background: #F2F2F2; background: #F2F2F2;
outline: none; outline: none;
border-left: none; border-left: none;
font-size: 0; font-size: 0;
line-height: 0; line-height: 0;
} }
.sf-dump-search-wrapper > .sf-dump-search-input-next { pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next {
border-top-right-radius: 3px; border-top-right-radius: 3px;
border-bottom-right-radius: 3px; border-bottom-right-radius: 3px;
} }
.sf-dump-search-wrapper > .sf-dump-search-input-next > svg, pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-next > svg,
.sf-dump-search-wrapper > .sf-dump-search-input-previous > svg { pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-input-previous > svg {
pointer-events: none; pointer-events: none;
width: 12px; width: 12px;
height: 12px; height: 12px;
} }
.sf-dump-search-wrapper > .sf-dump-search-count { pre.sf-dump .sf-dump-search-wrapper > .sf-dump-search-count {
display: inline-block; display: inline-block;
padding: 0 5px; padding: 0 5px;
margin: 0; margin: 0;

View File

@ -368,7 +368,11 @@ class Parser
foreach ($this->lines as $line) { foreach ($this->lines as $line) {
try { try {
$parsedLine = Inline::parse($line, $flags, $this->refs); if (isset($line[0]) && ('"' === $line[0] || "'" === $line[0])) {
$parsedLine = $line;
} else {
$parsedLine = Inline::parse($line, $flags, $this->refs);
}
if (!is_string($parsedLine)) { if (!is_string($parsedLine)) {
$parseError = true; $parseError = true;

View File

@ -1561,8 +1561,18 @@ EOT;
$this->assertEquals("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz")); $this->assertEquals("foo bar\nbaz", $this->parser->parse("foo\nbar\n\nbaz"));
} }
public function testParseMultiLineMappingValue() /**
* @dataProvider multiLineDataProvider
*/
public function testParseMultiLineMappingValue($yaml, $expected, $parseError)
{ {
$this->assertEquals($expected, $this->parser->parse($yaml));
}
public function multiLineDataProvider()
{
$tests = array();
$yaml = <<<'EOF' $yaml = <<<'EOF'
foo: foo:
- bar: - bar:
@ -1579,7 +1589,43 @@ EOF;
), ),
); );
$this->assertEquals($expected, $this->parser->parse($yaml)); $tests[] = array($yaml, $expected, false);
$yaml = <<<'EOF'
bar
"foo"
EOF;
$expected = 'bar "foo"';
$tests[] = array($yaml, $expected, false);
$yaml = <<<'EOF'
bar
"foo
EOF;
$expected = 'bar "foo';
$tests[] = array($yaml, $expected, false);
$yaml = <<<'EOF'
bar
'foo'
EOF;
$expected = "bar\n'foo'";
$tests[] = array($yaml, $expected, false);
$yaml = <<<'EOF'
bar
foo'
EOF;
$expected = "bar\nfoo'";
$tests[] = array($yaml, $expected, false);
return $tests;
} }
public function testTaggedInlineMapping() public function testTaggedInlineMapping()