',
+ ), $dump);
+
+ return new \Twig_Markup($dump, 'UTF-8');
}
public function getProfile()
diff --git a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php
index b13d7c0f8533..fa5fae2e77a0 100644
--- a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php
+++ b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php
@@ -13,6 +13,7 @@
use Symfony\Component\Security\Acl\Voter\FieldVote;
use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
+use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
/**
* SecurityExtension exposes security context features.
@@ -38,7 +39,11 @@ public function isGranted($role, $object = null, $field = null)
$object = new FieldVote($object, $field);
}
- return $this->securityChecker->isGranted($role, $object);
+ try {
+ return $this->securityChecker->isGranted($role, $object);
+ } catch (AuthenticationCredentialsNotFoundException $e) {
+ return false;
+ }
}
/**
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
index e3a611c38ffc..3e0a348d9ae9 100644
--- a/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/form_div_layout.html.twig
@@ -176,6 +176,11 @@
{{ block('form_widget_simple') }}
{%- endblock email_widget -%}
+{%- block range_widget -%}
+ {% set type = type|default('range') %}
+ {{- block('form_widget_simple') -}}
+{%- endblock range_widget %}
+
{%- block button_widget -%}
{%- if label is empty -%}
{%- if label_format is not empty -%}
@@ -314,7 +319,6 @@
{%- block widget_attributes -%}
id="{{ id }}" name="{{ full_name }}"
- {%- if read_only and attr.readonly is not defined %} readonly="readonly"{% endif -%}
{%- if disabled %} disabled="disabled"{% endif -%}
{%- if required %} required="required"{% endif -%}
{%- for attrname, attrvalue in attr -%}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig
new file mode 100644
index 000000000000..6e2b10608235
--- /dev/null
+++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig
@@ -0,0 +1,321 @@
+{% extends "form_div_layout.html.twig" %}
+
+{# Based on Foundation 5 Doc #}
+{# Widgets #}
+
+{% block form_widget_simple -%}
+ {% if errors|length > 0 -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {{- parent() -}}
+{%- endblock form_widget_simple %}
+
+{% block textarea_widget -%}
+ {% if errors|length > 0 -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {{- parent() -}}
+{%- endblock textarea_widget %}
+
+{% block button_widget -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %}
+ {{- parent() -}}
+{%- endblock %}
+
+{% block money_widget -%}
+
+ {% set prepend = '{{' == money_pattern[0:2] %}
+ {% if not prepend %}
+
+ {{ money_pattern|replace({ '{{ widget }}':''}) }}
+
+ {% endif %}
+
+ {{- block('form_widget_simple') -}}
+
+ {% if prepend %}
+
+ {{ money_pattern|replace({ '{{ widget }}':''}) }}
+
+ {% endif %}
+
+{%- endblock money_widget %}
+
+{% block percent_widget -%}
+
+
+ {{- block('form_widget_simple') -}}
+
+
+ %
+
+
+{%- endblock percent_widget %}
+
+{% block datetime_widget -%}
+ {% if widget == 'single_text' %}
+ {{- block('form_widget_simple') -}}
+ {% else %}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
+
+
{{ form_errors(form.date) }}
+
{{ form_errors(form.time) }}
+
+
+
{{ form_widget(form.date, { datetime: true } ) }}
+
{{ form_widget(form.time, { datetime: true } ) }}
+
+ {% endif %}
+{%- endblock datetime_widget %}
+
+{% block date_widget -%}
+ {% if widget == 'single_text' %}
+ {{- block('form_widget_simple') -}}
+ {% else %}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
+ {% if datetime is not defined or not datetime %}
+
+ {% endif %}
+ {{- date_pattern|replace({
+ '{{ year }}': '
' ~ form_widget(form.year) ~ '
',
+ '{{ month }}': '
' ~ form_widget(form.month) ~ '
',
+ '{{ day }}': '
' ~ form_widget(form.day) ~ '
',
+ })|raw -}}
+ {% if datetime is not defined or not datetime %}
+
+ {% endif %}
+ {% endif %}
+{%- endblock date_widget %}
+
+{% block time_widget -%}
+ {% if widget == 'single_text' %}
+ {{- block('form_widget_simple') -}}
+ {% else %}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' row')|trim}) %}
+ {% if datetime is not defined or false == datetime %}
+
+ {% endif %}
+ {% if with_seconds %}
+
{{ form_widget(form.hour) }}
+
+
+
+ :
+
+
+ {{ form_widget(form.minute) }}
+
+
+
+
+
+
+ :
+
+
+ {{ form_widget(form.second) }}
+
+
+
+ {% else %}
+
{{ form_widget(form.hour) }}
+
+
+
+ :
+
+
+ {{ form_widget(form.minute) }}
+
+
+
+ {% endif %}
+ {% if datetime is not defined or false == datetime %}
+
+ {% endif %}
+ {% endif %}
+{%- endblock time_widget %}
+
+{% block choice_widget_collapsed -%}
+ {% if errors|length > 0 -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+
+ {% if multiple -%}
+ {% set attr = attr|merge({style: (attr.style|default('') ~ ' height: auto; background-image: none;')|trim}) %}
+ {% endif %}
+
+ {% if required and placeholder is none and not placeholder_in_choices and not multiple -%}
+ {% set required = false %}
+ {%- endif -%}
+
+ {% if placeholder is not none -%}
+ {{ placeholder|trans({}, translation_domain) }}
+ {%- endif %}
+ {%- if preferred_choices|length > 0 -%}
+ {% set options = preferred_choices %}
+ {{- block('choice_widget_options') -}}
+ {% if choices|length > 0 and separator is not none -%}
+ {{ separator }}
+ {%- endif %}
+ {%- endif -%}
+ {% set options = choices -%}
+ {{- block('choice_widget_options') -}}
+
+{%- endblock choice_widget_collapsed %}
+
+{% block choice_widget_expanded -%}
+ {% if '-inline' in label_attr.class|default('') %}
+
+ {% for child in form %}
+ {{ form_widget(child, {
+ parent_label_class: label_attr.class|default(''),
+ }) }}
+ {% endfor %}
+
+ {% else %}
+
+ {% for child in form %}
+ {{ form_widget(child, {
+ parent_label_class: label_attr.class|default(''),
+ }) }}
+ {% endfor %}
+
+ {% endif %}
+{%- endblock choice_widget_expanded %}
+
+{% block checkbox_widget -%}
+ {% set parent_label_class = parent_label_class|default('') %}
+ {% if errors|length > 0 -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {% if 'checkbox-inline' in parent_label_class %}
+ {{ form_label(form, null, { widget: parent() }) }}
+ {% else %}
+
+ {{ form_label(form, null, { widget: parent() }) }}
+
+ {% endif %}
+{%- endblock checkbox_widget %}
+
+{% block radio_widget -%}
+ {% set parent_label_class = parent_label_class|default('') %}
+ {% if 'radio-inline' in parent_label_class %}
+ {{ form_label(form, null, { widget: parent() }) }}
+ {% else %}
+ {% if errors|length > 0 -%}
+ {% set attr = attr|merge({class: (attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+
+ {{ form_label(form, null, { widget: parent() }) }}
+
+ {% endif %}
+{%- endblock radio_widget %}
+
+{# Labels #}
+
+{% block form_label -%}
+ {% if errors|length > 0 -%}
+ {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {{- parent() -}}
+{%- endblock form_label %}
+
+{% block choice_label -%}
+ {% if errors|length > 0 -%}
+ {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #}
+ {% set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) %}
+ {{- block('form_label') -}}
+{%- endblock %}
+
+{% block checkbox_label -%}
+ {{- block('checkbox_radio_label') -}}
+{%- endblock checkbox_label %}
+
+{% block radio_label -%}
+ {{- block('checkbox_radio_label') -}}
+{%- endblock radio_label %}
+
+{% block checkbox_radio_label -%}
+ {% if required %}
+ {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %}
+ {% endif %}
+ {% if errors|length > 0 -%}
+ {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' error')|trim}) %}
+ {% endif %}
+ {% if parent_label_class is defined %}
+ {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ parent_label_class)|trim}) %}
+ {% endif %}
+ {% if label is empty %}
+ {% set label = name|humanize %}
+ {% endif %}
+
+ {{ widget|raw }}
+ {{ label|trans({}, translation_domain) }}
+
+{%- endblock checkbox_radio_label %}
+
+{# Rows #}
+
+{% block form_row -%}
+
+
+ {{ form_label(form) }}
+ {{ form_widget(form) }}
+ {{ form_errors(form) }}
+
+
+{%- endblock form_row %}
+
+{% block choice_row -%}
+ {% set force_error = true %}
+ {{ block('form_row') }}
+{%- endblock choice_row %}
+
+{% block date_row -%}
+ {% set force_error = true %}
+ {{ block('form_row') }}
+{%- endblock date_row %}
+
+{% block time_row -%}
+ {% set force_error = true %}
+ {{ block('form_row') }}
+{%- endblock time_row %}
+
+{% block datetime_row -%}
+ {% set force_error = true %}
+ {{ block('form_row') }}
+{%- endblock datetime_row %}
+
+{% block checkbox_row -%}
+
+
+ {{ form_widget(form) }}
+ {{ form_errors(form) }}
+
+
+{%- endblock checkbox_row %}
+
+{% block radio_row -%}
+
+
+ {{ form_widget(form) }}
+ {{ form_errors(form) }}
+
+
+{%- endblock radio_row %}
+
+{# Errors #}
+
+{% block form_errors -%}
+ {% if errors|length > 0 -%}
+ {% if form.parent %}{% else %} {% endif %}
+ {%- for error in errors -%}
+ {{ error.message }}
+ {% if not loop.last %}, {% endif %}
+ {%- endfor -%}
+ {% if form.parent %}{% else %}
{% endif %}
+ {%- endif %}
+{%- endblock form_errors %}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
index a9d161b2b909..8e7655269753 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php
@@ -115,14 +115,4 @@ protected function setTheme(FormView $view, array $themes)
{
$this->extension->renderer->setTheme($view, $themes);
}
-
- public function testRange()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
-
- public function testRangeWithMinMaxValues()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
index 1bce43b83780..e720836c9558 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php
@@ -69,7 +69,7 @@ protected function tearDown()
public function testThemeBlockInheritanceUsingUse()
{
$view = $this->factory
- ->createNamed('name', 'email')
+ ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType')
->createView()
;
@@ -84,7 +84,7 @@ public function testThemeBlockInheritanceUsingUse()
public function testThemeBlockInheritanceUsingExtend()
{
$view = $this->factory
- ->createNamed('name', 'email')
+ ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType')
->createView()
;
@@ -99,7 +99,7 @@ public function testThemeBlockInheritanceUsingExtend()
public function testThemeBlockInheritanceUsingDynamicExtend()
{
$view = $this->factory
- ->createNamed('name', 'email')
+ ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType')
->createView()
;
@@ -208,14 +208,4 @@ public static function themeInheritanceProvider()
array(array('parent_label.html.twig'), array('child_label.html.twig')),
);
}
-
- public function testRange()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
-
- public function testRangeWithMinMaxValues()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
index 555ea306fca8..f8f3ddf3e5bc 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php
@@ -116,14 +116,4 @@ protected function setTheme(FormView $view, array $themes)
{
$this->extension->renderer->setTheme($view, $themes);
}
-
- public function testRange()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
-
- public function testRangeWithMinMaxValues()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
}
diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
index 48bebdc13f8f..403ed32fd801 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
@@ -43,7 +43,7 @@ public function testUnknownFragmentRenderer()
->disableOriginalConstructor()
->getMock()
;
- $renderer = new FragmentHandler(array(), false, $context);
+ $renderer = new FragmentHandler($context);
$this->setExpectedException('InvalidArgumentException', 'The "inline" renderer does not exist.');
$renderer->render('/foo');
@@ -62,7 +62,7 @@ protected function getFragmentHandler($return)
$context->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/')));
- $renderer = new FragmentHandler(array($strategy), false, $context);
+ $renderer = new FragmentHandler($context, array($strategy), false);
return $renderer;
}
diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json
index 74939001f530..f56133daaab5 100644
--- a/src/Symfony/Bridge/Twig/composer.json
+++ b/src/Symfony/Bridge/Twig/composer.json
@@ -20,22 +20,22 @@
"twig/twig": "~1.20|~2.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
- "symfony/asset": "~2.7",
- "symfony/finder": "~2.3",
- "symfony/form": "~2.7,>=2.7.2",
- "symfony/http-kernel": "~2.3",
- "symfony/intl": "~2.3",
- "symfony/routing": "~2.2",
- "symfony/templating": "~2.1",
- "symfony/translation": "~2.7",
- "symfony/yaml": "~2.0,>=2.0.5",
- "symfony/security": "~2.6",
- "symfony/security-acl": "~2.6",
- "symfony/stopwatch": "~2.2",
- "symfony/console": "~2.7",
- "symfony/var-dumper": "~2.6",
- "symfony/expression-language": "~2.4"
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
+ "symfony/asset": "~2.7|~3.0.0",
+ "symfony/finder": "~2.3|~3.0.0",
+ "symfony/form": "~2.8",
+ "symfony/http-kernel": "~2.8|~3.0.0",
+ "symfony/intl": "~2.3|~3.0.0",
+ "symfony/routing": "~2.2|~3.0.0",
+ "symfony/templating": "~2.1|~3.0.0",
+ "symfony/translation": "~2.7|~3.0.0",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/security": "~2.6|~3.0.0",
+ "symfony/security-acl": "~2.6|~3.0.0",
+ "symfony/stopwatch": "~2.2|~3.0.0",
+ "symfony/console": "~2.7|~3.0.0",
+ "symfony/var-dumper": "~2.6|~3.0.0",
+ "symfony/expression-language": "~2.4|~3.0.0"
},
"suggest": {
"symfony/finder": "",
@@ -57,7 +57,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig
index e7a8245fb3b0..1163d283d020 100644
--- a/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig
+++ b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/dump.html.twig
@@ -1,21 +1,16 @@
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
{% block toolbar %}
- {% set dumps_count = collector.dumpsCount %}
-
- {% if dumps_count %}
+ {% if collector.dumpsCount %}
{% set icon %}
-
- {{ dumps_count }}
+ {{ include('@Debug/Profiler/icon.svg') }}
+ {{ collector.dumpsCount }}
{% endset %}
{% set text %}
-
- dump()
-
{% for dump in collector.getDumps('html') %}
- in
+
{% if dump.file %}
{% set link = dump.file|file_link(dump.line) %}
{% if link %}
@@ -26,54 +21,32 @@
{% else %}
{{ dump.name }}
{% endif %}
- line {{ dump.line }}:
+
+ line {{ dump.line }}
+
{{ dump.data|raw }}
{% endfor %}
{% endset %}
- {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': true } %}
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
{% endif %}
{% endblock %}
{% block menu %}
-
-
- {{- "" -}}
-
- {{- "" -}}
-
- dump()
-
- {{ collector.dumpsCount }}
-
+
+ {{ include('@Debug/Profiler/icon.svg') }}
+ Debug
{% endblock %}
{% block panel %}
- dump()
+ Dumped Contents
-
-
- {% if collector.dumpsCount %}
-
- {% for dump in collector.getDumps('html') %}
-
- in
+ {% for dump in collector.getDumps('html') %}
+
+
In
{% if dump.line %}
{% set link = dump.file|file_link(dump.line) %}
{% if link %}
@@ -84,19 +57,22 @@
{% else %}
{{ dump.name }}
{% endif %}
- line {{ dump.line }}:
- ▶
-
- {% if dump.fileExcerpt %}{{ dump.fileExcerpt|raw }}{% else %}{{ dump.file|file_excerpt(dump.line) }}{% endif %}
-
+ line {{ dump.line }}
- {{ dump.data|raw }}
-
- {% endfor %}
-
+ Show code
+
+
+
+
+ {{ dump.fileExcerpt ? dump.fileExcerpt|raw : dump.file|file_excerpt(dump.line) }}
+
+
+
+ {{ dump.data|raw }}
+
{% else %}
-
- No dumped variable
-
- {% endif %}
+
+
No content was dumped.
+
+ {% endfor %}
{% endblock %}
diff --git a/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/icon.svg b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/icon.svg
new file mode 100644
index 000000000000..2f7e708c8b3d
--- /dev/null
+++ b/src/Symfony/Bundle/DebugBundle/Resources/views/Profiler/icon.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json
index e7ccc9a4b11f..66d77643479d 100644
--- a/src/Symfony/Bundle/DebugBundle/composer.json
+++ b/src/Symfony/Bundle/DebugBundle/composer.json
@@ -17,15 +17,15 @@
],
"require": {
"php": ">=5.3.9",
- "symfony/http-kernel": "~2.6",
- "symfony/twig-bridge": "~2.6",
- "symfony/var-dumper": "~2.6"
+ "symfony/http-kernel": "~2.6|~3.0.0",
+ "symfony/twig-bridge": "~2.6|~3.0.0",
+ "symfony/var-dumper": "~2.6|~3.0.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
- "symfony/config": "~2.3",
- "symfony/dependency-injection": "~2.3",
- "symfony/web-profiler-bundle": "~2.3"
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
+ "symfony/config": "~2.3|~3.0.0",
+ "symfony/dependency-injection": "~2.3|~3.0.0",
+ "symfony/web-profiler-bundle": "~2.3|~3.0.0"
},
"suggest": {
"symfony/config": "For service container configuration",
@@ -37,7 +37,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
index ad8cb2e6e988..474637d6eaf0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========
+2.8.0
+-----
+
+ * Deprecated the Shell
+
2.7.0
-----
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
index 5b627ded6ae6..647dc0fd5850 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php
@@ -11,20 +11,34 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
+use Symfony\Component\Console\Helper\Table;
use Symfony\Component\Console\Input\InputArgument;
-use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Filesystem\Exception\IOException;
+use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
+use Symfony\Component\HttpKernel\Bundle\BundleInterface;
/**
* Command that places bundle web assets into a given directory.
*
* @author Fabien Potencier
+ * @author Gábor Egyed
*/
class AssetsInstallCommand extends ContainerAwareCommand
{
+ const METHOD_COPY = 'copy';
+ const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink';
+ const METHOD_RELATIVE_SYMLINK = 'relative symlink';
+
+ /**
+ * @var Filesystem
+ */
+ private $filesystem;
+
/**
* {@inheritdoc}
*/
@@ -63,8 +77,6 @@ protected function configure()
/**
* {@inheritdoc}
- *
- * @throws \InvalidArgumentException When the target directory does not exist or symlink cannot be used
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -74,77 +86,164 @@ protected function execute(InputInterface $input, OutputInterface $output)
throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target')));
}
- $filesystem = $this->getContainer()->get('filesystem');
+ $this->filesystem = $this->getContainer()->get('filesystem');
// Create the bundles directory otherwise symlink will fail.
$bundlesDir = $targetArg.'/bundles/';
- $filesystem->mkdir($bundlesDir, 0777);
+ $this->filesystem->mkdir($bundlesDir, 0777);
- // relative implies symlink
- $symlink = $input->getOption('symlink') || $input->getOption('relative');
+ $io = new SymfonyStyle($input, $output);
+ $io->newLine();
- if ($symlink) {
- $output->writeln('Trying to install assets as symbolic links .');
+ if ($input->getOption('relative')) {
+ $expectedMethod = self::METHOD_RELATIVE_SYMLINK;
+ $io->text('Trying to install assets as relative symbolic links .');
+ } elseif ($input->getOption('symlink')) {
+ $expectedMethod = self::METHOD_ABSOLUTE_SYMLINK;
+ $io->text('Trying to install assets as absolute symbolic links .');
} else {
- $output->writeln('Installing assets as hard copies .');
+ $expectedMethod = self::METHOD_COPY;
+ $io->text('Installing assets as hard copies .');
}
+ $io->newLine();
+
+ $rows = array();
+ $copyUsed = false;
+ $exitCode = 0;
+ /** @var BundleInterface $bundle */
foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) {
- if (is_dir($originDir = $bundle->getPath().'/Resources/public')) {
- $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
-
- $output->writeln(sprintf('Installing assets for %s into %s ', $bundle->getNamespace(), $targetDir));
-
- $filesystem->remove($targetDir);
-
- if ($symlink) {
- if ($input->getOption('relative')) {
- $relativeOriginDir = $filesystem->makePathRelative($originDir, realpath($bundlesDir));
- } else {
- $relativeOriginDir = $originDir;
- }
-
- try {
- $filesystem->symlink($relativeOriginDir, $targetDir);
- if (!file_exists($targetDir)) {
- throw new IOException('Symbolic link is broken');
- }
- $output->writeln('The assets were installed using symbolic links.');
- } catch (IOException $e) {
- if (!$input->getOption('relative')) {
- $this->hardCopy($originDir, $targetDir);
- $output->writeln('It looks like your system doesn\'t support symbolic links, so the assets were installed by copying them.');
- }
-
- // try again without the relative option
- try {
- $filesystem->symlink($originDir, $targetDir);
- if (!file_exists($targetDir)) {
- throw new IOException('Symbolic link is broken');
- }
- $output->writeln('It looks like your system doesn\'t support relative symbolic links, so the assets were installed by using absolute symbolic links.');
- } catch (IOException $e) {
- $this->hardCopy($originDir, $targetDir);
- $output->writeln('It looks like your system doesn\'t support symbolic links, so the assets were installed by copying them.');
- }
- }
+ if (!is_dir($originDir = $bundle->getPath().'/Resources/public')) {
+ continue;
+ }
+
+ $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName()));
+
+ if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
+ $message = sprintf("%s\n-> %s", $bundle->getName(), $targetDir);
+ } else {
+ $message = $bundle->getName();
+ }
+
+ try {
+ $this->filesystem->remove($targetDir);
+
+ if (self::METHOD_RELATIVE_SYMLINK === $expectedMethod) {
+ $method = $this->relativeSymlinkWithFallback($originDir, $targetDir);
+ } elseif (self::METHOD_ABSOLUTE_SYMLINK === $expectedMethod) {
+ $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
+ } else {
+ $method = $this->hardCopy($originDir, $targetDir);
+ }
+
+ if (self::METHOD_COPY === $method) {
+ $copyUsed = true;
+ }
+
+ if ($method === $expectedMethod) {
+ $rows[] = array(sprintf('%s>', '\\' === DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */), $message, $method);
} else {
- $this->hardCopy($originDir, $targetDir);
+ $rows[] = array(sprintf('%s>', '\\' === DIRECTORY_SEPARATOR ? 'WARNING' : '!'), $message, $method);
}
+ } catch (\Exception $e) {
+ $exitCode = 1;
+ $rows[] = array(sprintf('%s>', '\\' === DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */), $message, $e->getMessage());
+ }
+ }
+
+ $io->table(array('', 'Bundle', 'Method / Error'), $rows);
+
+ if (0 !== $exitCode) {
+ $io->error('Some errors occurred while installing assets.');
+ } else {
+ if ($copyUsed) {
+ $io->note('Some assets were installed via copy. If you make changes to these assets you have to run this command again.');
}
+ $io->success('All assets were successfully installed.');
}
+
+ return $exitCode;
}
/**
+ * Try to create relative symlink.
+ *
+ * Falling back to absolute symlink and finally hard copy.
+ *
* @param string $originDir
* @param string $targetDir
+ *
+ * @return string
*/
- private function hardCopy($originDir, $targetDir)
+ private function relativeSymlinkWithFallback($originDir, $targetDir)
+ {
+ try {
+ $this->symlink($originDir, $targetDir, true);
+ $method = self::METHOD_RELATIVE_SYMLINK;
+ } catch (IOException $e) {
+ $method = $this->absoluteSymlinkWithFallback($originDir, $targetDir);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Try to create absolute symlink.
+ *
+ * Falling back to hard copy.
+ *
+ * @param string $originDir
+ * @param string $targetDir
+ *
+ * @return string
+ */
+ private function absoluteSymlinkWithFallback($originDir, $targetDir)
+ {
+ try {
+ $this->symlink($originDir, $targetDir);
+ $method = self::METHOD_ABSOLUTE_SYMLINK;
+ } catch (IOException $e) {
+ // fall back to copy
+ $method = $this->hardCopy($originDir, $targetDir);
+ }
+
+ return $method;
+ }
+
+ /**
+ * Creates symbolic link.
+ *
+ * @param string $originDir
+ * @param string $targetDir
+ * @param bool $relative
+ *
+ * @throws IOException If link can not be created.
+ */
+ private function symlink($originDir, $targetDir, $relative = false)
{
- $filesystem = $this->getContainer()->get('filesystem');
+ if ($relative) {
+ $originDir = $this->filesystem->makePathRelative($originDir, realpath(dirname($targetDir)));
+ }
+ $this->filesystem->symlink($originDir, $targetDir);
+ if (!file_exists($targetDir)) {
+ throw new IOException(sprintf('Symbolic link "%s" was created but appears to be broken.', $targetDir), 0, null, $targetDir);
+ }
+ }
- $filesystem->mkdir($targetDir, 0777);
+ /**
+ * Copies origin to target.
+ *
+ * @param string $originDir
+ * @param string $targetDir
+ *
+ * @return string
+ */
+ private function hardCopy($originDir, $targetDir)
+ {
+ $this->filesystem->mkdir($targetDir, 0777);
// We use a custom iterator to ignore VCS files
- $filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
+ $this->filesystem->mirror($originDir, $targetDir, Finder::create()->ignoreDotFiles(false)->in($originDir));
+
+ return self::METHOD_COPY;
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
index 6e85702cf678..881a146d0d43 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php
@@ -14,6 +14,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Finder\Finder;
@@ -53,6 +54,9 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $outputIsVerbose = $output->isVerbose();
+ $output = new SymfonyStyle($input, $output);
+
$realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir');
$oldCacheDir = $realCacheDir.'_old';
$filesystem = $this->getContainer()->get('filesystem');
@@ -66,7 +70,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$kernel = $this->getContainer()->get('kernel');
- $output->writeln(sprintf('Clearing the cache for the %s environment with debug %s ', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
+ $output->comment(sprintf('Clearing the cache for the %s environment with debug %s ', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
$this->getContainer()->get('cache_clearer')->clear($realCacheDir);
if ($input->getOption('no-warmup')) {
@@ -78,14 +82,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
$warmupDir = substr($realCacheDir, 0, -1).'_';
if ($filesystem->exists($warmupDir)) {
- if ($output->isVerbose()) {
- $output->writeln(' Clearing outdated warmup directory');
+ if ($outputIsVerbose) {
+ $output->comment('Clearing outdated warmup directory...');
}
$filesystem->remove($warmupDir);
}
- if ($output->isVerbose()) {
- $output->writeln(' Warming up cache');
+ if ($outputIsVerbose) {
+ $output->comment('Warming up cache...');
}
$this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers'));
@@ -96,15 +100,17 @@ protected function execute(InputInterface $input, OutputInterface $output)
$filesystem->rename($warmupDir, $realCacheDir);
}
- if ($output->isVerbose()) {
- $output->writeln(' Removing old cache directory');
+ if ($outputIsVerbose) {
+ $output->comment('Removing old cache directory...');
}
$filesystem->remove($oldCacheDir);
- if ($output->isVerbose()) {
- $output->writeln(' Done');
+ if ($outputIsVerbose) {
+ $output->comment('Finished');
}
+
+ $output->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
index 8e08153d4a96..2352009b980e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php
@@ -14,6 +14,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Warmup the cache.
@@ -53,8 +54,10 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
+
$kernel = $this->getContainer()->get('kernel');
- $output->writeln(sprintf('Warming up the cache for the %s environment with debug %s ', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
+ $output->comment(sprintf('Warming up the cache for the %s environment with debug %s ', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
$warmer = $this->getContainer()->get('cache_warmer');
@@ -63,5 +66,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$warmer->warmUp($this->getContainer()->getParameter('kernel.cache_dir'));
+
+ $output->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true)));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterApacheDumperCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterApacheDumperCommand.php
index bfbfaa78bc48..f092b118d29f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterApacheDumperCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterApacheDumperCommand.php
@@ -15,6 +15,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Routing\Matcher\Dumper\ApacheMatcherDumper;
use Symfony\Component\Routing\RouterInterface;
@@ -74,9 +75,11 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
- $formatter = $this->getHelper('formatter');
+ $output = new SymfonyStyle($input, $output);
- $output->writeln($formatter->formatSection('warning', 'The router:dump-apache command is deprecated since version 2.5 and will be removed in 3.0', 'comment'));
+ $output->title('Router Apache Dumper');
+
+ $output->caution('The router:dump-apache command is deprecated since version 2.5 and will be removed in 3.0.');
$router = $this->getContainer()->get('router');
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
index 6f7db66a660f..9b96c77868ea 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php
@@ -16,6 +16,7 @@
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Route;
@@ -77,8 +78,10 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
+
if (false !== strpos($input->getFirstArgument(), ':d')) {
- $output->writeln('The use of "router:debug" command is deprecated since version 2.7 and will be removed in 3.0. Use the "debug:router" instead. ');
+ $output->caution('The use of "router:debug" command is deprecated since version 2.7 and will be removed in 3.0. Use the "debug:router" instead.');
}
$name = $input->getArgument('name');
@@ -89,11 +92,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
if (!$route) {
throw new \InvalidArgumentException(sprintf('The route "%s" does not exist.', $name));
}
+
$this->convertController($route);
+
$helper->describe($output, $route, array(
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'name' => $name,
+ 'output' => $output,
));
} else {
$routes = $this->getContainer()->get('router')->getRouteCollection();
@@ -106,6 +112,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
'format' => $input->getOption('format'),
'raw_text' => $input->getOption('raw'),
'show_controllers' => $input->getOption('show-controllers'),
+ 'output' => $output,
));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
index c1afc9d83b7e..ee690770037e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php
@@ -11,11 +11,12 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
+use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
-use Symfony\Component\Console\Input\ArrayInput;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Routing\RouterInterface;
use Symfony\Component\Routing\Matcher\TraceableUrlMatcher;
@@ -60,7 +61,7 @@ protected function configure()
The %command.name% shows which routes match a given request and which don't and for what reason:
php %command.full_name% /foo
-
+
or
php %command.full_name% /foo --method POST --scheme https --host symfony.com --verbose
@@ -75,6 +76,8 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
+
$router = $this->getContainer()->get('router');
$context = $router->getContext();
if (null !== $method = $input->getOption('method')) {
@@ -91,25 +94,26 @@ protected function execute(InputInterface $input, OutputInterface $output)
$traces = $matcher->getTraces($input->getArgument('path_info'));
+ $output->newLine();
+
$matches = false;
foreach ($traces as $trace) {
if (TraceableUrlMatcher::ROUTE_ALMOST_MATCHES == $trace['level']) {
- $output->writeln(sprintf('Route "%s" almost matches but %s>', $trace['name'], lcfirst($trace['log'])));
+ $output->text(sprintf('Route "%s"> almost matches but %s', $trace['name'], lcfirst($trace['log'])));
} elseif (TraceableUrlMatcher::ROUTE_MATCHES == $trace['level']) {
- $output->writeln(sprintf('Route "%s" matches>', $trace['name']));
+ $output->success(sprintf('Route "%s" matches', $trace['name']));
- $routerDebugcommand = $this->getApplication()->find('debug:router');
- $output->writeln('');
- $routerDebugcommand->run(new ArrayInput(array('name' => $trace['name'])), $output);
+ $routerDebugCommand = $this->getApplication()->find('debug:router');
+ $routerDebugCommand->run(new ArrayInput(array('name' => $trace['name'])), $output);
$matches = true;
} elseif ($input->getOption('verbose')) {
- $output->writeln(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log']));
+ $output->text(sprintf('Route "%s" does not match: %s', $trace['name'], $trace['log']));
}
}
if (!$matches) {
- $output->writeln(sprintf('None of the routes match the path "%s">', $input->getArgument('path_info')));
+ $output->error(sprintf('None of the routes match the path "%s"', $input->getArgument('path_info')));
return 1;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php
index 6af52feaaec5..767a935286b0 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerRunCommand.php
@@ -15,6 +15,7 @@
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\ProcessBuilder;
@@ -44,7 +45,8 @@ protected function configure()
{
$this
->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
+ new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
+ new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
))
@@ -83,6 +85,8 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $stdout = $output;
+ $output = new SymfonyStyle($input, $output);
$documentRoot = $input->getOption('docroot');
if (null === $documentRoot) {
@@ -90,7 +94,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if (!is_dir($documentRoot)) {
- $output->writeln(sprintf('The given document root directory "%s" does not exist ', $documentRoot));
+ $output->error(sprintf('The given document root directory "%s" does not exist', $documentRoot));
return 1;
}
@@ -99,23 +103,21 @@ protected function execute(InputInterface $input, OutputInterface $output)
$address = $input->getArgument('address');
if (false === strpos($address, ':')) {
- $output->writeln('The address has to be of the form bind-address:port .');
-
- return 1;
+ $address = $address.':'.$input->getOption('port');
}
if ($this->isOtherServerProcessRunning($address)) {
- $output->writeln(sprintf('A process is already listening on http://%s. ', $address));
+ $output->error(sprintf('A process is already listening on http://%s.', $address));
return 1;
}
if ('prod' === $env) {
- $output->writeln('Running PHP built-in server in production environment is NOT recommended! ');
+ $output->error('Running PHP built-in server in production environment is NOT recommended!');
}
- $output->writeln(sprintf("Server running on http://%s \n", $address));
- $output->writeln('Quit the server with CONTROL-C.');
+ $output->success(sprintf('Server running on http://%s', $address));
+ $output->comment('Quit the server with CONTROL-C.');
if (null === $builder = $this->createPhpProcessBuilder($output, $address, $input->getOption('router'), $env)) {
return 1;
@@ -125,26 +127,28 @@ protected function execute(InputInterface $input, OutputInterface $output)
$builder->setTimeout(null);
$process = $builder->getProcess();
- if (OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) {
+ if (OutputInterface::VERBOSITY_VERBOSE > $stdout->getVerbosity()) {
$process->disableOutput();
}
$this
->getHelper('process')
- ->run($output, $process, null, null, OutputInterface::VERBOSITY_VERBOSE);
+ ->run($stdout, $process, null, null, OutputInterface::VERBOSITY_VERBOSE);
if (!$process->isSuccessful()) {
- $output->writeln('Built-in server terminated unexpectedly ');
+ $errorMessages = array('Built-in server terminated unexpectedly.');
if ($process->isOutputDisabled()) {
- $output->writeln('Run the command again with -v option for more details ');
+ $errorMessages[] = 'Run the command again with -v option for more details.';
}
+
+ $output->error($errorMessages);
}
return $process->getExitCode();
}
- private function createPhpProcessBuilder(OutputInterface $output, $address, $router, $env)
+ private function createPhpProcessBuilder(SymfonyStyle $output, $address, $router, $env)
{
$router = $router ?: $this
->getContainer()
@@ -153,7 +157,7 @@ private function createPhpProcessBuilder(OutputInterface $output, $address, $rou
;
if (!file_exists($router)) {
- $output->writeln(sprintf('The given router script "%s" does not exist ', $router));
+ $output->error(sprintf('The given router script "%s" does not exist.', $router));
return;
}
@@ -162,7 +166,7 @@ private function createPhpProcessBuilder(OutputInterface $output, $address, $rou
$finder = new PhpExecutableFinder();
if (false === $binary = $finder->find()) {
- $output->writeln('Unable to find PHP binary to run server ');
+ $output->error('Unable to find PHP binary to run server.');
return;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php
index 04906317fa94..309ede6d068d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStartCommand.php
@@ -11,11 +11,11 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
-use Symfony\Component\Console\Question\ConfirmationQuestion;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Process\PhpExecutableFinder;
use Symfony\Component\Process\Process;
@@ -33,9 +33,11 @@ protected function configure()
{
$this
->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
+ new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
+ new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
new InputOption('docroot', 'd', InputOption::VALUE_REQUIRED, 'Document root', null),
new InputOption('router', 'r', InputOption::VALUE_REQUIRED, 'Path to custom router script'),
+ new InputOption('force', 'f', InputOption::VALUE_NONE, 'Force web server startup'),
))
->setName('server:start')
->setDescription('Starts PHP built-in web server in the background')
@@ -72,11 +74,15 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
+
if (!extension_loaded('pcntl')) {
- $output->writeln('This command needs the pcntl extension to run. ');
- $output->writeln('You can either install it or use the server:run command instead to run the built-in web server.');
+ $output->error(array(
+ 'This command needs the pcntl extension to run.',
+ 'You can either install it or use the "server:run" command instead to run the built-in web server.',
+ ));
- if ($this->getHelper('question')->ask($input, $output, new ConfirmationQuestion('Do you want to start server:run immediately? [Yn] ', true))) {
+ if ($output->ask('Do you want to execute server:run immediately? [Yn] ', true)) {
$command = $this->getApplication()->find('server:run');
return $command->run($input, $output);
@@ -92,7 +98,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if (!is_dir($documentRoot)) {
- $output->writeln(sprintf('The given document root directory "%s" does not exist ', $documentRoot));
+ $output->error(sprintf('The given document root directory "%s" does not exist.', $documentRoot));
return 1;
}
@@ -106,37 +112,38 @@ protected function execute(InputInterface $input, OutputInterface $output)
$address = $input->getArgument('address');
if (false === strpos($address, ':')) {
- $output->writeln('The address has to be of the form bind-address:port .');
-
- return 1;
+ $address = $address.':'.$input->getOption('port');
}
- if ($this->isOtherServerProcessRunning($address)) {
- $output->writeln(sprintf('A process is already listening on http://%s. ', $address));
+ if (!$input->getOption('force') && $this->isOtherServerProcessRunning($address)) {
+ $output->error(array(
+ sprintf('A process is already listening on http://%s.', $address),
+ 'Use the --force option if the server process terminated unexpectedly to start a new web server process.',
+ ));
return 1;
}
if ('prod' === $env) {
- $output->writeln('Running PHP built-in server in production environment is NOT recommended! ');
+ $output->error('Running PHP built-in server in production environment is NOT recommended!');
}
$pid = pcntl_fork();
if ($pid < 0) {
- $output->writeln('Unable to start the server process ');
+ $output->error('Unable to start the server process.');
return 1;
}
if ($pid > 0) {
- $output->writeln(sprintf('Web server listening on http://%s ', $address));
+ $output->success(sprintf('Web server listening on http://%s', $address));
return;
}
if (posix_setsid() < 0) {
- $output->writeln('Unable to set the child process as session leader ');
+ $output->error('Unable to set the child process as session leader');
return 1;
}
@@ -151,7 +158,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
touch($lockFile);
if (!$process->isRunning()) {
- $output->writeln('Unable to start the server process ');
+ $output->error('Unable to start the server process');
unlink($lockFile);
return 1;
@@ -171,13 +178,13 @@ protected function execute(InputInterface $input, OutputInterface $output)
* Determine the absolute file path for the router script, using the environment to choose a standard script
* if no custom router script is specified.
*
- * @param string|null $router File path of the custom router script, if set by the user; otherwise null
- * @param string $env The application environment
- * @param OutputInterface $output An OutputInterface instance
+ * @param string|null $router File path of the custom router script, if set by the user; otherwise null
+ * @param string $env The application environment
+ * @param SymfonyStyle $output An SymfonyStyle instance
*
* @return string|bool The absolute file path of the router script, or false on failure
*/
- private function determineRouterScript($router, $env, OutputInterface $output)
+ private function determineRouterScript($router, $env, SymfonyStyle $output)
{
if (null === $router) {
$router = $this
@@ -188,7 +195,7 @@ private function determineRouterScript($router, $env, OutputInterface $output)
}
if (false === $path = realpath($router)) {
- $output->writeln(sprintf('The given router script "%s" does not exist ', $router));
+ $output->error(sprintf('The given router script "%s" does not exist.', $router));
return false;
}
@@ -199,18 +206,18 @@ private function determineRouterScript($router, $env, OutputInterface $output)
/**
* Creates a process to start PHP's built-in web server.
*
- * @param OutputInterface $output A OutputInterface instance
- * @param string $address IP address and port to listen to
- * @param string $documentRoot The application's document root
- * @param string $router The router filename
+ * @param SymfonyStyle $output A SymfonyStyle instance
+ * @param string $address IP address and port to listen to
+ * @param string $documentRoot The application's document root
+ * @param string $router The router filename
*
* @return Process The process
*/
- private function createServerProcess(OutputInterface $output, $address, $documentRoot, $router)
+ private function createServerProcess(SymfonyStyle $output, $address, $documentRoot, $router)
{
$finder = new PhpExecutableFinder();
if (false === $binary = $finder->find()) {
- $output->writeln('Unable to find PHP binary to start server ');
+ $output->error('Unable to find PHP binary to start server.');
return;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
index 2c6d2c49ff09..7b73fc9384c9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
@@ -14,6 +14,7 @@
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Shows the status of a process that is running PHP's built-in web server in
@@ -42,6 +43,7 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
$address = $input->getArgument('address');
// remove an orphaned lock file
@@ -50,9 +52,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
if (file_exists($this->getLockFile($address))) {
- $output->writeln(sprintf('Web server still listening on http://%s ', $address));
+ $output->success(sprintf('Web server still listening on http://%s', $address));
} else {
- $output->writeln(sprintf('No web server is listening on http://%s ', $address));
+ $output->warning(sprintf('No web server is listening on http://%s', $address));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php
index 9b0656c220b6..d2bdaa167d80 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStopCommand.php
@@ -14,6 +14,8 @@
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Style\SymfonyStyle;
/**
* Stops a background process running PHP's built-in web server.
@@ -29,7 +31,8 @@ protected function configure()
{
$this
->setDefinition(array(
- new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
+ new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1'),
+ new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
))
->setName('server:stop')
->setDescription('Stops PHP\'s built-in web server that was started with the server:start command')
@@ -52,16 +55,22 @@ protected function configure()
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
+ $output = new SymfonyStyle($input, $output);
+
$address = $input->getArgument('address');
+ if (false === strpos($address, ':')) {
+ $address = $address.':'.$input->getOption('port');
+ }
+
$lockFile = $this->getLockFile($address);
if (!file_exists($lockFile)) {
- $output->writeln(sprintf('No web server is listening on http://%s ', $address));
+ $output->error(sprintf('No web server is listening on http://%s', $address));
return 1;
}
unlink($lockFile);
- $output->writeln(sprintf('Stopped the web server listening on http://%s ', $address));
+ $output->success(sprintf('Stopped the web server listening on http://%s', $address));
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
index 30d44493d4c4..a9978bdec147 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php
@@ -11,12 +11,14 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
+use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader;
use Symfony\Component\Console\Style\SymfonyStyle;
-use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Console\Input\InputInterface;
-use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Translation\MessageCatalogue;
use Symfony\Component\Translation\Translator;
@@ -48,6 +50,7 @@ protected function configure()
new InputOption('domain', null, InputOption::VALUE_OPTIONAL, 'The messages domain'),
new InputOption('only-missing', null, InputOption::VALUE_NONE, 'Displays only missing messages'),
new InputOption('only-unused', null, InputOption::VALUE_NONE, 'Displays only unused messages'),
+ new InputOption('all', null, InputOption::VALUE_NONE, 'Load messages from all registered bundles'),
))
->setDescription('Displays translation messages information')
->setHelp(<<php %command.full_name% en
+You can display information about translations in all registered bundles in a specific locale:
+
+ php %command.full_name% --all en
+
EOF
)
;
@@ -92,7 +99,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
$locale = $input->getArgument('locale');
$domain = $input->getOption('domain');
+ /** @var TranslationLoader $loader */
$loader = $this->getContainer()->get('translation.loader');
+ /** @var Kernel $kernel */
$kernel = $this->getContainer()->get('kernel');
// Define Root Path to App folder
@@ -109,30 +118,23 @@ protected function execute(InputInterface $input, OutputInterface $output)
} catch (\InvalidArgumentException $e) {
// such a bundle does not exist, so treat the argument as path
$transPaths = array($input->getArgument('bundle').'/Resources/');
+
if (!is_dir($transPaths[0])) {
throw new \InvalidArgumentException(sprintf('"%s" is neither an enabled bundle nor a directory.', $transPaths[0]));
}
}
+ } elseif ($input->getOption('all')) {
+ foreach ($kernel->getBundles() as $bundle) {
+ $transPaths[] = $bundle->getPath().'/Resources/';
+ $transPaths[] = sprintf('%s/Resources/%s/', $kernel->getRootDir(), $bundle->getName());
+ }
}
// Extract used messages
- $extractedCatalogue = new MessageCatalogue($locale);
- foreach ($transPaths as $path) {
- $path .= 'views';
-
- if (is_dir($path)) {
- $this->getContainer()->get('translation.extractor')->extract($path, $extractedCatalogue);
- }
- }
+ $extractedCatalogue = $this->extractMessages($locale, $transPaths);
// Load defined messages
- $currentCatalogue = new MessageCatalogue($locale);
- foreach ($transPaths as $path) {
- $path .= 'translations';
- if (is_dir($path)) {
- $loader->loadMessages($path, $currentCatalogue);
- }
- }
+ $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths, $loader);
// Merge defined and extracted messages to get all message ids
$mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue);
@@ -155,24 +157,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
// Load the fallback catalogues
- $fallbackCatalogues = array();
- $translator = $this->getContainer()->get('translator');
- if ($translator instanceof Translator) {
- foreach ($translator->getFallbackLocales() as $fallbackLocale) {
- if ($fallbackLocale === $locale) {
- continue;
- }
-
- $fallbackCatalogue = new MessageCatalogue($fallbackLocale);
- foreach ($transPaths as $path) {
- $path = $path.'translations';
- if (is_dir($path)) {
- $loader->loadMessages($path, $fallbackCatalogue);
- }
- }
- $fallbackCatalogues[] = $fallbackCatalogue;
- }
- }
+ $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths, $loader);
// Display header line
$headers = array('State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale));
@@ -265,4 +250,74 @@ private function sanitizeString($string, $length = 40)
return $string;
}
+
+ /**
+ * @param string $locale
+ * @param array $transPaths
+ *
+ * @return MessageCatalogue
+ */
+ private function extractMessages($locale, $transPaths)
+ {
+ $extractedCatalogue = new MessageCatalogue($locale);
+ foreach ($transPaths as $path) {
+ $path = $path.'views';
+ if (is_dir($path)) {
+ $this->getContainer()->get('translation.extractor')->extract($path, $extractedCatalogue);
+ }
+ }
+
+ return $extractedCatalogue;
+ }
+
+ /**
+ * @param string $locale
+ * @param array $transPaths
+ * @param TranslationLoader $loader
+ *
+ * @return MessageCatalogue
+ */
+ private function loadCurrentMessages($locale, $transPaths, TranslationLoader $loader)
+ {
+ $currentCatalogue = new MessageCatalogue($locale);
+ foreach ($transPaths as $path) {
+ $path = $path.'translations';
+ if (is_dir($path)) {
+ $loader->loadMessages($path, $currentCatalogue);
+ }
+ }
+
+ return $currentCatalogue;
+ }
+
+ /**
+ * @param string $locale
+ * @param array $transPaths
+ * @param TranslationLoader $loader
+ *
+ * @return MessageCatalogue[]
+ */
+ private function loadFallbackCatalogues($locale, $transPaths, TranslationLoader $loader)
+ {
+ $fallbackCatalogues = array();
+ $translator = $this->getContainer()->get('translator');
+ if ($translator instanceof Translator) {
+ foreach ($translator->getFallbackLocales() as $fallbackLocale) {
+ if ($fallbackLocale === $locale) {
+ continue;
+ }
+
+ $fallbackCatalogue = new MessageCatalogue($fallbackLocale);
+ foreach ($transPaths as $path) {
+ $path = $path.'translations';
+ if (is_dir($path)) {
+ $loader->loadMessages($path, $fallbackCatalogue);
+ }
+ }
+ $fallbackCatalogues[] = $fallbackCatalogue;
+ }
+ }
+
+ return $fallbackCatalogues;
+ }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
index 64143f6e21a1..57634b0233cd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php
@@ -12,7 +12,7 @@
namespace Symfony\Bundle\FrameworkBundle\Command;
use Symfony\Component\Console\Style\SymfonyStyle;
-use Symfony\Component\Translation\Catalogue\DiffOperation;
+use Symfony\Component\Translation\Catalogue\TargetOperation;
use Symfony\Component\Translation\Catalogue\MergeOperation;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
@@ -139,7 +139,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
// process catalogues
$operation = $input->getOption('clean')
- ? new DiffOperation($currentCatalogue, $extractedCatalogue)
+ ? new TargetOperation($currentCatalogue, $extractedCatalogue)
: new MergeOperation($currentCatalogue, $extractedCatalogue);
// Exit if no messages found.
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
index d10db38f37fa..b727c2bd1c34 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php
@@ -86,6 +86,8 @@ public function doRun(InputInterface $input, OutputInterface $output)
$this->setDispatcher($container->get('event_dispatcher'));
if (true === $input->hasParameterOption(array('--shell', '-s'))) {
+ @trigger_error('The "--shell" option is deprecated since Symfony 2.8 and will be removed in 3.0.', E_USER_DEPRECATED);
+
$shell = new Shell($this);
$shell->setProcessIsolation($input->hasParameterOption(array('--process-isolation')));
$shell->run();
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
index f61af1cc959c..57780d2e52fd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php
@@ -213,12 +213,16 @@ private function getContainerDefinitionData(Definition $definition, $omitTags =
{
$data = array(
'class' => (string) $definition->getClass(),
- 'scope' => $definition->getScope(),
+ 'scope' => $definition->getScope(false),
'public' => $definition->isPublic(),
'synthetic' => $definition->isSynthetic(),
'lazy' => $definition->isLazy(),
);
+ if (method_exists($definition, 'isShared')) {
+ $data['shared'] = $definition->isShared();
+ }
+
if (method_exists($definition, 'isSynchronized')) {
$data['synchronized'] = $definition->isSynchronized(false);
}
@@ -290,17 +294,27 @@ private function getEventDispatcherListenersData(EventDispatcherInterface $event
{
$data = array();
- $registeredListeners = $eventDispatcher->getListeners($event);
+ $registeredListeners = $eventDispatcher->getListeners($event, true);
if (null !== $event) {
- foreach ($registeredListeners as $listener) {
- $data[] = $this->getCallableData($listener);
+ krsort($registeredListeners);
+ foreach ($registeredListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $listener = $this->getCallableData($listener);
+ $listener['priority'] = $priority;
+ $data[] = $listener;
+ }
}
} else {
ksort($registeredListeners);
foreach ($registeredListeners as $eventListened => $eventListeners) {
- foreach ($eventListeners as $eventListener) {
- $data[$eventListened][] = $this->getCallableData($eventListener);
+ krsort($eventListeners);
+ foreach ($eventListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $listener = $this->getCallableData($listener);
+ $listener['priority'] = $priority;
+ $data[$eventListened][] = $listener;
+ }
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
index 8f1227e7e997..8f5437146bb5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php
@@ -179,12 +179,16 @@ protected function describeContainerServices(ContainerBuilder $builder, array $o
protected function describeContainerDefinition(Definition $definition, array $options = array())
{
$output = '- Class: `'.$definition->getClass().'`'
- ."\n".'- Scope: `'.$definition->getScope().'`'
+ ."\n".'- Scope: `'.$definition->getScope(false).'`'
."\n".'- Public: '.($definition->isPublic() ? 'yes' : 'no')
."\n".'- Synthetic: '.($definition->isSynthetic() ? 'yes' : 'no')
."\n".'- Lazy: '.($definition->isLazy() ? 'yes' : 'no')
;
+ if (method_exists($definition, 'isShared')) {
+ $output .= "\n".'- Shared: '.($definition->isShared() ? 'yes' : 'no');
+ }
+
if (method_exists($definition, 'isSynchronized')) {
$output .= "\n".'- Synchronized: '.($definition->isSynchronized(false) ? 'yes' : 'no');
}
@@ -269,21 +273,30 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev
$this->write(sprintf('# %s', $title)."\n");
- $registeredListeners = $eventDispatcher->getListeners($event);
+ $registeredListeners = $eventDispatcher->getListeners($event, true);
if (null !== $event) {
- foreach ($registeredListeners as $order => $listener) {
- $this->write("\n".sprintf('## Listener %d', $order + 1)."\n");
- $this->describeCallable($listener);
+ krsort($registeredListeners);
+ $order = 1;
+ foreach ($registeredListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $this->write("\n".sprintf('## Listener %d', $order++)."\n");
+ $this->describeCallable($listener);
+ $this->write(sprintf('- Priority: `%d`', $priority)."\n");
+ }
}
} else {
ksort($registeredListeners);
foreach ($registeredListeners as $eventListened => $eventListeners) {
$this->write("\n".sprintf('## %s', $eventListened)."\n");
-
- foreach ($eventListeners as $order => $eventListener) {
- $this->write("\n".sprintf('### Listener %d', $order + 1)."\n");
- $this->describeCallable($eventListener);
+ krsort($eventListeners);
+ $order = 1;
+ foreach ($eventListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $this->write("\n".sprintf('### Listener %d', $order++)."\n");
+ $this->describeCallable($listener);
+ $this->write(sprintf('- Priority: `%d`', $priority)."\n");
+ }
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
index 22d0bde4d42e..c77598c82c63 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php
@@ -34,11 +34,13 @@ class TextDescriptor extends Descriptor
protected function describeRouteCollection(RouteCollection $routes, array $options = array())
{
$showControllers = isset($options['show_controllers']) && $options['show_controllers'];
- $headers = array('Name', 'Method', 'Scheme', 'Host', 'Path');
- $table = new Table($this->getOutput());
- $table->setStyle('compact');
- $table->setHeaders($showControllers ? array_merge($headers, array('Controller')) : $headers);
+ $tableHeaders = array('Name', 'Method', 'Scheme', 'Host', 'Path');
+ if ($showControllers) {
+ $tableHeaders[] = 'Controller';
+ }
+
+ $tableRows = array();
foreach ($routes->all() as $name => $route) {
$row = array(
$name,
@@ -58,11 +60,16 @@ protected function describeRouteCollection(RouteCollection $routes, array $optio
$row[] = $controller;
}
- $table->addRow($row);
+ $tableRows[] = $row;
}
- $this->writeText($this->formatSection('router', 'Current routes')."\n", $options);
- $table->render();
+ if (isset($options['output'])) {
+ $options['output']->table($tableHeaders, $tableRows);
+ } else {
+ $table = new Table($this->getOutput());
+ $table->setHeaders($tableHeaders)->setRows($tableRows);
+ $table->render();
+ }
}
/**
@@ -73,26 +80,24 @@ protected function describeRoute(Route $route, array $options = array())
$requirements = $route->getRequirements();
unset($requirements['_scheme'], $requirements['_method']);
- // fixme: values were originally written as raw
- $description = array(
- 'Path '.$route->getPath(),
- 'Path Regex '.$route->compile()->getRegex(),
- 'Host '.('' !== $route->getHost() ? $route->getHost() : 'ANY'),
- 'Host Regex '.('' !== $route->getHost() ? $route->compile()->getHostRegex() : ''),
- 'Scheme '.($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY'),
- 'Method '.($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY'),
- 'Class '.get_class($route),
- 'Defaults '.$this->formatRouterConfig($route->getDefaults()),
- 'Requirements '.($requirements ? $this->formatRouterConfig($requirements) : 'NO CUSTOM'),
- 'Options '.$this->formatRouterConfig($route->getOptions()),
+ $tableHeaders = array('Property', 'Value');
+ $tableRows = array(
+ array('Route Name', $options['name']),
+ array('Path', $route->getPath()),
+ array('Path Regex', $route->compile()->getRegex()),
+ array('Host', ('' !== $route->getHost() ? $route->getHost() : 'ANY')),
+ array('Host Regex', ('' !== $route->getHost() ? $route->compile()->getHostRegex() : '')),
+ array('Scheme', ($route->getSchemes() ? implode('|', $route->getSchemes()) : 'ANY')),
+ array('Method', ($route->getMethods() ? implode('|', $route->getMethods()) : 'ANY')),
+ array('Requirements', ($requirements ? $this->formatRouterConfig($requirements) : 'NO CUSTOM')),
+ array('Class', get_class($route)),
+ array('Defaults', $this->formatRouterConfig($route->getDefaults())),
+ array('Options', $this->formatRouterConfig($route->getOptions())),
);
- if (isset($options['name'])) {
- array_unshift($description, 'Name '.$options['name']);
- array_unshift($description, $this->formatSection('router', sprintf('Route "%s"', $options['name'])));
- }
-
- $this->writeText(implode("\n", $description)."\n", $options);
+ $table = new Table($this->getOutput());
+ $table->setHeaders($tableHeaders)->setRows($tableRows);
+ $table->render();
}
/**
@@ -261,10 +266,13 @@ protected function describeContainerDefinition(Definition $definition, array $op
$description[] = 'Tags -';
}
- $description[] = sprintf('Scope %s', $definition->getScope());
+ $description[] = sprintf('Scope %s', $definition->getScope(false));
$description[] = sprintf('Public %s', $definition->isPublic() ? 'yes' : 'no');
$description[] = sprintf('Synthetic %s', $definition->isSynthetic() ? 'yes' : 'no');
$description[] = sprintf('Lazy %s', $definition->isLazy() ? 'yes' : 'no');
+ if (method_exists($definition, 'isShared')) {
+ $description[] = sprintf('Shared %s', $definition->isShared() ? 'yes' : 'no');
+ }
if (method_exists($definition, 'isSynchronized')) {
$description[] = sprintf('Synchronized %s', $definition->isSynchronized(false) ? 'yes' : 'no');
}
@@ -336,33 +344,16 @@ protected function describeEventDispatcherListeners(EventDispatcherInterface $ev
$this->writeText($this->formatSection('event_dispatcher', $label)."\n", $options);
- $registeredListeners = $eventDispatcher->getListeners($event);
+ $registeredListeners = $eventDispatcher->getListeners($event, true);
if (null !== $event) {
$this->writeText("\n");
- $table = new Table($this->getOutput());
- $table->getStyle()->setCellHeaderFormat('%s');
- $table->setHeaders(array('Order', 'Callable'));
-
- foreach ($registeredListeners as $order => $listener) {
- $table->addRow(array(sprintf('#%d', $order + 1), $this->formatCallable($listener)));
- }
-
- $table->render();
+ $this->renderEventListenerTable($registeredListeners);
} else {
ksort($registeredListeners);
foreach ($registeredListeners as $eventListened => $eventListeners) {
$this->writeText(sprintf("\n[Event] %s\n", $eventListened), $options);
-
- $table = new Table($this->getOutput());
- $table->getStyle()->setCellHeaderFormat('%s');
- $table->setHeaders(array('Order', 'Callable'));
-
- foreach ($eventListeners as $order => $eventListener) {
- $table->addRow(array(sprintf('#%d', $order + 1), $this->formatCallable($eventListener)));
- }
-
- $table->render();
+ $this->renderEventListenerTable($eventListeners);
}
}
}
@@ -377,22 +368,43 @@ protected function describeCallable($callable, array $options = array())
/**
* @param array $array
+ */
+ private function renderEventListenerTable(array $eventListeners)
+ {
+ $table = new Table($this->getOutput());
+ $table->getStyle()->setCellHeaderFormat('%s');
+ $table->setHeaders(array('Order', 'Callable', 'Priority'));
+
+ krsort($eventListeners);
+ $order = 1;
+ foreach ($eventListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $table->addRow(array(sprintf('#%d', $order++), $this->formatCallable($listener), $priority));
+ }
+ }
+
+ $table->render();
+ }
+
+ /**
+ * @param array $config
*
* @return string
*/
- private function formatRouterConfig(array $array)
+ private function formatRouterConfig(array $config)
{
- if (!count($array)) {
+ if (empty($config)) {
return 'NONE';
}
- $string = '';
- ksort($array);
- foreach ($array as $name => $value) {
- $string .= ($string ? "\n".str_repeat(' ', 13) : '').$name.': '.$this->formatValue($value);
+ ksort($config);
+
+ $configAsString = '';
+ foreach ($config as $key => $value) {
+ $configAsString .= sprintf("\n%s: %s", $key, $this->formatValue($value));
}
- return $string;
+ return trim($configAsString);
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
index c37a9009fcff..cc83d6cd1f27 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php
@@ -362,10 +362,13 @@ private function getContainerDefinitionDocument(Definition $definition, $id = nu
}
}
- $serviceXML->setAttribute('scope', $definition->getScope());
+ $serviceXML->setAttribute('scope', $definition->getScope(false));
$serviceXML->setAttribute('public', $definition->isPublic() ? 'true' : 'false');
$serviceXML->setAttribute('synthetic', $definition->isSynthetic() ? 'true' : 'false');
$serviceXML->setAttribute('lazy', $definition->isLazy() ? 'true' : 'false');
+ if (method_exists($definition, 'isShared')) {
+ $serviceXML->setAttribute('shared', $definition->isShared() ? 'true' : 'false');
+ }
if (method_exists($definition, 'isSynchronized')) {
$serviceXML->setAttribute('synchronized', $definition->isSynchronized(false) ? 'true' : 'false');
}
@@ -446,13 +449,9 @@ private function getEventDispatcherListenersDocument(EventDispatcherInterface $e
$dom = new \DOMDocument('1.0', 'UTF-8');
$dom->appendChild($eventDispatcherXML = $dom->createElement('event-dispatcher'));
- $registeredListeners = $eventDispatcher->getListeners($event);
+ $registeredListeners = $eventDispatcher->getListeners($event, true);
if (null !== $event) {
- foreach ($registeredListeners as $listener) {
- $callableXML = $this->getCallableDocument($listener);
-
- $eventDispatcherXML->appendChild($eventDispatcherXML->ownerDocument->importNode($callableXML->childNodes->item(0), true));
- }
+ $this->appendEventListenerDocument($eventDispatcherXML, $registeredListeners);
} else {
ksort($registeredListeners);
@@ -460,17 +459,30 @@ private function getEventDispatcherListenersDocument(EventDispatcherInterface $e
$eventDispatcherXML->appendChild($eventXML = $dom->createElement('event'));
$eventXML->setAttribute('name', $eventListened);
- foreach ($eventListeners as $eventListener) {
- $callableXML = $this->getCallableDocument($eventListener);
-
- $eventXML->appendChild($eventXML->ownerDocument->importNode($callableXML->childNodes->item(0), true));
- }
+ $this->appendEventListenerDocument($eventXML, $eventListeners);
}
}
return $dom;
}
+ /**
+ * @param \DOMElement $element
+ * @param array $eventListeners
+ */
+ private function appendEventListenerDocument(\DOMElement $element, array $eventListeners)
+ {
+ krsort($eventListeners);
+ foreach ($eventListeners as $priority => $listeners) {
+ foreach ($listeners as $listener) {
+ $callableXML = $this->getCallableDocument($listener);
+ $callableXML->childNodes->item(0)->setAttribute('priority', $priority);
+
+ $element->appendChild($element->ownerDocument->importNode($callableXML->childNodes->item(0), true));
+ }
+ }
+ }
+
/**
* @param callable $callable
*
diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Shell.php b/src/Symfony/Bundle/FrameworkBundle/Console/Shell.php
index 80daebd4cd3b..8a1e407ed253 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Console/Shell.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Console/Shell.php
@@ -16,6 +16,8 @@
/**
* Shell.
*
+ * @deprecated since version 2.8, to be removed in 3.0.
+ *
* @author Fabien Potencier
*/
class Shell extends BaseShell
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
index ecdb73598c1b..b46838114b30 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php
@@ -159,7 +159,15 @@ protected function denyAccessUnlessGranted($attributes, $object = null, $message
*/
public function renderView($view, array $parameters = array())
{
- return $this->container->get('templating')->render($view, $parameters);
+ if ($this->container->has('templating')) {
+ return $this->container->get('templating')->render($view, $parameters);
+ }
+
+ if (!$this->container->has('twig')) {
+ throw new \LogicException('You can not use the "renderView" method if the Templating Component or the Twig Bundle are not available.');
+ }
+
+ return $this->container->get('twig')->render($view, $parameters);
}
/**
@@ -173,7 +181,21 @@ public function renderView($view, array $parameters = array())
*/
public function render($view, array $parameters = array(), Response $response = null)
{
- return $this->container->get('templating')->renderResponse($view, $parameters, $response);
+ if ($this->container->has('templating')) {
+ return $this->container->get('templating')->renderResponse($view, $parameters, $response);
+ }
+
+ if (!$this->container->has('twig')) {
+ throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.');
+ }
+
+ if (null === $response) {
+ $response = new Response();
+ }
+
+ $response->setContent($this->container->get('twig')->render($view, $parameters));
+
+ return $response;
}
/**
@@ -187,11 +209,21 @@ public function render($view, array $parameters = array(), Response $response =
*/
public function stream($view, array $parameters = array(), StreamedResponse $response = null)
{
- $templating = $this->container->get('templating');
-
- $callback = function () use ($templating, $view, $parameters) {
- $templating->stream($view, $parameters);
- };
+ if ($this->container->has('templating')) {
+ $templating = $this->container->get('templating');
+
+ $callback = function () use ($templating, $view, $parameters) {
+ $templating->stream($view, $parameters);
+ };
+ } elseif ($this->container->has('twig')) {
+ $twig = $this->container->get('twig');
+
+ $callback = function () use ($twig, $view, $parameters) {
+ $twig->display($view, $parameters);
+ };
+ } else {
+ throw new \LogicException('You can not use the "stream" method if the Templating Component or the Twig Bundle are not available.');
+ }
if (null === $response) {
return new StreamedResponse($callback);
@@ -260,7 +292,16 @@ public function createForm($type, $data = null, array $options = array())
*/
public function createFormBuilder($data = null, array $options = array())
{
- return $this->container->get('form.factory')->createBuilder('form', $data, $options);
+ if (method_exists('Symfony\Component\Form\AbstractType', 'getBlockPrefix')) {
+ $type = 'Symfony\Component\Form\Extension\Core\Type\FormType';
+ } else {
+ // not using the class name is deprecated since Symfony 2.8 and
+ // is only used for backwards compatibility with older versions
+ // of the Form component
+ $type = 'form';
+ }
+
+ return $this->container->get('form.factory')->createBuilder($type, $data, $options);
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php
new file mode 100644
index 000000000000..a8e1c549a2d6
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php
@@ -0,0 +1,45 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority.
+ *
+ * @author Matthias Pigulla
+ * @author Benjamin Klotz
+ */
+class ConfigCachePass implements CompilerPassInterface
+{
+ public function process(ContainerBuilder $container)
+ {
+ $resourceCheckers = array();
+
+ foreach ($container->findTaggedServiceIds('config_cache.resource_checker') as $id => $tags) {
+ $priority = isset($tags[0]['priority']) ? $tags[0]['priority'] : 0;
+ $resourceCheckers[$priority][] = new Reference($id);
+ }
+
+ if (empty($resourceCheckers)) {
+ return;
+ }
+
+ // sort by priority and flatten
+ krsort($resourceCheckers);
+ $resourceCheckers = call_user_func_array('array_merge', $resourceCheckers);
+
+ $container->getDefinition('config_cache_factory')->replaceArgument(0, $resourceCheckers);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
index 8b46b946e550..cc0c218e4941 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php
@@ -34,12 +34,18 @@ public function process(ContainerBuilder $container)
$types = array();
foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) {
- $alias = isset($tag[0]['alias'])
- ? $tag[0]['alias']
- : $serviceId;
+ // The following if-else block is deprecated and will be removed
+ // in Symfony 3.0
+ // Deprecation errors are triggered in the form registry
+ if (isset($tag[0]['alias'])) {
+ $types[$tag[0]['alias']] = $serviceId;
+ } else {
+ $types[$serviceId] = $serviceId;
+ }
- // Flip, because we want tag aliases (= type identifiers) as keys
- $types[$alias] = $serviceId;
+ // Support type access by FQCN
+ $serviceDefinition = $container->getDefinition($serviceId);
+ $types[$serviceDefinition->getClass()] = $serviceId;
}
$definition->replaceArgument(1, $types);
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
new file mode 100644
index 000000000000..ed852fd04194
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php
@@ -0,0 +1,87 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Find all service tags which are defined, but not used and yield a warning log message.
+ *
+ * @author Florian Pfitzer
+ */
+class UnusedTagsPass implements CompilerPassInterface
+{
+ private $whitelist = array(
+ 'console.command',
+ 'config_cache.resource_checker',
+ 'data_collector',
+ 'form.type',
+ 'form.type_extension',
+ 'form.type_guesser',
+ 'kernel.cache_clearer',
+ 'kernel.cache_warmer',
+ 'kernel.event_listener',
+ 'kernel.event_subscriber',
+ 'kernel.fragment_renderer',
+ 'monolog.logger',
+ 'routing.expression_language_provider',
+ 'routing.loader',
+ 'security.expression_language_provider',
+ 'security.remember_me_aware',
+ 'security.voter',
+ 'serializer.encoder',
+ 'serializer.normalizer',
+ 'templating.helper',
+ 'translation.dumper',
+ 'translation.extractor',
+ 'translation.loader',
+ 'twig.extension',
+ 'twig.loader',
+ 'validator.constraint_validator',
+ 'validator.initializer',
+ );
+
+ public function process(ContainerBuilder $container)
+ {
+ $compiler = $container->getCompiler();
+ $formatter = $compiler->getLoggingFormatter();
+ $tags = array_unique(array_merge($container->findTags(), $this->whitelist));
+
+ foreach ($container->findUnusedTags() as $tag) {
+ // skip whitelisted tags
+ if (in_array($tag, $this->whitelist)) {
+ continue;
+ }
+
+ // check for typos
+ $candidates = array();
+ foreach ($tags as $definedTag) {
+ if ($definedTag === $tag) {
+ continue;
+ }
+
+ if (false !== strpos($definedTag, $tag) || levenshtein($tag, $definedTag) <= strlen($tag) / 3) {
+ $candidates[] = $definedTag;
+ }
+ }
+
+ $services = array_keys($container->findTaggedServiceIds($tag));
+ $message = sprintf('Tag "%s" was defined on service(s) "%s", but was never used.', $tag, implode('", "', $services));
+ if (!empty($candidates)) {
+ $message .= sprintf(' Did you mean "%s"?', implode('", "', $candidates));
+ }
+
+ $compiler->addLogMessage($formatter->format($this, $message));
+ }
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
index c14399c0c650..023276e476b9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php
@@ -340,7 +340,8 @@ private function addSessionSection(ArrayNodeDefinition $rootNode)
->scalarNode('cookie_path')->end()
->scalarNode('cookie_domain')->end()
->booleanNode('cookie_secure')->end()
- ->booleanNode('cookie_httponly')->end()
+ ->booleanNode('cookie_httponly')->defaultTrue()->end()
+ ->booleanNode('use_cookies')->end()
->scalarNode('gc_divisor')->end()
->scalarNode('gc_probability')->defaultValue(1)->end()
->scalarNode('gc_maxlifetime')->end()
@@ -575,6 +576,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode)
->info('translator configuration')
->canBeEnabled()
->fixXmlConfig('fallback')
+ ->fixXmlConfig('path')
->children()
->arrayNode('fallbacks')
->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end()
@@ -582,6 +584,9 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode)
->defaultValue(array('en'))
->end()
->booleanNode('logging')->defaultValue($this->debug)->end()
+ ->arrayNode('paths')
+ ->prototype('scalar')->end()
+ ->end()
->end()
->end()
->end()
@@ -656,6 +661,7 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode)
->children()
->booleanNode('enable_annotations')->defaultFalse()->end()
->scalarNode('cache')->end()
+ ->scalarNode('name_converter')->end()
->end()
->end()
->end()
diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
index 08a7b12de4eb..1ccb2188d757 100644
--- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
+++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php
@@ -396,7 +396,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c
// session storage
$container->setAlias('session.storage', $config['storage_id']);
$options = array();
- foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
+ foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) {
if (isset($config[$key])) {
$options[$key] = $config[$key];
}
@@ -695,6 +695,13 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
$dirs[] = $dir;
}
}
+ foreach ($config['paths'] as $dir) {
+ if (is_dir($dir)) {
+ $dirs[] = $dir;
+ } else {
+ throw new \UnexpectedValueException(sprintf('%s defined in translator.paths does not exist or is not a directory', $dir));
+ }
+ }
if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/translations')) {
$dirs[] = $dir;
}
@@ -966,6 +973,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
1, new Reference($config['cache'])
);
}
+
+ if (isset($config['name_converter']) && $config['name_converter']) {
+ $container->getDefinition('serializer.normalizer.object')->replaceArgument(1, new Reference($config['name_converter']));
+ }
}
/**
diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
index 499f39c6c95c..3a96f71e1176 100644
--- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
+++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php
@@ -28,6 +28,8 @@
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass;
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass;
use Symfony\Component\Debug\ErrorHandler;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\PassConfig;
@@ -90,8 +92,10 @@ public function build(ContainerBuilder $container)
$container->addCompilerPass(new SerializerPass());
if ($container->getParameter('kernel.debug')) {
+ $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
$container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING);
+ $container->addCompilerPass(new ConfigCachePass());
}
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
index 3e049c0f2ceb..01a271797ae9 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml
@@ -17,17 +17,17 @@
-
+
-
+
-
+
@@ -46,13 +46,13 @@
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
index 7d1a588fbad3..57611435ebc4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml
@@ -115,6 +115,9 @@
+
+
+
@@ -152,7 +155,7 @@
-
+
@@ -166,14 +169,14 @@
-
+
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
index f20552ed1822..a78a125940aa 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml
@@ -10,7 +10,7 @@
-
+
%form.type_extension.csrf.enabled%
%form.type_extension.csrf.field_name%
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
index 1e8e3c89834d..ddf0a4e32cfe 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml
@@ -21,7 +21,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
index d3687da13a5d..bb484b26a45d 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
@@ -16,8 +16,8 @@
- %kernel.debug%
+ %kernel.debug%
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml
index cee86b3b72cf..167deb02fb8f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml
@@ -26,10 +26,10 @@
+
%profiler_listener.only_exceptions%
%profiler_listener.only_master_requests%
-
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
index 6b2f7c968869..a750027406ec 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -45,6 +45,11 @@
+
+
+
+
+
@@ -70,6 +75,9 @@
+
+
+
@@ -92,9 +100,9 @@
+
-
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
index fa7aa2b2bd80..4190dad7cb78 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/schema/symfony-1.0.xsd
@@ -107,6 +107,7 @@
+
@@ -183,6 +184,7 @@
+
@@ -216,5 +218,6 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
index e5b53e94938e..db5cdb8a54c8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml
@@ -22,7 +22,7 @@
- null
+ null
@@ -55,5 +55,8 @@
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
index 2021505726fe..f0d54b0d76a4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
@@ -63,5 +63,21 @@
%kernel.secret%
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
index 4e609a06e5d9..428ba0c8ee48 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml
@@ -13,16 +13,16 @@
-
+
%test.client.parameters%
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
index 0007a360c6e4..ff4c18f212f2 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml
@@ -45,6 +45,9 @@
%kernel.debug%
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
index ccfd44e5ca48..c0bf73a94e98 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml
@@ -39,6 +39,16 @@
%validator.mapping.cache.prefix%
+
+
+
+
+ %validator.mapping.cache.prefix%
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
index 9b2f3cb3a437..b7a77671c58e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
@@ -36,9 +36,9 @@
+
%kernel.default_locale%
-
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/range_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/range_widget.html.php
new file mode 100644
index 000000000000..4c628f8e005b
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/range_widget.html.php
@@ -0,0 +1 @@
+block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'range'));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
index 14e65a7991c5..ac5a481d0b55 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/widget_attributes.html.php
@@ -1,12 +1,11 @@
-id="escape($id) ?>" name="escape($full_name) ?>" readonly="readonly"
-disabled="disabled"
-required="required"
+id="escape($id) ?>" name="escape($full_name) ?>" disabled="disabled"
+ required="required"
$v): ?>
-escape($k), $view->escape($view['translator']->trans($v, array(), $translation_domain))) ?>
+escape($k), $view->escape($view['translator']->trans($v, array(), $translation_domain))) ?>
-escape($k), $view->escape($k)) ?>
+escape($k), $view->escape($k)) ?>
-escape($k), $view->escape($v)) ?>
+escape($k), $view->escape($v)) ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
index 501355beff6f..9830897914a3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php
@@ -14,7 +14,7 @@
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Bundle\FrameworkBundle\Tests\Command\CacheClearCommand\Fixture\TestAppKernel;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;
-use Symfony\Component\Config\ConfigCache;
+use Symfony\Component\Config\ConfigCacheFactory;
use Symfony\Component\Config\Resource\ResourceInterface;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
@@ -56,15 +56,13 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup()
$metaFiles = $finder->files()->in($this->kernel->getCacheDir())->name('*.php.meta');
// simply check that cache is warmed up
$this->assertGreaterThanOrEqual(1, count($metaFiles));
+ $configCacheFactory = new ConfigCacheFactory(true);
+ $that = $this;
+
foreach ($metaFiles as $file) {
- $configCache = new ConfigCache(substr($file, 0, -5), true);
- $this->assertTrue(
- $configCache->isFresh(),
- sprintf(
- 'Meta file "%s" is not fresh',
- (string) $file
- )
- );
+ $configCacheFactory->cache(substr($file, 0, -5), function () use ($that, $file) {
+ $that->fail(sprintf('Meta file "%s" is not fresh', (string) $file));
+ });
}
// check that app kernel file present in meta file of container's cache
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
index 8a9800bc865b..38dda10ba7d7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/AbstractDescriptorTest.php
@@ -75,6 +75,9 @@ public function testLegacyDescribeSynchronizedServiceDefinition(Definition $defi
$this->assertDescription($expectedDescription, $definition);
}
+ /**
+ * @group legacy
+ */
public function provideLegacySynchronizedServiceDefinitionTestData()
{
return $this->getDescriptionTestData(ObjectsProvider::getLegacyContainerDefinitions());
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
index df3f338fbb31..e0d707162ccb 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php
@@ -158,8 +158,8 @@ public static function getEventDispatchers()
{
$eventDispatcher = new EventDispatcher();
- $eventDispatcher->addListener('event1', 'global_function');
- $eventDispatcher->addListener('event1', function () { return 'Closure'; });
+ $eventDispatcher->addListener('event1', 'global_function', 255);
+ $eventDispatcher->addListener('event1', function () { return 'Closure'; }, -1);
$eventDispatcher->addListener('event2', new CallableClass());
return array('event_dispatcher_1' => $eventDispatcher);
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php
new file mode 100644
index 000000000000..c0eef3d627ce
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php
@@ -0,0 +1,68 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass;
+
+class ConfigCachePassTest extends \PHPUnit_Framework_TestCase
+{
+ public function testThatCheckersAreProcessedInPriorityOrder()
+ {
+ $services = array(
+ 'checker_2' => array(0 => array('priority' => 100)),
+ 'checker_1' => array(0 => array('priority' => 200)),
+ 'checker_3' => array(),
+ );
+
+ $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
+ $container = $this->getMock(
+ 'Symfony\Component\DependencyInjection\ContainerBuilder',
+ array('findTaggedServiceIds', 'getDefinition', 'hasDefinition')
+ );
+
+ $container->expects($this->atLeastOnce())
+ ->method('findTaggedServiceIds')
+ ->will($this->returnValue($services));
+ $container->expects($this->atLeastOnce())
+ ->method('getDefinition')
+ ->with('config_cache_factory')
+ ->will($this->returnValue($definition));
+
+ $definition->expects($this->once())
+ ->method('replaceArgument')
+ ->with(0, array(
+ new Reference('checker_1'),
+ new Reference('checker_2'),
+ new Reference('checker_3'),
+ ));
+
+ $pass = new ConfigCachePass();
+ $pass->process($container);
+ }
+
+ public function testThatCheckersCanBeMissing()
+ {
+ $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition');
+ $container = $this->getMock(
+ 'Symfony\Component\DependencyInjection\ContainerBuilder',
+ array('findTaggedServiceIds')
+ );
+
+ $container->expects($this->atLeastOnce())
+ ->method('findTaggedServiceIds')
+ ->will($this->returnValue(array()));
+
+ $pass = new ConfigCachePass();
+ $pass->process($container);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
new file mode 100644
index 000000000000..d7dc9d8a347d
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php
@@ -0,0 +1,184 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\Form\AbstractType;
+
+/**
+ * @author Bernhard Schussek
+ */
+class FormPassTest extends \PHPUnit_Framework_TestCase
+{
+ public function testDoNothingIfFormExtensionNotLoaded()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new FormPass());
+
+ $container->compile();
+
+ $this->assertFalse($container->hasDefinition('form.extension'));
+ }
+
+ public function testAddTaggedTypes()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new FormPass());
+
+ $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
+ $extDefinition->setArguments(array(
+ new Reference('service_container'),
+ array(),
+ array(),
+ array(),
+ ));
+
+ $definition1 = new Definition(__CLASS__.'_Type1');
+ $definition1->addTag('form.type');
+ $definition2 = new Definition(__CLASS__.'_Type2');
+ $definition2->addTag('form.type');
+
+ $container->setDefinition('form.extension', $extDefinition);
+ $container->setDefinition('my.type1', $definition1);
+ $container->setDefinition('my.type2', $definition2);
+
+ $container->compile();
+
+ $extDefinition = $container->getDefinition('form.extension');
+
+ $this->assertEquals(array(
+ // As of Symfony 2.8, the class is used to look up types
+ __CLASS__.'_Type1' => 'my.type1',
+ __CLASS__.'_Type2' => 'my.type2',
+ // Before Symfony 2.8, the service ID was used as default alias
+ 'my.type1' => 'my.type1',
+ 'my.type2' => 'my.type2',
+ ), $extDefinition->getArgument(1));
+ }
+
+ public function testUseCustomAliasIfSet()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new FormPass());
+
+ $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
+ $extDefinition->setArguments(array(
+ new Reference('service_container'),
+ array(),
+ array(),
+ array(),
+ ));
+
+ $definition1 = new Definition(__CLASS__.'_Type1');
+ $definition1->addTag('form.type', array('alias' => 'mytype1'));
+ $definition2 = new Definition(__CLASS__.'_Type2');
+ $definition2->addTag('form.type', array('alias' => 'mytype2'));
+
+ $container->setDefinition('form.extension', $extDefinition);
+ $container->setDefinition('my.type1', $definition1);
+ $container->setDefinition('my.type2', $definition2);
+
+ $container->compile();
+
+ $extDefinition = $container->getDefinition('form.extension');
+
+ $this->assertEquals(array(
+ __CLASS__.'_Type1' => 'my.type1',
+ __CLASS__.'_Type2' => 'my.type2',
+ 'mytype1' => 'my.type1',
+ 'mytype2' => 'my.type2',
+ ), $extDefinition->getArgument(1));
+ }
+
+ public function testAddTaggedTypeExtensions()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new FormPass());
+
+ $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
+ $extDefinition->setArguments(array(
+ new Reference('service_container'),
+ array(),
+ array(),
+ array(),
+ ));
+
+ $definition1 = new Definition('stdClass');
+ $definition1->addTag('form.type_extension', array('alias' => 'type1'));
+ $definition2 = new Definition('stdClass');
+ $definition2->addTag('form.type_extension', array('alias' => 'type1'));
+ $definition3 = new Definition('stdClass');
+ $definition3->addTag('form.type_extension', array('alias' => 'type2'));
+
+ $container->setDefinition('form.extension', $extDefinition);
+ $container->setDefinition('my.type_extension1', $definition1);
+ $container->setDefinition('my.type_extension2', $definition2);
+ $container->setDefinition('my.type_extension3', $definition3);
+
+ $container->compile();
+
+ $extDefinition = $container->getDefinition('form.extension');
+
+ $this->assertSame(array(
+ 'type1' => array(
+ 'my.type_extension1',
+ 'my.type_extension2',
+ ),
+ 'type2' => array(
+ 'my.type_extension3',
+ ),
+ ), $extDefinition->getArgument(2));
+ }
+
+ public function testAddTaggedGuessers()
+ {
+ $container = new ContainerBuilder();
+ $container->addCompilerPass(new FormPass());
+
+ $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension');
+ $extDefinition->setArguments(array(
+ new Reference('service_container'),
+ array(),
+ array(),
+ array(),
+ ));
+
+ $definition1 = new Definition('stdClass');
+ $definition1->addTag('form.type_guesser');
+ $definition2 = new Definition('stdClass');
+ $definition2->addTag('form.type_guesser');
+
+ $container->setDefinition('form.extension', $extDefinition);
+ $container->setDefinition('my.guesser1', $definition1);
+ $container->setDefinition('my.guesser2', $definition2);
+
+ $container->compile();
+
+ $extDefinition = $container->getDefinition('form.extension');
+
+ $this->assertSame(array(
+ 'my.guesser1',
+ 'my.guesser2',
+ ), $extDefinition->getArgument(3));
+ }
+}
+
+class FormPassTest_Type1 extends AbstractType
+{
+}
+
+class FormPassTest_Type2 extends AbstractType
+{
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php
new file mode 100644
index 000000000000..f354007bb982
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/UnusedTagsPassTest.php
@@ -0,0 +1,52 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
+
+use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass;
+
+class UnusedTagsPassTest extends \PHPUnit_Framework_TestCase
+{
+ public function testProcess()
+ {
+ $pass = new UnusedTagsPass();
+
+ $formatter = $this->getMock('Symfony\Component\DependencyInjection\Compiler\LoggingFormatter');
+ $formatter
+ ->expects($this->at(0))
+ ->method('format')
+ ->with($pass, 'Tag "kenrel.event_subscriber" was defined on service(s) "foo", "bar", but was never used. Did you mean "kernel.event_subscriber"?')
+ ;
+
+ $compiler = $this->getMock('Symfony\Component\DependencyInjection\Compiler\Compiler');
+ $compiler->expects($this->once())->method('getLoggingFormatter')->will($this->returnValue($formatter));
+
+ $container = $this->getMock('Symfony\Component\DependencyInjection\ContainerBuilder',
+ array('findTaggedServiceIds', 'getCompiler', 'findUnusedTags', 'findTags')
+ );
+ $container->expects($this->once())->method('getCompiler')->will($this->returnValue($compiler));
+ $container->expects($this->once())
+ ->method('findTags')
+ ->will($this->returnValue(array('kenrel.event_subscriber')));
+ $container->expects($this->once())
+ ->method('findUnusedTags')
+ ->will($this->returnValue(array('kenrel.event_subscriber', 'form.type')));
+ $container->expects($this->once())
+ ->method('findTaggedServiceIds')
+ ->with('kenrel.event_subscriber')
+ ->will($this->returnValue(array(
+ 'foo' => array(),
+ 'bar' => array(),
+ )));
+
+ $pass->process($container);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
index f8bb4cb2fc73..04b6c95b46da 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php
@@ -157,6 +157,7 @@ protected static function getBundleDefaultConfig()
'enabled' => false,
'fallbacks' => array('en'),
'logging' => true,
+ 'paths' => array(),
),
'validation' => array(
'enabled' => false,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
index 5022aeaf9f20..7c135dfc352f 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php
@@ -32,7 +32,8 @@
'cookie_path' => '/',
'cookie_domain' => 'example.com',
'cookie_secure' => true,
- 'cookie_httponly' => true,
+ 'cookie_httponly' => false,
+ 'use_cookies' => true,
'gc_maxlifetime' => 90000,
'gc_divisor' => 108,
'gc_probability' => 1,
@@ -50,6 +51,7 @@
'translator' => array(
'enabled' => true,
'fallback' => 'fr',
+ 'paths' => array('%kernel.root_dir%/Fixtures/translations'),
),
'validation' => array(
'enabled' => true,
@@ -60,7 +62,12 @@
'debug' => true,
'file_cache_dir' => '%kernel.cache_dir%/annotations',
),
- 'serializer' => array('enabled' => true),
+ 'serializer' => array(
+ 'enabled' => true,
+ 'enable_annotations' => true,
+ 'cache' => 'serializer.mapping.cache.apc',
+ 'name_converter' => 'serializer.name_converter.camel_case_to_snake_case',
+ ),
'ide' => 'file%%link%%format',
'request' => array(
'formats' => array(
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php
new file mode 100644
index 000000000000..dedd090beb77
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_disabled.php
@@ -0,0 +1,7 @@
+loadFromExtension('framework', array(
+ 'serializer' => array(
+ 'enabled' => false,
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php
new file mode 100644
index 000000000000..eadad57ec718
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/serializer_enabled.php
@@ -0,0 +1,7 @@
+loadFromExtension('framework', array(
+ 'serializer' => array(
+ 'enabled' => true,
+ ),
+));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/translations/test_paths.en.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/translations/test_paths.en.yml
new file mode 100644
index 000000000000..d4e682c47c9c
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/translations/test_paths.en.yml
@@ -0,0 +1,2 @@
+custom:
+ paths: test
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
index 5b16a5979609..b94f44762fda 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml
@@ -14,7 +14,7 @@
-
+
text/csv
@@ -34,9 +34,11 @@
theme2
-
+
+ %kernel.root_dir%/Fixtures/translations
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml
new file mode 100644
index 000000000000..73f1dccb1a6e
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_disabled.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml
new file mode 100644
index 000000000000..e202fc1b5ee2
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/serializer_enabled.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
index be1b41e25f89..13ceca12a4f1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml
@@ -24,7 +24,8 @@ framework:
cookie_path: /
cookie_domain: example.com
cookie_secure: true
- cookie_httponly: true
+ cookie_httponly: false
+ use_cookies: true
gc_probability: 1
gc_divisor: 108
gc_maxlifetime: 90000
@@ -39,6 +40,7 @@ framework:
translator:
enabled: true
fallback: fr
+ paths: ['%kernel.root_dir%/Fixtures/translations']
validation:
enabled: true
cache: apc
@@ -46,7 +48,11 @@ framework:
cache: file
debug: true
file_cache_dir: %kernel.cache_dir%/annotations
- serializer: { enabled: true }
+ serializer:
+ enabled: true
+ enable_annotations: true
+ cache: serializer.mapping.cache.apc
+ name_converter: serializer.name_converter.camel_case_to_snake_case
ide: file%%link%%format
request:
formats:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml
new file mode 100644
index 000000000000..330e19a6976e
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_disabled.yml
@@ -0,0 +1,3 @@
+framework:
+ serializer:
+ enabled: false
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml
new file mode 100644
index 000000000000..40a1ff7d65b3
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/serializer_enabled.yml
@@ -0,0 +1,3 @@
+framework:
+ serializer:
+ enabled: true
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
index db8c8cd689f3..ad0c427100dd 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php
@@ -149,7 +149,8 @@ public function testSession()
$this->assertEquals('/', $options['cookie_path']);
$this->assertEquals('example.com', $options['cookie_domain']);
$this->assertTrue($options['cookie_secure']);
- $this->assertTrue($options['cookie_httponly']);
+ $this->assertFalse($options['cookie_httponly']);
+ $this->assertTrue($options['use_cookies']);
$this->assertEquals(108, $options['gc_divisor']);
$this->assertEquals(1, $options['gc_probability']);
$this->assertEquals(90000, $options['gc_maxlifetime']);
@@ -242,9 +243,14 @@ public function testTranslator()
$files,
'->registerTranslatorConfiguration() finds Security translation resources'
);
+ $this->assertContains(
+ strtr(__DIR__.'/Fixtures/translations/test_paths.en.yml', '/', DIRECTORY_SEPARATOR),
+ $files,
+ '->registerTranslatorConfiguration() finds translation resources in custom paths'
+ );
$calls = $container->getDefinition('translator.default')->getMethodCalls();
- $this->assertEquals(array('fr'), $calls[0][1][0]);
+ $this->assertEquals(array('fr'), $calls[1][1][0]);
}
public function testTranslatorMultipleFallbacks()
@@ -252,7 +258,7 @@ public function testTranslatorMultipleFallbacks()
$container = $this->createContainerFromFile('translator_fallbacks');
$calls = $container->getDefinition('translator.default')->getMethodCalls();
- $this->assertEquals(array('en', 'fr'), $calls[0][1][0]);
+ $this->assertEquals(array('en', 'fr'), $calls[1][1][0]);
}
/**
@@ -441,6 +447,13 @@ public function testSerializerEnabled()
{
$container = $this->createContainerFromFile('full');
$this->assertTrue($container->has('serializer'));
+
+ $argument = $container->getDefinition('serializer.mapping.chain_loader')->getArgument(0);
+
+ $this->assertCount(1, $argument);
+ $this->assertEquals('Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader', $argument[0]->getClass());
+ $this->assertEquals(new Reference('serializer.mapping.cache.apc'), $container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1));
+ $this->assertEquals(new Reference('serializer.name_converter.camel_case_to_snake_case'), $container->getDefinition('serializer.normalizer.object')->getArgument(1));
}
public function testAssetHelperWhenAssetsAreEnabled()
@@ -459,6 +472,20 @@ public function testAssetHelperWhenTemplatesAreEnabledAndAssetsAreDisabled()
$this->assertSame('assets.packages', (string) $packages);
}
+ public function testSerializerServiceIsRegisteredWhenEnabled()
+ {
+ $container = $this->createContainerFromFile('serializer_enabled');
+
+ $this->assertTrue($container->hasDefinition('serializer'));
+ }
+
+ public function testSerializerServiceIsNotRegisteredWhenDisabled()
+ {
+ $container = $this->createContainerFromFile('serializer_disabled');
+
+ $this->assertFalse($container->hasDefinition('serializer'));
+ }
+
protected function createContainer(array $data = array())
{
return new ContainerBuilder(new ParameterBag(array_merge(array(
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
index 047f4e8c16a4..9be35dad0705 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.json
@@ -6,6 +6,7 @@
"public": true,
"synthetic": false,
"lazy": true,
+ "shared": true,
"synchronized": false,
"abstract": true,
"file": null,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
index 1c3b958bd92c..de404d24d0f5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.md
@@ -12,6 +12,7 @@ definition_1
- Public: yes
- Synthetic: no
- Lazy: yes
+- Shared: yes
- Synchronized: no
- Abstract: yes
- Factory Class: `Full\Qualified\FactoryClass`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
index b21190dc7983..59a1e85c6bb8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_public.xml
@@ -2,7 +2,7 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
index 3397fd67acd6..c76d13ee4234 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.json
@@ -6,6 +6,7 @@
"public": true,
"synthetic": false,
"lazy": true,
+ "shared": true,
"synchronized": false,
"abstract": true,
"file": null,
@@ -21,6 +22,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
index b3018b80b7f3..3a3de41c409e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.md
@@ -12,6 +12,7 @@ definition_1
- Public: yes
- Synthetic: no
- Lazy: yes
+- Shared: yes
- Synchronized: no
- Abstract: yes
- Factory Class: `Full\Qualified\FactoryClass`
@@ -25,6 +26,7 @@ definition_2
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
index 7aecc4f629e7..5ceee2772a99 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_services.xml
@@ -2,10 +2,10 @@
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
index 53bf114e81e0..40a3da00963a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.json
@@ -6,6 +6,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
index 56a2c390779a..c0d4f11e3326 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.md
@@ -12,6 +12,7 @@ definition_2
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
index d6ac0b750b16..51bb9c254f54 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tag1.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
index 3837b95cb89e..6844d2d18076 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.json
@@ -6,6 +6,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
@@ -20,6 +21,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
index 6577037f9c00..551c9cb24b29 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.md
@@ -12,6 +12,7 @@ definition_2
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
@@ -30,6 +31,7 @@ definition_2
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
index be9d2f015bd2..01f324860885 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_tags.xml
@@ -1,12 +1,12 @@
-
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
index 8de781dfc45a..92f1300b4bd5 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.json
@@ -4,6 +4,7 @@
"public": true,
"synthetic": false,
"lazy": true,
+ "shared": true,
"synchronized": false,
"abstract": true,
"file": null,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
index 68d3569732c6..6c18a6c2bbf8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.md
@@ -3,6 +3,7 @@
- Public: yes
- Synthetic: no
- Lazy: yes
+- Shared: yes
- Synchronized: no
- Abstract: yes
- Factory Class: `Full\Qualified\FactoryClass`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
index af495497dd35..4c37faccf29a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.txt
@@ -5,6 +5,7 @@
Public yes
Synthetic no
Lazy yes
+Shared yes
Synchronized no
Abstract yes
Factory Class Full\Qualified\FactoryClass
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
index 92a9bbd70bd3..ec8a8cefa9e4 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_1.xml
@@ -1,4 +1,4 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
index 9d58434c17e1..22a094928a48 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.json
@@ -4,6 +4,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
index 6b2f14651d30..866858799427 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.md
@@ -3,6 +3,7 @@
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
index 28a00d583b09..62fc7d2dc6c3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.txt
@@ -8,6 +8,7 @@
Public no
Synthetic yes
Lazy no
+Shared yes
Synchronized no
Abstract no
Required File /path/to/file
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
index f128e522e599..ce9b1d05220c 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_2.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.json
index e40e130d453c..4b68f0cefc0e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.json
@@ -1,9 +1,11 @@
[
{
"type": "function",
- "name": "global_function"
+ "name": "global_function",
+ "priority": 255
},
{
- "type": "closure"
+ "type": "closure",
+ "priority": -1
}
]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.md
index 206c44f71752..98b81ecdce42 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.md
@@ -4,7 +4,9 @@
- Type: `function`
- Name: `global_function`
+- Priority: `255`
## Listener 2
- Type: `closure`
+- Priority: `-1`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.txt
index 22b17a19cfb9..45035d12d622 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.txt
@@ -1,8 +1,8 @@
[event_dispatcher] Registered listeners for event event1
-+-------+-------------------+
-| Order | Callable |
-+-------+-------------------+
-| #1 | global_function() |
-| #2 | \Closure() |
-+-------+-------------------+
++-------+-------------------+----------+
+| Order | Callable | Priority |
++-------+-------------------+----------+
+| #1 | global_function() | 255 |
+| #2 | \Closure() | -1 |
++-------+-------------------+----------+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.xml
index 4806f1f1280c..bc03189af7b8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_event1.xml
@@ -1,5 +1,5 @@
-
-
+
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.json
index 56fc7a4f1e54..30772d9a4a21 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.json
@@ -2,16 +2,19 @@
"event1": [
{
"type": "function",
- "name": "global_function"
+ "name": "global_function",
+ "priority": 255
},
{
- "type": "closure"
+ "type": "closure",
+ "priority": -1
}
],
"event2": [
{
"type": "object",
- "name": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass"
+ "name": "Symfony\\Bundle\\FrameworkBundle\\Tests\\Console\\Descriptor\\CallableClass",
+ "priority": 0
}
]
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.md
index ad4b79e3117f..eb809789d5f1 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.md
@@ -6,10 +6,12 @@
- Type: `function`
- Name: `global_function`
+- Priority: `255`
### Listener 2
- Type: `closure`
+- Priority: `-1`
## event2
@@ -17,3 +19,4 @@
- Type: `object`
- Name: `Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\CallableClass`
+- Priority: `0`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.txt
index 95a5b4648e93..88e5dc9c8969 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.txt
@@ -1,16 +1,16 @@
[event_dispatcher] Registered listeners by event
[Event] event1
-+-------+-------------------+
-| Order | Callable |
-+-------+-------------------+
-| #1 | global_function() |
-| #2 | \Closure() |
-+-------+-------------------+
++-------+-------------------+----------+
+| Order | Callable | Priority |
++-------+-------------------+----------+
+| #1 | global_function() | 255 |
+| #2 | \Closure() | -1 |
++-------+-------------------+----------+
[Event] event2
-+-------+-----------------------------------------------------------------------------------+
-| Order | Callable |
-+-------+-----------------------------------------------------------------------------------+
-| #1 | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\CallableClass::__invoke() |
-+-------+-----------------------------------------------------------------------------------+
++-------+-----------------------------------------------------------------------------------+----------+
+| Order | Callable | Priority |
++-------+-----------------------------------------------------------------------------------+----------+
+| #1 | Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor\CallableClass::__invoke() | 0 |
++-------+-----------------------------------------------------------------------------------+----------+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.xml
index 3e4b20d82379..d7443f974366 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/event_dispatcher_1_events.xml
@@ -1,10 +1,10 @@
-
-
+
+
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.json
index 6372d9e5b56d..b7a5dec87df7 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.json
@@ -4,6 +4,7 @@
"public": true,
"synthetic": false,
"lazy": true,
+ "shared": true,
"synchronized": true,
"abstract": true,
"file": null,
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.md
index d9832a1511ab..f527ab9ff874 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.md
@@ -3,6 +3,7 @@
- Public: yes
- Synthetic: no
- Lazy: yes
+- Shared: yes
- Synchronized: yes
- Abstract: yes
- Factory Class: `Full\Qualified\FactoryClass`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.txt
index 3d9cbb2077c3..09340efcf5d8 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.txt
@@ -5,6 +5,7 @@
Public yes
Synthetic no
Lazy yes
+Shared yes
Synchronized yes
Abstract yes
Factory Class Full\Qualified\FactoryClass
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.xml
index 75d082024457..6088d9a21b5a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_1.xml
@@ -1,2 +1,2 @@
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.json
index 278a5bfed413..bb0f5685f36a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.json
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.json
@@ -4,6 +4,7 @@
"public": false,
"synthetic": true,
"lazy": false,
+ "shared": true,
"synchronized": false,
"abstract": false,
"file": "\/path\/to\/file",
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.md b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.md
index f552debbf18b..43227638d88a 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.md
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.md
@@ -3,6 +3,7 @@
- Public: no
- Synthetic: yes
- Lazy: no
+- Shared: yes
- Synchronized: no
- Abstract: no
- File: `/path/to/file`
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.txt
index 28a00d583b09..62fc7d2dc6c3 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.txt
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.txt
@@ -8,6 +8,7 @@
Public no
Synthetic yes
Lazy no
+Shared yes
Synchronized no
Abstract no
Required File /path/to/file
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.xml
index dd3e2e06d717..7a2154487d1e 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/legacy_synchronized_service_definition_2.xml
@@ -1,5 +1,5 @@
-
+
val1
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
index 4af5b929cbb5..52d91ec12758 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php
@@ -128,14 +128,4 @@ public static function themeInheritanceProvider()
array(array('TestBundle:Parent'), array('TestBundle:Child')),
);
}
-
- public function testRange()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
-
- public function testRangeWithMinMaxValues()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
index 1bf641fe1b93..4a5c025c6d37 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php
@@ -115,14 +115,4 @@ protected function setTheme(FormView $view, array $themes)
{
$this->engine->get('form')->setTheme($view, $themes);
}
-
- public function testRange()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
-
- public function testRangeWithMinMaxValues()
- {
- // No-op for forward compatibility with AbstractLayoutTest 2.8
- }
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json
index 93b63cd8ed02..b60e65c51767 100644
--- a/src/Symfony/Bundle/FrameworkBundle/composer.json
+++ b/src/Symfony/Bundle/FrameworkBundle/composer.json
@@ -17,36 +17,36 @@
],
"require": {
"php": ">=5.3.9",
- "symfony/asset": "~2.7",
- "symfony/dependency-injection": "~2.6,>=2.6.2",
- "symfony/config": "~2.4",
- "symfony/event-dispatcher": "~2.5",
- "symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4",
- "symfony/http-kernel": "~2.7",
- "symfony/filesystem": "~2.3",
- "symfony/routing": "~2.6,>2.6.4",
- "symfony/security-core": "~2.6",
- "symfony/security-csrf": "~2.6",
- "symfony/stopwatch": "~2.3",
- "symfony/templating": "~2.1",
- "symfony/translation": "~2.7",
+ "symfony/asset": "~2.7|~3.0.0",
+ "symfony/dependency-injection": "~2.8",
+ "symfony/config": "~2.8",
+ "symfony/event-dispatcher": "~2.8|~3.0.0",
+ "symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4|~3.0.0",
+ "symfony/http-kernel": "~2.8",
+ "symfony/filesystem": "~2.3|~3.0.0",
+ "symfony/routing": "~2.8|~3.0.0",
+ "symfony/security-core": "~2.6|~3.0.0",
+ "symfony/security-csrf": "~2.6|~3.0.0",
+ "symfony/stopwatch": "~2.3|~3.0.0",
+ "symfony/templating": "~2.1|~3.0.0",
+ "symfony/translation": "~2.8",
"doctrine/annotations": "~1.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
- "symfony/browser-kit": "~2.4",
- "symfony/console": "~2.7",
- "symfony/css-selector": "~2.0,>=2.0.5",
- "symfony/dom-crawler": "~2.0,>=2.0.5",
- "symfony/finder": "~2.0,>=2.0.5",
- "symfony/intl": "~2.3",
- "symfony/security": "~2.6",
- "symfony/form": "~2.7,>=2.7.2",
- "symfony/class-loader": "~2.1",
- "symfony/expression-language": "~2.6",
- "symfony/process": "~2.0,>=2.0.5",
- "symfony/validator": "~2.5",
- "symfony/yaml": "~2.0,>=2.0.5"
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
+ "symfony/browser-kit": "~2.4|~3.0.0",
+ "symfony/console": "~2.7|~3.0.0",
+ "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/finder": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/intl": "~2.3|~3.0.0",
+ "symfony/security": "~2.6|~3.0.0",
+ "symfony/form": "~2.8",
+ "symfony/class-loader": "~2.1|~3.0.0",
+ "symfony/expression-language": "~2.6|~3.0.0",
+ "symfony/process": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/validator": "~2.5|~3.0.0",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0"
},
"suggest": {
"symfony/console": "For using the console commands",
@@ -63,7 +63,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
index 657777f02000..1508f58c647e 100644
--- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
+++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md
@@ -1,12 +1,18 @@
CHANGELOG
=========
+2.8.0
+-----
+
+ * deprecated the `key` setting of `anonymous` and `remember_me` in favor of the
+ `secret` setting.
+
2.6.0
-----
* Added the possibility to override the default success/failure handler
to get the provider key and the options injected
- * Deprecated the `security.context` service for the `security.token_storage` and
+ * Deprecated the `security.context` service for the `security.token_storage` and
`security.authorization_checker` services.
2.4.0
diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
index a6ea333d95b8..7b3e111974ea 100644
--- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
+++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php
@@ -17,6 +17,7 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
use Symfony\Component\Security\Core\Role\RoleInterface;
+use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator;
/**
* SecurityDataCollector.
@@ -27,17 +28,20 @@ class SecurityDataCollector extends DataCollector
{
private $tokenStorage;
private $roleHierarchy;
+ private $logoutUrlGenerator;
/**
* Constructor.
*
* @param TokenStorageInterface|null $tokenStorage
* @param RoleHierarchyInterface|null $roleHierarchy
+ * @param LogoutUrlGenerator|null $logoutUrlGenerator
*/
- public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null)
+ public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null)
{
$this->tokenStorage = $tokenStorage;
$this->roleHierarchy = $roleHierarchy;
+ $this->logoutUrlGenerator = $logoutUrlGenerator;
}
/**
@@ -50,6 +54,7 @@ public function collect(Request $request, Response $response, \Exception $except
'enabled' => false,
'authenticated' => false,
'token_class' => null,
+ 'logout_url' => null,
'user' => '',
'roles' => array(),
'inherited_roles' => array(),
@@ -60,6 +65,7 @@ public function collect(Request $request, Response $response, \Exception $except
'enabled' => true,
'authenticated' => false,
'token_class' => null,
+ 'logout_url' => null,
'user' => '',
'roles' => array(),
'inherited_roles' => array(),
@@ -68,6 +74,7 @@ public function collect(Request $request, Response $response, \Exception $except
} else {
$inheritedRoles = array();
$assignedRoles = $token->getRoles();
+
if (null !== $this->roleHierarchy) {
$allRoles = $this->roleHierarchy->getReachableRoles($assignedRoles);
foreach ($allRoles as $role) {
@@ -76,10 +83,21 @@ public function collect(Request $request, Response $response, \Exception $except
}
}
}
+
+ $logoutUrl = null;
+ try {
+ if (null !== $this->logoutUrlGenerator) {
+ $logoutUrl = $this->logoutUrlGenerator->getLogoutPath();
+ }
+ } catch(\Exception $e) {
+ // fail silently when the logout URL cannot be generated
+ }
+
$this->data = array(
'enabled' => true,
'authenticated' => $token->isAuthenticated(),
'token_class' => get_class($token),
+ 'logout_url' => $logoutUrl,
'user' => $token->getUsername(),
'roles' => array_map(function (RoleInterface $role) { return $role->getRole();}, $assignedRoles),
'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles),
@@ -159,6 +177,16 @@ public function getTokenClass()
return $this->data['token_class'];
}
+ /**
+ * Get the provider key (i.e. the name of the active firewall).
+ *
+ * @return string The provider key
+ */
+ public function getLogoutUrl()
+ {
+ return $this->data['logout_url'];
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
index 497807174d24..992d5a5f7c6f 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php
@@ -14,6 +14,7 @@
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Exception\LogicException;
/**
* Adds all configured security voters to the access decision manager.
@@ -40,6 +41,10 @@ public function process(ContainerBuilder $container)
$voters = iterator_to_array($voters);
ksort($voters);
- $container->getDefinition('security.access.decision_manager')->replaceArgument(0, array_values($voters));
+ if (!$voters) {
+ throw new LogicException('No security voters found. You need to tag at least one with "security.voter"');
+ }
+
+ $container->getDefinition('security.access.decision_manager')->addMethodCall('setVoters', array(array_values($voters)));
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
index 36dbcdf89a1b..c2381a4344cb 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php
@@ -286,8 +286,22 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto
->end()
->arrayNode('anonymous')
->canBeUnset()
+ ->beforeNormalization()
+ ->ifTrue(function ($v) { return isset($v['key']); })
+ ->then(function ($v) {
+ if (isset($v['secret'])) {
+ throw new \LogicException('Cannot set both key and secret options for security.firewall.anonymous, use only secret instead.');
+ }
+
+ @trigger_error('security.firewall.anonymous.key is deprecated since version 2.8 and will be removed in 3.0. Use security.firewall.anonymous.secret instead.', E_USER_DEPRECATED);
+
+ $v['secret'] = $v['key'];
+
+ unset($v['key']);
+ })
+ ->end()
->children()
- ->scalarNode('key')->defaultValue(uniqid('', true))->end()
+ ->scalarNode('secret')->defaultValue(uniqid('', true))->end()
->end()
->end()
->arrayNode('switch_user')
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php
new file mode 100644
index 000000000000..c758b32b8d86
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/FormLoginLdapFactory.php
@@ -0,0 +1,57 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
+
+use Symfony\Component\Config\Definition\Builder\NodeDefinition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * FormLoginLdapFactory creates services for form login ldap authentication.
+ *
+ * @author Grégoire Pineau
+ * @author Charles Sarrazin
+ */
+class FormLoginLdapFactory extends FormLoginFactory
+{
+ protected function createAuthProvider(ContainerBuilder $container, $id, $config, $userProviderId)
+ {
+ $provider = 'security.authentication.provider.ldap_bind.'.$id;
+ $container
+ ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind'))
+ ->replaceArgument(0, new Reference($userProviderId))
+ ->replaceArgument(2, $id)
+ ->replaceArgument(3, new Reference($config['service']))
+ ->replaceArgument(4, $config['dn_string'])
+ ;
+
+ return $provider;
+ }
+
+ public function addConfiguration(NodeDefinition $node)
+ {
+ parent::addConfiguration($node);
+
+ $node
+ ->children()
+ ->scalarNode('service')->end()
+ ->scalarNode('dn_string')->defaultValue('{username}')->end()
+ ->end()
+ ;
+ }
+
+ public function getKey()
+ {
+ return 'form-login-ldap';
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php
new file mode 100644
index 000000000000..23752677775e
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/GuardAuthenticationFactory.php
@@ -0,0 +1,122 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
+
+use Symfony\Component\Config\Definition\Builder\NodeDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * Configures the "guard" authentication provider key under a firewall.
+ *
+ * @author Ryan Weaver
+ */
+class GuardAuthenticationFactory implements SecurityFactoryInterface
+{
+ public function getPosition()
+ {
+ return 'pre_auth';
+ }
+
+ public function getKey()
+ {
+ return 'guard';
+ }
+
+ public function addConfiguration(NodeDefinition $node)
+ {
+ $node
+ ->fixXmlConfig('authenticator')
+ ->children()
+ ->scalarNode('provider')
+ ->info('A key from the "providers" section of your security config, in case your user provider is different than the firewall')
+ ->end()
+ ->scalarNode('entry_point')
+ ->info('A service id (of one of your authenticators) whose start() method should be called when an anonymous user hits a page that requires authentication')
+ ->defaultValue(null)
+ ->end()
+ ->arrayNode('authenticators')
+ ->info('An array of service ids for all of your "authenticators"')
+ ->requiresAtLeastOneElement()
+ ->prototype('scalar')->end()
+ ->end()
+ ->end()
+ ;
+ }
+
+ public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
+ {
+ $authenticatorIds = $config['authenticators'];
+ $authenticatorReferences = array();
+ foreach ($authenticatorIds as $authenticatorId) {
+ $authenticatorReferences[] = new Reference($authenticatorId);
+ }
+
+ // configure the GuardAuthenticationFactory to have the dynamic constructor arguments
+ $providerId = 'security.authentication.provider.guard.'.$id;
+ $container
+ ->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.guard'))
+ ->replaceArgument(0, $authenticatorReferences)
+ ->replaceArgument(1, new Reference($userProvider))
+ ->replaceArgument(2, $id)
+ ;
+
+ // listener
+ $listenerId = 'security.authentication.listener.guard.'.$id;
+ $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.guard'));
+ $listener->replaceArgument(2, $id);
+ $listener->replaceArgument(3, $authenticatorReferences);
+
+ // determine the entryPointId to use
+ $entryPointId = $this->determineEntryPoint($defaultEntryPoint, $config);
+
+ // this is always injected - then the listener decides if it should be used
+ $container
+ ->getDefinition($listenerId)
+ ->addTag('security.remember_me_aware', array('id' => $id, 'provider' => $userProvider));
+
+ return array($providerId, $listenerId, $entryPointId);
+ }
+
+ private function determineEntryPoint($defaultEntryPointId, array $config)
+ {
+ if ($defaultEntryPointId) {
+ // explode if they've configured the entry_point, but there is already one
+ if ($config['entry_point']) {
+ throw new \LogicException(sprintf(
+ 'The guard authentication provider cannot use the "%s" entry_point because another entry point is already configured by another provider! Either remove the other provider or move the entry_point configuration as a root key under your firewall (i.e. at the same level as "guard").',
+ $config['entry_point']
+ ));
+ }
+
+ return $defaultEntryPointId;
+ }
+
+ if ($config['entry_point']) {
+ // if it's configured explicitly, use it!
+ return $config['entry_point'];
+ }
+
+ $authenticatorIds = $config['authenticators'];
+ if (count($authenticatorIds) == 1) {
+ // if there is only one authenticator, use that as the entry point
+ return array_shift($authenticatorIds);
+ }
+
+ // we have multiple entry points - we must ask them to configure one
+ throw new \LogicException(sprintf(
+ 'Because you have multiple guard configurators, you need to set the "guard.entry_point" key to one of you configurators (%s)',
+ implode(', ', $authenticatorIds)
+ ));
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php
new file mode 100644
index 000000000000..23c013058408
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpBasicLdapFactory.php
@@ -0,0 +1,67 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory;
+
+use Symfony\Component\Config\Definition\Builder\NodeDefinition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * HttpBasicFactory creates services for HTTP basic authentication.
+ *
+ * @author Fabien Potencier
+ * @author Grégoire Pineau
+ * @author Charles Sarrazin
+ */
+class HttpBasicLdapFactory extends HttpBasicFactory
+{
+ public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint)
+ {
+ $provider = 'security.authentication.provider.ldap_bind.'.$id;
+ $container
+ ->setDefinition($provider, new DefinitionDecorator('security.authentication.provider.ldap_bind'))
+ ->replaceArgument(0, new Reference($userProvider))
+ ->replaceArgument(2, $id)
+ ->replaceArgument(3, new Reference($config['service']))
+ ->replaceArgument(4, $config['dn_string'])
+ ;
+
+ // entry point
+ $entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint);
+
+ // listener
+ $listenerId = 'security.authentication.listener.basic.'.$id;
+ $listener = $container->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.basic'));
+ $listener->replaceArgument(2, $id);
+ $listener->replaceArgument(3, new Reference($entryPointId));
+
+ return array($provider, $listenerId, $entryPointId);
+ }
+
+ public function addConfiguration(NodeDefinition $node)
+ {
+ parent::addConfiguration($node);
+
+ $node
+ ->children()
+ ->scalarNode('service')->end()
+ ->scalarNode('dn_string')->defaultValue('{username}')->end()
+ ->end()
+ ;
+ }
+
+ public function getKey()
+ {
+ return 'http-basic-ldap';
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
index 7aa4f5baa03e..d8321f52456a 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php
@@ -35,7 +35,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
$authProviderId = 'security.authentication.provider.rememberme.'.$id;
$container
->setDefinition($authProviderId, new DefinitionDecorator('security.authentication.provider.rememberme'))
- ->addArgument($config['key'])
+ ->addArgument($config['secret'])
->addArgument($id)
;
@@ -56,7 +56,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider,
}
$rememberMeServices = $container->setDefinition($rememberMeServicesId, new DefinitionDecorator($templateId));
- $rememberMeServices->replaceArgument(1, $config['key']);
+ $rememberMeServices->replaceArgument(1, $config['secret']);
$rememberMeServices->replaceArgument(2, $id);
if (isset($config['token_provider'])) {
@@ -120,10 +120,25 @@ public function getKey()
public function addConfiguration(NodeDefinition $node)
{
$node->fixXmlConfig('user_provider');
- $builder = $node->children();
+ $builder = $node
+ ->beforeNormalization()
+ ->ifTrue(function ($v) { return isset($v['key']); })
+ ->then(function ($v) {
+ if (isset($v['secret'])) {
+ throw new \LogicException('Cannot set both key and secret options for remember_me, use only secret instead.');
+ }
+
+ @trigger_error('remember_me.key is deprecated since version 2.8 and will be removed in 3.0. Use remember_me.secret instead.', E_USER_DEPRECATED);
+
+ $v['secret'] = $v['key'];
+
+ unset($v['key']);
+ })
+ ->end()
+ ->children();
$builder
- ->scalarNode('key')->isRequired()->cannotBeEmpty()->end()
+ ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
->scalarNode('token_provider')->end()
->arrayNode('user_providers')
->beforeNormalization()
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
new file mode 100644
index 000000000000..068cda6a1fe8
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/UserProvider/LdapFactory.php
@@ -0,0 +1,64 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider;
+
+use Symfony\Component\Config\Definition\Builder\NodeDefinition;
+use Symfony\Component\DependencyInjection\DefinitionDecorator;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+/**
+ * LdapFactory creates services for Ldap user provider.
+ *
+ * @author Grégoire Pineau
+ * @author Charles Sarrazin
+ */
+class LdapFactory implements UserProviderFactoryInterface
+{
+ public function create(ContainerBuilder $container, $id, $config)
+ {
+ $container
+ ->setDefinition($id, new DefinitionDecorator('security.user.provider.ldap'))
+ ->replaceArgument(0, new Reference($config['service']))
+ ->replaceArgument(1, $config['base_dn'])
+ ->replaceArgument(2, $config['search_dn'])
+ ->replaceArgument(3, $config['search_password'])
+ ->replaceArgument(4, $config['default_roles'])
+ ->replaceArgument(5, $config['uid_key'])
+ ->replaceArgument(6, $config['filter'])
+ ;
+ }
+
+ public function getKey()
+ {
+ return 'ldap';
+ }
+
+ public function addConfiguration(NodeDefinition $node)
+ {
+ $node
+ ->children()
+ ->scalarNode('service')->isRequired()->cannotBeEmpty()->end()
+ ->scalarNode('base_dn')->isRequired()->cannotBeEmpty()->end()
+ ->scalarNode('search_dn')->end()
+ ->scalarNode('search_password')->end()
+ ->arrayNode('default_roles')
+ ->beforeNormalization()->ifString()->then(function($v) { return preg_split('/\s*,\s*/', $v); })->end()
+ ->requiresAtLeastOneElement()
+ ->prototype('scalar')->end()
+ ->end()
+ ->scalarNode('uid_key')->defaultValue('sAMAccountName')->end()
+ ->scalarNode('filter')->defaultValue('({uid_key}={username})')->end()
+ ->end()
+ ;
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
index 36c16e0dbc7d..6db34e4d2810 100644
--- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
+++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php
@@ -65,6 +65,7 @@ public function load(array $configs, ContainerBuilder $container)
$loader->load('templating_php.xml');
$loader->load('templating_twig.xml');
$loader->load('collectors.xml');
+ $loader->load('guard.xml');
if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
$container->removeDefinition('security.expression_language');
@@ -410,7 +411,7 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut
$listenerId = 'security.authentication.listener.anonymous.'.$id;
$container
->setDefinition($listenerId, new DefinitionDecorator('security.authentication.listener.anonymous'))
- ->replaceArgument(1, $firewall['anonymous']['key'])
+ ->replaceArgument(1, $firewall['anonymous']['secret'])
;
$listeners[] = new Reference($listenerId);
@@ -418,7 +419,7 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut
$providerId = 'security.authentication.provider.anonymous.'.$id;
$container
->setDefinition($providerId, new DefinitionDecorator('security.authentication.provider.anonymous'))
- ->replaceArgument(0, $firewall['anonymous']['key'])
+ ->replaceArgument(0, $firewall['anonymous']['secret'])
;
$authenticationProviders[] = $providerId;
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml
index 8f6a608c6de8..bfc236b8cf8e 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml
@@ -13,6 +13,7 @@
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml
new file mode 100644
index 000000000000..0524cf2b95b4
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
index b7c1407c1cc5..b1a2cdfc80cb 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml
@@ -158,10 +158,21 @@
+
+
+
+
+
+
+
+
+
+
+
@@ -169,6 +180,7 @@
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
index 917e90f79281..948286bb5a85 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml
@@ -223,6 +223,15 @@
%security.authentication.hide_user_not_found%
+
+
+
+
+
+
+ %security.authentication.hide_user_not_found%
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg
new file mode 100644
index 000000000000..02033fdc7f5e
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/icon.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
index 923be8381064..dd724682d749 100644
--- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
+++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig
@@ -1,92 +1,122 @@
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
+{% block page_title 'Security' %}
+
{% block toolbar %}
{% if collector.tokenClass %}
- {% set color_code = (collector.enabled and collector.authenticated) ? 'green' : 'yellow' %}
- {% set authentication_color_code = (collector.enabled and collector.authenticated) ? 'green' : 'red' %}
- {% set authentication_color_text = (collector.enabled and collector.authenticated) ? 'Yes' : 'No' %}
+ {% set is_authenticated = collector.enabled and collector.authenticated %}
+ {% set color_code = is_authenticated ? '' : 'yellow' %}
{% else %}
- {% set color_code = collector.enabled ? 'red' : 'black' %}
+ {% set color_code = collector.enabled ? 'red' : '' %}
{% endif %}
+
+ {% set icon %}
+ {{ include('@Security/Collector/icon.svg') }}
+ {{ collector.user|default('n/a') }}
+ {% endset %}
+
{% set text %}
{% if collector.tokenClass %}
Logged in as
- {{ collector.user }}
+ {{ collector.user }}
+
Authenticated
- {{ authentication_color_text }}
+ {{ is_authenticated ? 'Yes' : 'No' }}
+
{% if collector.tokenClass != null %}
Token class
- {{ collector.tokenClass|abbr_class }}
+ {{ collector.tokenClass|abbr_class }}
+
+ {% endif %}
+ {% if collector.logoutUrl %}
+
{% endif %}
{% elseif collector.enabled %}
- You are not authenticated.
+
+ You are not authenticated.
+
{% else %}
- The security is disabled.
+
+ The security is disabled.
+
{% endif %}
{% endset %}
- {% set icon %}
-
-
- {% if collector.user %}{{ collector.user }}
{% endif %}
- {% endset %}
- {% include '@WebProfiler/Profiler/toolbar_item.html.twig' with { 'link': profiler_url } %}
+
+ {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: color_code }) }}
{% endblock %}
{% block menu %}
-
-
- Security
-
+
+ {{ include('@Security/Collector/icon.svg') }}
+ Security
+
{% endblock %}
{% block panel %}
- Security
+ Security Token
+
{% if collector.tokenClass %}
+
+
+ {{ collector.user == 'anon.' ? 'Anonymous' : collector.user }}
+ Username
+
+
+
+ {{ include('@WebProfiler/Icon/' ~ (collector.authenticated ? 'yes' : 'no') ~ '.svg') }}
+ Authenticated
+
+
+
-
- Username
- {{ collector.user }}
-
-
- Authenticated?
-
- {% if collector.authenticated %}
- yes
- {% else %}
- no {% if not collector.roles|length %}(probably because the user has no roles) {% endif %}
- {% endif %}
-
-
-
- Roles
- {{ collector.roles|yaml_encode }}
-
- {% if collector.supportsRoleHierarchy %}
-
- Inherited Roles
- {{ collector.inheritedRoles|yaml_encode }}
-
- {% endif %}
- {% if collector.tokenClass != null %}
-
- Token class
- {{ collector.tokenClass }}
-
- {% endif %}
+
+
+ Property
+ Value
+
+
+
+
+ Roles
+
+ {{ collector.roles is empty ? 'none' : collector.roles|yaml_encode }}
+
+ {% if not collector.authenticated and collector.roles is empty %}
+ User is not authenticated probably because they have no roles.
+ {% endif %}
+
+
+
+ {% if collector.supportsRoleHierarchy %}
+
+ Inherited Roles
+ {{ collector.inheritedRoles is empty ? 'none' : collector.inheritedRoles|yaml_encode }}
+
+ {% endif %}
+
+ {% if collector.tokenClass %}
+
+ Token class
+ {{ collector.tokenClass }}
+
+ {% endif %}
+
{% elseif collector.enabled %}
-
- No token
-
+
+
There is no security token.
+
{% else %}
-
- The security component is disabled
-
+
+
The security component is disabled.
+
{% endif %}
{% endblock %}
diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
index 72f7b68de959..f2dfc991fbce 100644
--- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
+++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php
@@ -15,7 +15,9 @@
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginFactory;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginLdapFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicFactory;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicLdapFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpDigestFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\X509Factory;
@@ -23,6 +25,8 @@
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SimplePreAuthenticationFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SimpleFormFactory;
use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\InMemoryFactory;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\GuardAuthenticationFactory;
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\LdapFactory;
/**
* Bundle.
@@ -37,15 +41,19 @@ public function build(ContainerBuilder $container)
$extension = $container->getExtension('security');
$extension->addSecurityListenerFactory(new FormLoginFactory());
+ $extension->addSecurityListenerFactory(new FormLoginLdapFactory());
$extension->addSecurityListenerFactory(new HttpBasicFactory());
+ $extension->addSecurityListenerFactory(new HttpBasicLdapFactory());
$extension->addSecurityListenerFactory(new HttpDigestFactory());
$extension->addSecurityListenerFactory(new RememberMeFactory());
$extension->addSecurityListenerFactory(new X509Factory());
$extension->addSecurityListenerFactory(new RemoteUserFactory());
$extension->addSecurityListenerFactory(new SimplePreAuthenticationFactory());
$extension->addSecurityListenerFactory(new SimpleFormFactory());
+ $extension->addSecurityListenerFactory(new GuardAuthenticationFactory());
$extension->addUserProviderFactory(new InMemoryFactory());
+ $extension->addUserProviderFactory(new LdapFactory());
$container->addCompilerPass(new AddSecurityVotersPass());
}
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
index b16a46ff0345..4521c8cdcd22 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php
@@ -71,7 +71,7 @@
'x509' => true,
'remote_user' => true,
'logout' => true,
- 'remember_me' => array('key' => 'TheKey'),
+ 'remember_me' => array('secret' => 'TheSecret'),
),
'host' => array(
'pattern' => '/test',
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php
index 93a30444139e..e0ca4f6dedf3 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php
@@ -9,7 +9,7 @@
'main' => array(
'form_login' => true,
'remember_me' => array(
- 'key' => 'TheyKey',
+ 'secret' => 'TheSecret',
'catch_exceptions' => false,
'token_provider' => 'token_provider_id',
),
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
index 1a56aa88fda0..e5f5905fa7e0 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml
@@ -56,7 +56,7 @@
-
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml
index 167475689157..b6ade91a0797 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml
@@ -11,7 +11,7 @@
-
+
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
index 93c231ea235f..6b27806e564b 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml
@@ -55,7 +55,7 @@ security:
remote_user: true
logout: true
remember_me:
- key: TheKey
+ secret: TheSecret
host:
pattern: /test
host: foo\.example\.org
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml
index 3a38b33c521c..a521c8c6a803 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml
@@ -7,6 +7,6 @@ security:
main:
form_login: true
remember_me:
- key: TheKey
+ secret: TheSecret
catch_exceptions: false
token_provider: token_provider_id
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php
new file mode 100644
index 000000000000..cfbc37859b97
--- /dev/null
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Security/Factory/GuardAuthenticationFactoryTest.php
@@ -0,0 +1,180 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection\Security\Factory;
+
+use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\GuardAuthenticationFactory;
+use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+
+class GuardAuthenticationFactoryTest extends \PHPUnit_Framework_TestCase
+{
+ /**
+ * @dataProvider getValidConfigurationTests
+ */
+ public function testAddValidConfiguration(array $inputConfig, array $expectedConfig)
+ {
+ $factory = new GuardAuthenticationFactory();
+ $nodeDefinition = new ArrayNodeDefinition('guard');
+ $factory->addConfiguration($nodeDefinition);
+
+ $node = $nodeDefinition->getNode();
+ $normalizedConfig = $node->normalize($inputConfig);
+ $finalizedConfig = $node->finalize($normalizedConfig);
+
+ $this->assertEquals($expectedConfig, $finalizedConfig);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
+ * @dataProvider getInvalidConfigurationTests
+ */
+ public function testAddInvalidConfiguration(array $inputConfig)
+ {
+ $factory = new GuardAuthenticationFactory();
+ $nodeDefinition = new ArrayNodeDefinition('guard');
+ $factory->addConfiguration($nodeDefinition);
+
+ $node = $nodeDefinition->getNode();
+ $normalizedConfig = $node->normalize($inputConfig);
+ // will validate and throw an exception on invalid
+ $node->finalize($normalizedConfig);
+ }
+
+ public function getValidConfigurationTests()
+ {
+ $tests = array();
+
+ // completely basic
+ $tests[] = array(
+ array(
+ 'authenticators' => array('authenticator1', 'authenticator2'),
+ 'provider' => 'some_provider',
+ 'entry_point' => 'the_entry_point',
+ ),
+ array(
+ 'authenticators' => array('authenticator1', 'authenticator2'),
+ 'provider' => 'some_provider',
+ 'entry_point' => 'the_entry_point',
+ ),
+ );
+
+ // testing xml config fix: authenticator -> authenticators
+ $tests[] = array(
+ array(
+ 'authenticator' => array('authenticator1', 'authenticator2'),
+ ),
+ array(
+ 'authenticators' => array('authenticator1', 'authenticator2'),
+ 'entry_point' => null,
+ ),
+ );
+
+ return $tests;
+ }
+
+ public function getInvalidConfigurationTests()
+ {
+ $tests = array();
+
+ // testing not empty
+ $tests[] = array(
+ array('authenticators' => array()),
+ );
+
+ return $tests;
+ }
+
+ public function testBasicCreate()
+ {
+ // simple configuration
+ $config = array(
+ 'authenticators' => array('authenticator123'),
+ 'entry_point' => null,
+ );
+ list($container, $entryPointId) = $this->executeCreate($config, null);
+ $this->assertEquals('authenticator123', $entryPointId);
+
+ $providerDefinition = $container->getDefinition('security.authentication.provider.guard.my_firewall');
+ $this->assertEquals(array(
+ 'index_0' => array(new Reference('authenticator123')),
+ 'index_1' => new Reference('my_user_provider'),
+ 'index_2' => 'my_firewall',
+ ), $providerDefinition->getArguments());
+
+ $listenerDefinition = $container->getDefinition('security.authentication.listener.guard.my_firewall');
+ $this->assertEquals('my_firewall', $listenerDefinition->getArgument(2));
+ $this->assertEquals(array(new Reference('authenticator123')), $listenerDefinition->getArgument(3));
+ }
+
+ public function testExistingDefaultEntryPointUsed()
+ {
+ // any existing default entry point is used
+ $config = array(
+ 'authenticators' => array('authenticator123'),
+ 'entry_point' => null,
+ );
+ list($container, $entryPointId) = $this->executeCreate($config, 'some_default_entry_point');
+ $this->assertEquals('some_default_entry_point', $entryPointId);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testCannotOverrideDefaultEntryPoint()
+ {
+ // any existing default entry point is used
+ $config = array(
+ 'authenticators' => array('authenticator123'),
+ 'entry_point' => 'authenticator123',
+ );
+ $this->executeCreate($config, 'some_default_entry_point');
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testMultipleAuthenticatorsRequiresEntryPoint()
+ {
+ // any existing default entry point is used
+ $config = array(
+ 'authenticators' => array('authenticator123', 'authenticatorABC'),
+ 'entry_point' => null,
+ );
+ $this->executeCreate($config, null);
+ }
+
+ public function testCreateWithEntryPoint()
+ {
+ // any existing default entry point is used
+ $config = array(
+ 'authenticators' => array('authenticator123', 'authenticatorABC'),
+ 'entry_point' => 'authenticatorABC',
+ );
+ list($container, $entryPointId) = $this->executeCreate($config, null);
+ $this->assertEquals('authenticatorABC', $entryPointId);
+ }
+
+ private function executeCreate(array $config, $defaultEntryPointId)
+ {
+ $container = new ContainerBuilder();
+ $container->register('security.authentication.provider.guard');
+ $container->register('security.authentication.listener.guard');
+ $id = 'my_firewall';
+ $userProviderId = 'my_user_provider';
+
+ $factory = new GuardAuthenticationFactory();
+ list($providerId, $listenerId, $entryPointId) = $factory->create($container, $id, $config, $userProviderId, $defaultEntryPointId);
+
+ return array($container, $entryPointId);
+ }
+}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
index 1eccbfd795be..dd7c19e9c7f1 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Controller/LoginController.php
@@ -19,7 +19,7 @@ class LoginController extends ContainerAware
{
public function loginAction()
{
- $form = $this->container->get('form.factory')->create('user_login');
+ $form = $this->container->get('form.factory')->create('Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\Form\UserLoginType');
return $this->container->get('templating')->renderResponse('CsrfFormLoginBundle:Login:login.html.twig', array(
'form' => $form->createView(),
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginFormType.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginType.php
similarity index 79%
rename from src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginFormType.php
rename to src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginType.php
index d76d8fd629bb..48b87fbecbfc 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginFormType.php
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/CsrfFormLoginBundle/Form/UserLoginType.php
@@ -16,7 +16,7 @@
use Symfony\Component\Form\FormError;
use Symfony\Component\Form\FormEvents;
use Symfony\Component\Form\FormEvent;
-use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Security\Core\Security;
@@ -27,16 +27,16 @@
* @author Henrik Bjornskov
* @author Jeremy Mikola
*/
-class UserLoginFormType extends AbstractType
+class UserLoginType extends AbstractType
{
- private $request;
+ private $requestStack;
/**
- * @param Request $request A request instance
+ * @param RequestStack $requestStack A RequestStack instance
*/
- public function __construct(Request $request)
+ public function __construct(RequestStack $requestStack)
{
- $this->request = $request;
+ $this->requestStack = $requestStack;
}
/**
@@ -45,12 +45,12 @@ public function __construct(Request $request)
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
- ->add('username', 'text')
- ->add('password', 'password')
- ->add('_target_path', 'hidden')
+ ->add('username', 'Symfony\Component\Form\Extension\Core\Type\TextType')
+ ->add('password', 'Symfony\Component\Form\Extension\Core\Type\PasswordType')
+ ->add('_target_path', 'Symfony\Component\Form\Extension\Core\Type\HiddenType')
;
- $request = $this->request;
+ $request = $this->requestStack->getCurrentRequest();
/* Note: since the Security component's form login listener intercepts
* the POST request, this form will never really be bound to the
@@ -87,12 +87,4 @@ public function configureOptions(OptionsResolver $resolver)
'intention' => 'authenticate',
));
}
-
- /**
- * {@inheritdoc}
- */
- public function getName()
- {
- return 'user_login';
- }
}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/config.yml
index e1e2b0e88393..d7ad6049aa61 100644
--- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/config.yml
+++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/CsrfFormLogin/config.yml
@@ -3,12 +3,11 @@ imports:
services:
csrf_form_login.form.type:
- class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\Form\UserLoginFormType
- scope: request
+ class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\CsrfFormLoginBundle\Form\UserLoginType
arguments:
- - @request
+ - @request_stack
tags:
- - { name: form.type, alias: user_login }
+ - { name: form.type }
security:
encoders:
diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json
index 881031d0209f..5239f039fee7 100644
--- a/src/Symfony/Bundle/SecurityBundle/composer.json
+++ b/src/Symfony/Bundle/SecurityBundle/composer.json
@@ -17,26 +17,26 @@
],
"require": {
"php": ">=5.3.9",
- "symfony/security": "~2.7",
- "symfony/security-acl": "~2.7",
- "symfony/http-kernel": "~2.2"
+ "symfony/security": "~2.8|~3.0.0",
+ "symfony/security-acl": "~2.7|~3.0.0",
+ "symfony/http-kernel": "~2.2|~3.0.0"
},
"require-dev": {
- "symfony/phpunit-bridge": "~2.7",
- "symfony/browser-kit": "~2.4",
- "symfony/console": "~2.7",
- "symfony/css-selector": "~2.0,>=2.0.5",
- "symfony/dependency-injection": "~2.6,>=2.6.6",
- "symfony/dom-crawler": "~2.0,>=2.0.5",
- "symfony/form": "~2.7",
- "symfony/framework-bundle": "~2.7",
- "symfony/http-foundation": "~2.3",
- "symfony/twig-bundle": "~2.7",
- "symfony/twig-bridge": "~2.7",
- "symfony/process": "~2.0,>=2.0.5",
- "symfony/validator": "~2.5",
- "symfony/yaml": "~2.0,>=2.0.5",
- "symfony/expression-language": "~2.6",
+ "symfony/phpunit-bridge": "~2.7|~3.0.0",
+ "symfony/browser-kit": "~2.4|~3.0.0",
+ "symfony/config": "~2.8|~3.0.0",
+ "symfony/console": "~2.7|~3.0.0",
+ "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/dom-crawler": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/form": "~2.8",
+ "symfony/framework-bundle": "~2.8",
+ "symfony/http-foundation": "~2.4|~3.0.0",
+ "symfony/twig-bundle": "~2.7|~3.0.0",
+ "symfony/twig-bridge": "~2.7|~3.0.0",
+ "symfony/process": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/validator": "~2.5|~3.0.0",
+ "symfony/yaml": "~2.0,>=2.0.5|~3.0.0",
+ "symfony/expression-language": "~2.6|~3.0.0",
"doctrine/doctrine-bundle": "~1.2",
"twig/twig": "~1.20|~2.0",
"ircmaxell/password-compat": "~1.0"
@@ -47,7 +47,7 @@
"minimum-stability": "dev",
"extra": {
"branch-alias": {
- "dev-master": "2.7-dev"
+ "dev-master": "2.8-dev"
}
}
}
diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
index 65827eba5a6b..5dde9406914a 100644
--- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
+++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php
@@ -11,9 +11,11 @@
namespace Symfony\Bundle\TwigBundle\CacheWarmer;
+use Symfony\Component\Finder\Finder;
use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinderInterface;
+use Symfony\Component\Templating\TemplateReference;
/**
* Generates the Twig cache for all templates.
@@ -27,14 +29,16 @@ class TemplateCacheCacheWarmer implements CacheWarmerInterface
{
protected $container;
protected $finder;
+ private $paths;
/**
* Constructor.
*
* @param ContainerInterface $container The dependency injection container
* @param TemplateFinderInterface $finder The template paths cache warmer
+ * @param array $paths Additional twig paths to warm
*/
- public function __construct(ContainerInterface $container, TemplateFinderInterface $finder)
+ public function __construct(ContainerInterface $container, TemplateFinderInterface $finder, array $paths = array())
{
// We don't inject the Twig environment directly as it depends on the
// template locator (via the loader) which might be a cached one.
@@ -42,6 +46,7 @@ public function __construct(ContainerInterface $container, TemplateFinderInterfa
// has been warmed up
$this->container = $container;
$this->finder = $finder;
+ $this->paths = $paths;
}
/**
@@ -53,7 +58,13 @@ public function warmUp($cacheDir)
{
$twig = $this->container->get('twig');
- foreach ($this->finder->findAllTemplates() as $template) {
+ $templates = $this->finder->findAllTemplates();
+
+ foreach ($this->paths as $path => $namespace) {
+ $templates = array_merge($templates, $this->findTemplatesInFolder($namespace, $path));
+ }
+
+ foreach ($templates as $template) {
if ('twig' !== $template->get('engine')) {
continue;
}
@@ -75,4 +86,32 @@ public function isOptional()
{
return true;
}
+
+ /**
+ * Find templates in the given directory.
+ *
+ * @param string $namespace The namespace for these templates
+ * @param string $dir The folder where to look for templates
+ *
+ * @return array An array of templates of type TemplateReferenceInterface
+ */
+ private function findTemplatesInFolder($namespace, $dir)
+ {
+ if (!is_dir($dir)) {
+ return array();
+ }
+
+ $templates = array();
+ $finder = new Finder();
+
+ foreach ($finder->files()->followLinks()->in($dir) as $file) {
+ $name = $file->getRelativePathname();
+ $templates[] = new TemplateReference(
+ $namespace ? sprintf('@%s/%s', $namespace, $name) : $name,
+ 'twig'
+ );
+ }
+
+ return $templates;
+ }
}
diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
index b0c172c1e9e1..237fda48ec93 100644
--- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
+++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php
@@ -11,12 +11,10 @@
namespace Symfony\Bundle\TwigBundle\Controller;
-use Symfony\Bundle\FrameworkBundle\Templating\TemplateReference;
use Symfony\Component\HttpKernel\Exception\FlattenException;
use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
-use Symfony\Component\Templating\TemplateReferenceInterface;
/**
* ExceptionController renders error or exception pages for a given
@@ -96,7 +94,7 @@ protected function getAndCleanOutputBuffering($startObLevel)
* @param int $code An HTTP response status code
* @param bool $showException
*
- * @return TemplateReferenceInterface
+ * @return string
*/
protected function findTemplate(Request $request, $format, $code, $showException)
{
@@ -107,14 +105,14 @@ protected function findTemplate(Request $request, $format, $code, $showException
// For error pages, try to find a template for the specific HTTP status code and format
if (!$showException) {
- $template = new TemplateReference('TwigBundle', 'Exception', $name.$code, $format, 'twig');
+ $template = sprintf('@Twig/Exception/%s%s.%s.twig', $name, $code, $format);
if ($this->templateExists($template)) {
return $template;
}
}
// try to find a template for the given format
- $template = new TemplateReference('TwigBundle', 'Exception', $name, $format, 'twig');
+ $template = sprintf('@Twig/Exception/%s.%s.twig', $name, $format);
if ($this->templateExists($template)) {
return $template;
}
@@ -122,7 +120,7 @@ protected function findTemplate(Request $request, $format, $code, $showException
// default to a generic HTML exception
$request->setRequestFormat('html');
- return new TemplateReference('TwigBundle', 'Exception', $showException ? 'exception_full' : $name, 'html', 'twig');
+ return sprintf('@Twig/Exception/%s.html.twig', $showException ? 'exception_full' : $name);
}
// to be removed when the minimum required version of Twig is >= 3.0
diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
index 7b97e120baa4..c0171219d048 100644
--- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
+++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php
@@ -12,6 +12,7 @@
namespace Symfony\Bundle\TwigBundle\DependencyInjection;
use Symfony\Component\Config\FileLocator;
+use Symfony\Component\Config\Resource\FileExistenceResource;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
@@ -76,21 +77,29 @@ public function load(array $configs, ContainerBuilder $container)
}
}
+ $container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
+
// register bundles as Twig namespaces
foreach ($container->getParameter('kernel.bundles') as $bundle => $class) {
- if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$bundle.'/views')) {
+ $dir = $container->getParameter('kernel.root_dir').'/Resources/'.$bundle.'/views';
+ if (is_dir($dir)) {
$this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle);
}
+ $container->addResource(new FileExistenceResource($dir));
$reflection = new \ReflectionClass($class);
- if (is_dir($dir = dirname($reflection->getFileName()).'/Resources/views')) {
+ $dir = dirname($reflection->getFileName()).'/Resources/views';
+ if (is_dir($dir)) {
$this->addTwigPath($twigFilesystemLoaderDefinition, $dir, $bundle);
}
+ $container->addResource(new FileExistenceResource($dir));
}
- if (is_dir($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) {
+ $dir = $container->getParameter('kernel.root_dir').'/Resources/views';
+ if (is_dir($dir)) {
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir));
}
+ $container->addResource(new FileExistenceResource($dir));
if (!empty($config['globals'])) {
$def = $container->getDefinition('twig');
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
index 9e1a11777418..bb871f440a20 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
+++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml
@@ -48,6 +48,7 @@
+
@@ -78,7 +79,7 @@
-
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
index 074389ce919e..c27cc56e6a07 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.atom.twig
@@ -1 +1 @@
-{% include 'TwigBundle:Exception:error.xml.twig' %}
+{% include '@Twig/Exception/error.xml.twig' %}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
index 074389ce919e..c27cc56e6a07 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/error.rdf.twig
@@ -1 +1 @@
-{% include 'TwigBundle:Exception:error.xml.twig' %}
+{% include '@Twig/Exception/error.xml.twig' %}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
index 989740fdd01c..d507ce46f694 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.atom.twig
@@ -1 +1 @@
-{% include 'TwigBundle:Exception:exception.xml.twig' with { 'exception': exception } %}
+{% include '@Twig/Exception/exception.xml.twig' with { 'exception': exception } %}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
index 870d4a0fd240..bdf242b7f199 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.css.twig
@@ -1,3 +1,3 @@
/*
-{% include 'TwigBundle:Exception:exception.txt.twig' with { 'exception': exception } %}
+{% include '@Twig/Exception/exception.txt.twig' with { 'exception': exception } %}
*/
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
index f09ffb3c658d..947df655836b 100644
--- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
+++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig
@@ -37,7 +37,7 @@
{% for position, e in exception.toarray %}
- {% include 'TwigBundle:Exception:traces.html.twig' with { 'exception': e, 'position': position, 'count': previous_count } only %}
+ {% include '@Twig/Exception/traces.html.twig' with { 'exception': e, 'position': position, 'count': previous_count } only %}
{% endfor %}
{% if logger %}
@@ -63,7 +63,7 @@
- {% include 'TwigBundle:Exception:logs.html.twig' with { 'logs': logger.logs } only %}
+ {% include '@Twig/Exception/logs.html.twig' with { 'logs': logger.logs } only %}
{% endif %}
@@ -88,7 +88,7 @@
{% endif %}
-{% include 'TwigBundle:Exception:traces_text.html.twig' with { 'exception': exception } only %}
+{% include '@Twig/Exception/traces_text.html.twig' with { 'exception': exception } only %}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/body.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/body.css.twig
deleted file mode 100644
index fa4d07691743..000000000000
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/body.css.twig
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
-Copyright (c) 2010, Yahoo! Inc. All rights reserved.
-Code licensed under the BSD License:
-http://developer.yahoo.com/yui/license.html
-version: 3.1.2
-build: 56
-*/
-.sf-reset div,.sf-reset dl,.sf-reset dt,.sf-reset dd,.sf-reset ul,.sf-reset ol,.sf-reset li,.sf-reset h1,.sf-reset h2,.sf-reset h3,.sf-reset h4,.sf-reset h5,.sf-reset h6,.sf-reset pre,.sf-reset code,.sf-reset form,.sf-reset fieldset,.sf-reset legend,.sf-reset input,.sf-reset textarea,.sf-reset p,.sf-reset blockquote,.sf-reset th,.sf-reset td{margin:0;padding:0;}.sf-reset table{border-collapse:collapse;border-spacing:0;}.sf-reset fieldset,.sf-reset img{border:0;}.sf-reset address,.sf-reset caption,.sf-reset cite,.sf-reset code,.sf-reset dfn,.sf-reset em,.sf-reset strong,.sf-reset th,.sf-reset var{font-style:normal;font-weight:normal;}.sf-reset li{list-style:none;}.sf-reset caption,.sf-reset th{text-align:left;}.sf-reset h1,.sf-reset h2,.sf-reset h3,.sf-reset h4,.sf-reset h5,.sf-reset h6{font-size:100%;font-weight:normal;}.sf-reset q:before,.sf-reset q:after{content:'';}.sf-reset abbr,.sf-reset acronym{border:0;font-variant:normal;}.sf-reset sup{vertical-align:text-top;}.sf-reset sub{vertical-align:text-bottom;}.sf-reset input,.sf-reset textarea,.sf-reset select{font-family:inherit;font-size:inherit;font-weight:inherit;}.sf-reset input,.sf-reset textarea,.sf-reset select{font-size:100%;}.sf-reset legend{color:#000;}
-.sf-reset abbr {
- border-bottom: 1px dotted #000;
- cursor: help;
-}
-.sf-reset p {
- font-size: 14px;
- line-height: 20px;
- padding-bottom: 20px;
-}
-.sf-reset strong {
- color: #313131;
- font-weight: bold;
-}
-.sf-reset a {
- color: #6c6159;
-}
-.sf-reset a img {
- border: none;
-}
-.sf-reset a:hover {
- text-decoration: underline;
-}
-.sf-reset em {
- font-style: italic;
-}
-.sf-reset h2,
-.sf-reset h3 {
- font-weight: bold;
-}
-.sf-reset h1 {
- font-family: Georgia, "Times New Roman", Times, serif;
- font-size: 20px;
- color: #313131;
- word-break: break-all;
-}
-.sf-reset li {
- padding-bottom: 10px;
-}
-.sf-reset .block {
- -moz-border-radius: 16px;
- -webkit-border-radius: 16px;
- border-radius: 16px;
- margin-bottom: 20px;
- background-color: #FFFFFF;
- border: 1px solid #dfdfdf;
- padding: 40px 50px;
-}
-.sf-reset h2 {
- font-size: 16px;
- font-family: Arial, Helvetica, sans-serif;
-}
-.sf-reset li a {
- background: none;
- color: #868686;
- text-decoration: none;
-}
-.sf-reset li a:hover {
- background: none;
- color: #313131;
- text-decoration: underline;
-}
-.sf-reset ol {
- padding: 10px 0;
-}
-.sf-reset ol li {
- list-style: decimal;
- margin-left: 20px;
- padding: 2px;
- padding-bottom: 20px;
-}
-.sf-reset ol ol li {
- list-style-position: inside;
- margin-left: 0;
- white-space: nowrap;
- font-size: 12px;
- padding-bottom: 0;
-}
-.sf-reset li .selected {
- background-color: #ffd;
-}
-.sf-button {
- display: -moz-inline-box;
- display: inline-block;
- text-align: center;
- vertical-align: middle;
- border: 0;
- background: transparent none;
- text-transform: uppercase;
- cursor: pointer;
- font: bold 11px Arial, Helvetica, sans-serif;
-}
-.sf-button span {
- text-decoration: none;
- display: block;
- height: 28px;
- float: left;
-}
-.sf-button .border-l {
- text-decoration: none;
- display: block;
- height: 28px;
- float: left;
- padding: 0 0 0 7px;
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQtJREFUeNpiPHnyJAMakARiByDWYEGT8ADiYGVlZStubm5xlv///4MEQYoKZGRkQkRERLRYWVl5wYJQyXBZWdkwCQkJUxAHKgaWlAHSLqKiosb//v1DsYMFKGCvoqJiDmQzwXTAJYECulxcXNLoumCSoszMzDzoumDGghQwYZUECWIzkrAkSIIGOmlkLI10AiX//P379x8jIyMTNmPf/v79+ysLCwsvuiQoNi5//fr1Kch4dAyS3P/gwYMTQBP+wxwHw0xA4gkQ73v9+vUZdJ2w1Lf82bNn4iCHCQoKasHsZw4ODgbRIL8c+/Lly5M3b978Y2dn5wC6npkFLXnsAOKLjx49AmUHLYAAAwBoQubG016R5wAAAABJRU5ErkJggg==) no-repeat top left;
-}
-.sf-button .border-r {
- padding: 0 7px 0 0;
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAR1JREFUeNpiPHnyZCMDA8MNID5gZmb2nAEJMH7//v3N169fX969e/cYkL8WqGAHXPLv37//QYzfv39/fvPmzbUnT56sAXInmJub/2H5/x8sx8DCwsIrISFhDmQyPX78+CmQXs70798/BmQsKipqBNTgdvz4cWkmkE5kDATMioqKZkCFdiwg1eiAi4tLGqhQF24nMmBmZuYEigth1QkEbEBxTlySYPvJkwSJ00AnjYylgU6gxB8g/oFVEphkvgLF32KNMmCCewYUv4qhEyj47+HDhyeBzIMYOoEp8CxQw56wsLAncJ1//vz5/P79+2svX74EJc2V4BT58+fPd8CE/QKYHMGJOiIiAp6oWW7evDkNSF8DZYfIyEiU7AAQYACJ2vxVdJW4eQAAAABJRU5ErkJggg==) right top no-repeat;
-}
-.sf-button .btn-bg {
- padding: 0px 14px;
- color: #636363;
- line-height: 28px;
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAcCAYAAACgXdXMAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAClJREFUeNpiPnny5EKGf//+/Wf6//8/A4QAcrGzKCZwGc9sa2urBBBgAIbDUoYVp9lmAAAAAElFTkSuQmCC) repeat-x top left;
-}
-.sf-button:hover .border-l,
-.sf-button-selected .border-l {
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAR9JREFUeNpi/P//PwMyOHfunDqQSgNiexZkibNnzxYBqZa3HOs5v7PcYQBLnjlzhg1IbfzIdsTjA/t+ht9Mr8GKwZL//v3r+sB+0OMN+zqIEf8gFMvJkyd1gXTOa9YNDP//otrPAtSV/Jp9HfPff78Z0AEL0LUeXxivMfxD0wXTqfjj/2ugkf+wSrL9/YtpJEyS4S8WI5Ek/+GR/POPFjr//cenE6/kP9q4Fo/kr39/mdj+M/zFkGQCSj5i+ccPjLJ/GBgkuYOHQR1sNDpmAkb2LBmWwL///zKCIxwZM0VHR18G6p4uxeLLAA4tJMwEshiou1iMxXaHLGswA+t/YbhORuQUv2DBAnCifvxzI+enP3dQJUFg/vz5sOzgBBBgAPxX9j0YnH4JAAAAAElFTkSuQmCC) no-repeat top left;
-}
-.sf-button:hover .border-r,
-.sf-button-selected .border-r {
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAcCAYAAACtQ6WLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT5JREFUeNpiPHv27BkGBoaDQDzLyMjoJgMSYHrM3WX8hn1d0f///88DFRYhSzIuv2X5H8Rg/SfKIPDTkYH/l80OINffxMTkF9O/f/8ZQPgnwyuGl+wrGd6x7vf49+9fO9jYf3+Bkkj4NesmBqAV+SdPntQC6vzHgIz//gOawbqOGchOxtAJwp8Zr4F0e7D8/fuPAR38/P8eZIo0yz8skv8YvoIk+YE6/zNgAyD7sRqLkPzzjxY6/+HS+R+fTkZ8djLh08lCUCcuSWawJGbwMTGwg7zyBatX2Bj5QZKPsBrLzaICktzN8g/NWEYGZgYZjoC/wMiei5FMpFh8QPSU6Ojoy3Cd7EwiDBJsDgxiLNY7gLrKQGIsHAxSDHxAO2TZ/b8D+TVxcXF9MCtYtLiKLgDpfUDVsxITE1GyA0CAAQA2E/N8VuHyAAAAAABJRU5ErkJggg==) right top no-repeat;
-}
-.sf-button:hover .btn-bg,
-.sf-button-selected .btn-bg {
- color: #FFFFFF;
- text-shadow:0 1px 1px #6b9311;
- background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAcCAIAAAAvP0KbAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAEFJREFUeNpiPnv2LNMdvlymf///M/37B8R/QfQ/MP33L4j+B6Qh7L9//sHpf2h8MA1V+w/KRjYLaDaLCU8vQIABAFO3TxZriO4yAAAAAElFTkSuQmCC) repeat-x top left;
-}
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/header.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/header.html.twig
index acc76300b59d..d04cf37e6c7b 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/header.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/header.html.twig
@@ -1,25 +1,14 @@
-