Merge branch '4.0'
* 4.0: [DI] Fix missing unset leading to false-positive circular ref [DI] Fix deep-inlining of non-shared refs parse newlines in quoted multiline strings Fix collision between view properties and form fields Fix collision between view properties and form fields [SecurityBundle] Fix compat with HttpFoundation >=3.4 [DI] turn $private to protected in dumped container, to make cache:clear BC Fix collision between view properties and form fields
This commit is contained in:
commit
19b03b5d7e
@ -13,6 +13,7 @@ namespace Symfony\Bridge\Twig\Extension;
|
||||
|
||||
use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser;
|
||||
use Symfony\Component\Form\ChoiceList\View\ChoiceView;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
use Twig\TwigFilter;
|
||||
use Twig\TwigFunction;
|
||||
@ -72,9 +73,15 @@ class FormExtension extends AbstractExtension
|
||||
{
|
||||
return array(
|
||||
new TwigTest('selectedchoice', 'Symfony\Bridge\Twig\Extension\twig_is_selected_choice'),
|
||||
new TwigTest('rootform', array($this, 'isRootForm')),
|
||||
);
|
||||
}
|
||||
|
||||
public function isRootForm(FormView $formView)
|
||||
{
|
||||
return null === $formView->parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -140,12 +140,12 @@
|
||||
|
||||
{% block form_errors -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% if form.parent %}<span class="help-block">{% else %}<div class="alert alert-danger">{% endif %}
|
||||
{% if form is not rootform %}<span class="help-block">{% else %}<div class="alert alert-danger">{% endif %}
|
||||
<ul class="list-unstyled">
|
||||
{%- for error in errors -%}
|
||||
<li><span class="glyphicon glyphicon-exclamation-sign"></span> {{ error.message }}</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
{% if form.parent %}</span>{% else %}</div>{% endif %}
|
||||
{% if form is not rootform %}</span>{% else %}</div>{% endif %}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
@ -173,7 +173,7 @@
|
||||
|
||||
{% block form_errors -%}
|
||||
{%- if errors|length > 0 -%}
|
||||
<div class="{% if form.parent %}invalid-feedback{% else %}alert alert-danger{% endif %}">
|
||||
<div class="{% if form is not rootform %}invalid-feedback{% else %}alert alert-danger{% endif %}">
|
||||
<ul class="list-unstyled mb-0">
|
||||
{%- for error in errors -%}
|
||||
<li>{{ error.message }}</li>
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
{%- block form_widget_compound -%}
|
||||
<div {{ block('widget_container_attributes') }}>
|
||||
{%- if form.parent is empty -%}
|
||||
{%- if form is rootform -%}
|
||||
{{ form_errors(form) }}
|
||||
{%- endif -%}
|
||||
{{- block('form_rows') -}}
|
||||
@ -349,7 +349,7 @@
|
||||
{% endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{% if not form.methodRendered and form.parent is null %}
|
||||
{% if not form.methodRendered and form is rootform %}
|
||||
{%- do form.setMethodRendered() -%}
|
||||
{% set method = method|upper %}
|
||||
{%- if method in ["GET", "POST"] -%}
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
{%- block form_widget_compound -%}
|
||||
<table {{ block('widget_container_attributes') }}>
|
||||
{%- if form.parent is empty and errors|length > 0 -%}
|
||||
{%- if form is rootform and errors|length > 0 -%}
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
{{- form_errors(form) -}}
|
||||
|
@ -318,11 +318,11 @@
|
||||
|
||||
{% block form_errors -%}
|
||||
{% if errors|length > 0 -%}
|
||||
{% if form.parent %}<small class="error">{% else %}<div data-alert class="alert-box alert">{% endif %}
|
||||
{% if form is not rootform %}<small class="error">{% else %}<div data-alert class="alert-box alert">{% endif %}
|
||||
{%- for error in errors -%}
|
||||
{{ error.message }}
|
||||
{% if not loop.last %}, {% endif %}
|
||||
{%- endfor -%}
|
||||
{% if form.parent %}</small>{% else %}</div>{% endif %}
|
||||
{% if form is not rootform %}</small>{% else %}</div>{% endif %}
|
||||
{%- endif %}
|
||||
{%- endblock form_errors %}
|
||||
|
@ -149,6 +149,23 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest
|
||||
$this->assertSame('<form name="form" method="get" action="0">', $html);
|
||||
}
|
||||
|
||||
public function isRootFormProvider()
|
||||
{
|
||||
return array(
|
||||
array(true, new FormView()),
|
||||
array(false, new FormView(new FormView())),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider isRootFormProvider
|
||||
*/
|
||||
public function testIsRootForm($expected, FormView $formView)
|
||||
{
|
||||
$extension = new FormExtension();
|
||||
$this->assertSame($expected, $extension->isRootForm($formView));
|
||||
}
|
||||
|
||||
protected function renderForm(FormView $view, array $vars = array())
|
||||
{
|
||||
return (string) $this->renderer->renderBlock($view, 'form', $vars);
|
||||
|
@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
||||
use Symfony\Component\DependencyInjection\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
|
||||
use Symfony\Component\DependencyInjection\Reference;
|
||||
|
||||
/**
|
||||
@ -23,6 +24,7 @@ use Symfony\Component\DependencyInjection\Reference;
|
||||
class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
|
||||
{
|
||||
private $repeatedPass;
|
||||
private $cloningIds = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@ -41,17 +43,43 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
|
||||
// Reference found in ArgumentInterface::getValues() are not inlineable
|
||||
return $value;
|
||||
}
|
||||
if ($value instanceof Reference && $this->container->hasDefinition($id = (string) $value)) {
|
||||
$definition = $this->container->getDefinition($id);
|
||||
|
||||
if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
|
||||
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
|
||||
|
||||
return $definition->isShared() ? $definition : clone $definition;
|
||||
if ($value instanceof Definition && $this->cloningIds) {
|
||||
if ($value->isShared()) {
|
||||
return $value;
|
||||
}
|
||||
$value = clone $value;
|
||||
}
|
||||
|
||||
return parent::processValue($value, $isRoot);
|
||||
if (!$value instanceof Reference || !$this->container->hasDefinition($id = (string) $value)) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$definition = $this->container->getDefinition($id);
|
||||
|
||||
if (!$this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
|
||||
|
||||
if ($definition->isShared()) {
|
||||
return $definition;
|
||||
}
|
||||
|
||||
if (isset($this->cloningIds[$id])) {
|
||||
$ids = array_keys($this->cloningIds);
|
||||
$ids[] = $id;
|
||||
|
||||
throw new ServiceCircularReferenceException($id, array_slice($ids, array_search($id, $ids)));
|
||||
}
|
||||
|
||||
$this->cloningIds[$id] = true;
|
||||
try {
|
||||
return $this->processValue($definition);
|
||||
} finally {
|
||||
unset($this->cloningIds[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -878,7 +878,11 @@ class $class extends $baseClass
|
||||
{
|
||||
private \$parameters;
|
||||
private \$targetDirs = array();
|
||||
private \$privates = array();
|
||||
|
||||
/*{$this->docStar}
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected \$privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
@ -1062,7 +1066,7 @@ EOF;
|
||||
return $code." );\n";
|
||||
}
|
||||
|
||||
private function addInlineRequires() :string
|
||||
private function addInlineRequires(): string
|
||||
{
|
||||
if (!$this->hotPathTag || !$this->inlineRequires) {
|
||||
return '';
|
||||
|
@ -111,6 +111,60 @@ class InlineServiceDefinitionsPassTest extends TestCase
|
||||
$this->assertEquals($container->getDefinition('foo')->getArgument(0), $container->getDefinition('bar'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException
|
||||
* @expectedExceptionMessage Circular reference detected for service "bar", path: "bar -> foo -> bar".
|
||||
*/
|
||||
public function testProcessThrowsOnNonSharedLoops()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container
|
||||
->register('foo')
|
||||
->addArgument(new Reference('bar'))
|
||||
->setShared(false)
|
||||
;
|
||||
$container
|
||||
->register('bar')
|
||||
->setShared(false)
|
||||
->addMethodCall('setFoo', array(new Reference('foo')))
|
||||
;
|
||||
|
||||
$this->process($container);
|
||||
}
|
||||
|
||||
public function testProcessNestedNonSharedServices()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$container
|
||||
->register('foo')
|
||||
->addArgument(new Reference('bar1'))
|
||||
->addArgument(new Reference('bar2'))
|
||||
;
|
||||
$container
|
||||
->register('bar1')
|
||||
->setShared(false)
|
||||
->addArgument(new Reference('baz'))
|
||||
;
|
||||
$container
|
||||
->register('bar2')
|
||||
->setShared(false)
|
||||
->addArgument(new Reference('baz'))
|
||||
;
|
||||
$container
|
||||
->register('baz')
|
||||
->setShared(false)
|
||||
;
|
||||
|
||||
$this->process($container);
|
||||
|
||||
$baz1 = $container->getDefinition('foo')->getArgument(0)->getArgument(0);
|
||||
$baz2 = $container->getDefinition('foo')->getArgument(1)->getArgument(0);
|
||||
|
||||
$this->assertEquals($container->getDefinition('baz'), $baz1);
|
||||
$this->assertEquals($container->getDefinition('baz'), $baz2);
|
||||
$this->assertNotSame($baz1, $baz2);
|
||||
}
|
||||
|
||||
public function testProcessInlinesIfMultipleReferencesButAllFromTheSameDefinition()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
@ -20,7 +20,11 @@ class Container extends \Symfony\Component\DependencyInjection\Dump\AbstractCont
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_EnvParameters extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -309,7 +309,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class ProjectServiceContainer extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -18,7 +18,11 @@ class Symfony_DI_PhpDumper_Test_Uninitialized_Reference extends Container
|
||||
{
|
||||
private $parameters;
|
||||
private $targetDirs = array();
|
||||
private $privates = array();
|
||||
|
||||
/**
|
||||
* @internal but protected for BC on cache:clear
|
||||
*/
|
||||
protected $privates = array();
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -684,6 +684,8 @@ class Parser
|
||||
return Inline::parse($value, $flags, $this->refs);
|
||||
}
|
||||
|
||||
$lines = array();
|
||||
|
||||
while ($this->moveToNextLine()) {
|
||||
// unquoted strings end before the first unindented line
|
||||
if (null === $quotation && 0 === $this->getCurrentLineIndentation()) {
|
||||
@ -692,7 +694,7 @@ class Parser
|
||||
break;
|
||||
}
|
||||
|
||||
$value .= ' '.trim($this->currentLine);
|
||||
$lines[] = trim($this->currentLine);
|
||||
|
||||
// quoted string values end with a line that is terminated with the quotation character
|
||||
if ('' !== $this->currentLine && substr($this->currentLine, -1) === $quotation) {
|
||||
@ -700,6 +702,21 @@ class Parser
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0, $linesCount = count($lines), $previousLineBlank = false; $i < $linesCount; ++$i) {
|
||||
if ('' === $lines[$i]) {
|
||||
$value .= "\n";
|
||||
$previousLineBlank = true;
|
||||
} elseif ($previousLineBlank) {
|
||||
$value .= $lines[$i];
|
||||
$previousLineBlank = false;
|
||||
} else {
|
||||
$value .= ' '.$lines[$i];
|
||||
$previousLineBlank = false;
|
||||
}
|
||||
}
|
||||
|
||||
Inline::$parsedLineNumber = $this->getRealCurrentLineNb();
|
||||
|
||||
$parsedValue = Inline::parse($value, $flags, $this->refs);
|
||||
|
||||
if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) {
|
||||
|
@ -1451,6 +1451,20 @@ YAML;
|
||||
$this->assertSame($expected, $this->parser->parse($yaml));
|
||||
}
|
||||
|
||||
public function testBlankLinesInQuotedMultiLineString()
|
||||
{
|
||||
$yaml = <<<YAML
|
||||
foobar: 'foo
|
||||
|
||||
bar'
|
||||
YAML;
|
||||
$expected = array(
|
||||
'foobar' => "foo\nbar",
|
||||
);
|
||||
|
||||
$this->assertSame($expected, $this->parser->parse($yaml));
|
||||
}
|
||||
|
||||
public function testParseMultiLineUnquotedString()
|
||||
{
|
||||
$yaml = <<<EOT
|
||||
|
Reference in New Issue
Block a user