diff --git a/UPGRADE-3.0.md b/UPGRADE-3.0.md
index 8925b91189..8c509b36f0 100644
--- a/UPGRADE-3.0.md
+++ b/UPGRADE-3.0.md
@@ -398,8 +398,11 @@ UPGRADE FROM 2.x to 3.0
```
- * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`,
- `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed.
+ * The `max_length` option was removed. Use the `attr` option instead by setting it to
+ an `array` with a `maxlength` key.
+
+ * The `ChoiceToBooleanArrayTransformer`, `ChoicesToBooleanArrayTransformer`,
+ `FixRadioInputListener`, and `FixCheckboxInputListener` classes were removed.
* The `choice_list` option of `ChoiceType` was removed.
@@ -636,6 +639,11 @@ UPGRADE FROM 2.x to 3.0
be removed in Symfony 3.0. Use the `debug:config`, `debug:container`,
`debug:router`, `debug:translation` and `lint:yaml` commands instead.
+ * The base `Controller`class is now abstract.
+
+ * The visibility of all methods of the base `Controller` class has been changed from
+ `public` to `protected`.
+
* The `getRequest` method of the base `Controller` class has been deprecated
since Symfony 2.4 and must be therefore removed in 3.0. The only reliable
way to get the `Request` object is to inject it in the action method.
@@ -1737,8 +1745,7 @@ UPGRADE FROM 2.x to 3.0
### WebProfiler
- * The `profiler:import` and `profiler:export` commands have been deprecated and
- will be removed in 3.0.
+ * The `profiler:import` and `profiler:export` commands have been removed.
* All the profiler storages different than `FileProfilerStorage` have been
removed. The removed classes are:
diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
index b6ec558701..d7cb9e7d08 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerStatusCommand.php
@@ -13,6 +13,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command;
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;
@@ -32,6 +33,7 @@ class ServerStatusCommand extends ServerCommand
$this
->setDefinition(array(
new InputArgument('address', InputArgument::OPTIONAL, 'Address:port', '127.0.0.1:8000'),
+ new InputOption('port', 'p', InputOption::VALUE_REQUIRED, 'Address port number', '8000'),
))
->setName('server:status')
->setDescription('Outputs the status of the built-in web server for the given address')
@@ -46,6 +48,10 @@ class ServerStatusCommand extends ServerCommand
$io = new SymfonyStyle($input, $output);
$address = $input->getArgument('address');
+ if (false === strpos($address, ':')) {
+ $address = $address.':'.$input->getOption('port');
+ }
+
// remove an orphaned lock file
if (file_exists($this->getLockFile($address)) && !$this->isServerRunning($address)) {
unlink($this->getLockFile($address));
diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
index 873c736841..374d0eba10 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php
@@ -142,6 +142,7 @@ class ControllerNameParser
$lev = levenshtein($nonExistentBundleName, $bundleName);
if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) {
$alternative = $bundleName;
+ $shortest = $lev;
}
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
index 4718c1eb0b..0fe47b0908 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php
@@ -59,8 +59,8 @@ class ControllerNameParserTest extends TestCase
{
$parser = $this->createParser();
- $this->assertEquals('FooBundle:Default:index', $parser->build('TestBundle\FooBundle\Controller\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
- $this->assertEquals('FooBundle:Sub\Default:index', $parser->build('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
+ $this->assertEquals('FoooooBundle:Default:index', $parser->build('TestBundle\FooBundle\Controller\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
+ $this->assertEquals('FoooooBundle:Sub\Default:index', $parser->build('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction'), '->parse() converts a class::method string to a short a:b:c notation string');
try {
$parser->build('TestBundle\FooBundle\Controller\DefaultController::index');
@@ -132,8 +132,9 @@ class ControllerNameParserTest extends TestCase
public function getInvalidBundleNameTests()
{
return array(
- array('FoodBundle:Default:index', 'FooBundle:Default:index'),
- array('CrazyBundle:Default:index', false),
+ 'Alternative will be found using levenshtein' => array('FoodBundle:Default:index', 'FooBundle:Default:index'),
+ 'Alternative will be found using partial match' => array('FabpotFooBund:Default:index', 'FabpotFooBundle:Default:index'),
+ 'Bundle does not exist at all' => array('CrazyBundle:Default:index', false),
);
}
@@ -162,6 +163,7 @@ class ControllerNameParserTest extends TestCase
$bundles = array(
'SensioFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'),
+ 'FoooooBundle' => $this->getBundle('TestBundle\FooBundle', 'FoooooBundle'),
'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'),
'FabpotFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
);
diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
index c9103ae419..bd8213721e 100644
--- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
+++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig
@@ -82,6 +82,20 @@
requestStack = [],
+ extractHeaders = function(xhr, stackElement) {
+ // Here we avoid to call xhr.getResponseHeader in order to
+ // prevent polluting the console with CORS security errors
+ var allHeaders = xhr.getAllResponseHeaders();
+ var ret;
+
+ if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) {
+ stackElement.profile = ret[1];
+ }
+ if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) {
+ stackElement.profilerUrl = ret[1];
+ }
+ },
+
renderAjaxRequests = function() {
var requestCounter = document.querySelectorAll('.sf-toolbar-ajax-requests');
if (!requestCounter.length) {
@@ -255,8 +269,7 @@
stackElement.loading = false;
stackElement.error = self.status < 200 || self.status >= 400;
stackElement.statusCode = self.status;
- stackElement.profile = self.getResponseHeader("X-Debug-Token");
- stackElement.profilerUrl = self.getResponseHeader("X-Debug-Token-Link");
+ extractHeaders(self, stackElement);
Sfjs.renderAjaxRequests();
}
diff --git a/src/Symfony/Component/Console/Helper/ProgressIndicator.php b/src/Symfony/Component/Console/Helper/ProgressIndicator.php
index ccf9771bcf..f90a85c291 100644
--- a/src/Symfony/Component/Console/Helper/ProgressIndicator.php
+++ b/src/Symfony/Component/Console/Helper/ProgressIndicator.php
@@ -76,42 +76,6 @@ class ProgressIndicator
$this->display();
}
- /**
- * Gets the current indicator message.
- *
- * @return string|null
- *
- * @internal for PHP 5.3 compatibility
- */
- public function getMessage()
- {
- return $this->message;
- }
-
- /**
- * Gets the progress bar start time.
- *
- * @return int The progress bar start time
- *
- * @internal for PHP 5.3 compatibility
- */
- public function getStartTime()
- {
- return $this->startTime;
- }
-
- /**
- * Gets the current animated indicator character.
- *
- * @return string
- *
- * @internal for PHP 5.3 compatibility
- */
- public function getCurrentValue()
- {
- return $this->indicatorValues[$this->indicatorCurrent % count($this->indicatorValues)];
- }
-
/**
* Starts the indicator output.
*
@@ -294,13 +258,13 @@ class ProgressIndicator
{
return array(
'indicator' => function (ProgressIndicator $indicator) {
- return $indicator->getCurrentValue();
+ return $indicator->indicatorValues[$indicator->indicatorCurrent % count($indicator->indicatorValues)];
},
'message' => function (ProgressIndicator $indicator) {
- return $indicator->getMessage();
+ return $indicator->message;
},
'elapsed' => function (ProgressIndicator $indicator) {
- return Helper::formatTime(time() - $indicator->getStartTime());
+ return Helper::formatTime(time() - $indicator->startTime);
},
'memory' => function () {
return Helper::formatMemory(memory_get_usage(true));
diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php
index 5fdcd5cdb4..f4932fc82c 100644
--- a/src/Symfony/Component/Debug/ErrorHandler.php
+++ b/src/Symfony/Component/Debug/ErrorHandler.php
@@ -580,6 +580,8 @@ class ErrorHandler
}
} catch (\Exception $exception) {
// Handled below
+ } catch (\Throwable $exception) {
+ // Handled below
}
if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) {
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
index 8e1b06e0ff..fdf0edcfb4 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php
@@ -45,8 +45,8 @@ class AutowirePass implements CompilerPassInterface
$this->completeDefinition($id, $definition);
}
}
- } catch (\Error $e) {
} catch (\Exception $e) {
+ } catch (\Throwable $e) {
}
spl_autoload_unregister($throwingAutoloader);
@@ -283,7 +283,7 @@ class AutowirePass implements CompilerPassInterface
try {
$this->completeDefinition($argumentId, $argumentDefinition);
- } catch (\RuntimeException $e) {
+ } catch (RuntimeException $e) {
$classOrInterface = $typeHint->isInterface() ? 'interface' : 'class';
$message = sprintf('Unable to autowire argument of type "%s" for the service "%s". No services were found matching this %s and it cannot be auto-registered.', $typeHint->name, $id, $classOrInterface);
throw new RuntimeException($message, 0, $e);
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 57b0f086c0..ce0336b3e4 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -542,6 +542,10 @@ class PhpDumper extends Dumper
return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName);
}
+ if (0 === strpos($class, 'new ')) {
+ return sprintf(" (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
+ }
+
return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName);
}
@@ -723,6 +727,10 @@ EOF;
return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : '');
}
+ if (0 === strpos($class, 'new ')) {
+ return sprintf(" $return{$instantiation}(%s)->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : '');
+ }
+
return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : '');
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
index 96f334fdd1..f499635604 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
@@ -78,6 +78,15 @@ $container
->register('configured_service', 'stdClass')
->setConfigurator(array(new Reference('configurator_service'), 'configureStdClass'))
;
+$container
+ ->register('configurator_service_simple', 'ConfClass')
+ ->addArgument('bar')
+ ->setPublic(false)
+;
+$container
+ ->register('configured_service_simple', 'stdClass')
+ ->setConfigurator(array(new Reference('configurator_service_simple'), 'configureStdClass'))
+;
$container
->register('decorated', 'stdClass')
;
@@ -111,5 +120,14 @@ $container
->register('service_from_static_method', 'Bar\FooClass')
->setFactory(array('Bar\FooClass', 'getInstance'))
;
+$container
+ ->register('factory_simple', 'SimpleFactoryClass')
+ ->addArgument('foo')
+ ->setPublic(false)
+;
+$container
+ ->register('factory_service_simple', 'Bar')
+ ->setFactory(array(new Reference('factory_simple'), 'getInstance'))
+;
return $container;
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
index f6536980aa..3b24ef8ffb 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
@@ -14,6 +14,8 @@ digraph sc {
node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_configurator_service [label="configurator_service\nConfClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_configured_service [label="configured_service\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_configurator_service_simple [label="configurator_service_simple\nConfClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_configured_service_simple [label="configured_service_simple\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_decorated [label="decorated\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_decorator_service [label="decorator_service\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_decorator_service_with_name [label="decorator_service_with_name\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
@@ -22,6 +24,8 @@ digraph sc {
node_factory_service [label="factory_service\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_new_factory_service [label="new_factory_service\nFooBarBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_from_static_method [label="service_from_static_method\nBar\\FooClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_factory_simple [label="factory_simple\nSimpleFactoryClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php
index cc2a18dcd1..6c56cfcebf 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php
@@ -40,7 +40,7 @@ class ProjectServiceContainer extends Container
*/
protected function getServiceFromAnonymousFactoryService()
{
- return $this->services['service_from_anonymous_factory'] = call_user_func(array(new \Bar\FooClass(), 'getInstance'));
+ return $this->services['service_from_anonymous_factory'] = (new \Bar\FooClass())->getInstance();
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
index a29f7dd768..cb84452bca 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
@@ -28,12 +28,16 @@ class ProjectServiceContainer extends Container
'bar' => 'getBarService',
'baz' => 'getBazService',
'configurator_service' => 'getConfiguratorServiceService',
+ 'configurator_service_simple' => 'getConfiguratorServiceSimpleService',
'configured_service' => 'getConfiguredServiceService',
+ 'configured_service_simple' => 'getConfiguredServiceSimpleService',
'decorated' => 'getDecoratedService',
'decorator_service' => 'getDecoratorServiceService',
'decorator_service_with_name' => 'getDecoratorServiceWithNameService',
'deprecated_service' => 'getDeprecatedServiceService',
'factory_service' => 'getFactoryServiceService',
+ 'factory_service_simple' => 'getFactoryServiceSimpleService',
+ 'factory_simple' => 'getFactorySimpleService',
'foo' => 'getFooService',
'foo.baz' => 'getFoo_BazService',
'foo_bar' => 'getFooBarService',
@@ -104,6 +108,23 @@ class ProjectServiceContainer extends Container
return $instance;
}
+ /**
+ * Gets the 'configured_service_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \stdClass A stdClass instance.
+ */
+ protected function getConfiguredServiceSimpleService()
+ {
+ $this->services['configured_service_simple'] = $instance = new \stdClass();
+
+ $this->get('configurator_service_simple')->configureStdClass($instance);
+
+ return $instance;
+ }
+
/**
* Gets the 'decorated' service.
*
@@ -173,6 +194,19 @@ class ProjectServiceContainer extends Container
return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
}
+ /**
+ * Gets the 'factory_service_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \Bar A Bar instance.
+ */
+ protected function getFactoryServiceSimpleService()
+ {
+ return $this->services['factory_service_simple'] = $this->get('factory_simple')->getInstance();
+ }
+
/**
* Gets the 'foo' service.
*
@@ -334,6 +368,40 @@ class ProjectServiceContainer extends Container
return $instance;
}
+ /**
+ * Gets the 'configurator_service_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * This service is private.
+ * If you want to be able to request this service from the container directly,
+ * make it public, otherwise you might end up with broken code.
+ *
+ * @return \ConfClass A ConfClass instance.
+ */
+ protected function getConfiguratorServiceSimpleService()
+ {
+ return $this->services['configurator_service_simple'] = new \ConfClass('bar');
+ }
+
+ /**
+ * Gets the 'factory_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * This service is private.
+ * If you want to be able to request this service from the container directly,
+ * make it public, otherwise you might end up with broken code.
+ *
+ * @return \SimpleFactoryClass A SimpleFactoryClass instance.
+ */
+ protected function getFactorySimpleService()
+ {
+ return $this->services['factory_simple'] = new \SimpleFactoryClass('foo');
+ }
+
/**
* Gets the 'inlined' service.
*
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
index 5386b12a99..4fd1ac90f3 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
@@ -30,10 +30,12 @@ class ProjectServiceContainer extends Container
'bar' => 'getBarService',
'baz' => 'getBazService',
'configured_service' => 'getConfiguredServiceService',
+ 'configured_service_simple' => 'getConfiguredServiceSimpleService',
'decorator_service' => 'getDecoratorServiceService',
'decorator_service_with_name' => 'getDecoratorServiceWithNameService',
'deprecated_service' => 'getDeprecatedServiceService',
'factory_service' => 'getFactoryServiceService',
+ 'factory_service_simple' => 'getFactoryServiceSimpleService',
'foo' => 'getFooService',
'foo.baz' => 'getFoo_BazService',
'foo_bar' => 'getFooBarService',
@@ -114,6 +116,23 @@ class ProjectServiceContainer extends Container
return $instance;
}
+ /**
+ * Gets the 'configured_service_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \stdClass A stdClass instance.
+ */
+ protected function getConfiguredServiceSimpleService()
+ {
+ $this->services['configured_service_simple'] = $instance = new \stdClass();
+
+ (new \ConfClass('bar'))->configureStdClass($instance);
+
+ return $instance;
+ }
+
/**
* Gets the 'decorator_service' service.
*
@@ -170,6 +189,19 @@ class ProjectServiceContainer extends Container
return $this->services['factory_service'] = $this->get('foo.baz')->getInstance();
}
+ /**
+ * Gets the 'factory_service_simple' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return \Bar A Bar instance.
+ */
+ protected function getFactoryServiceSimpleService()
+ {
+ return $this->services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance();
+ }
+
/**
* Gets the 'foo' service.
*
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
index 4ddb8655c5..d3974c07b0 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
@@ -84,6 +84,12 @@
+
+ bar
+
+
+
+
@@ -103,6 +109,12 @@
+
+ foo
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
index 6efeb37e74..4a97dcadff 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
@@ -67,6 +67,13 @@ services:
configured_service:
class: stdClass
configurator: ['@configurator_service', configureStdClass]
+ configurator_service_simple:
+ class: ConfClass
+ public: false
+ arguments: ['bar']
+ configured_service_simple:
+ class: stdClass
+ configurator: ['@configurator_service_simple', configureStdClass]
decorated:
class: stdClass
decorator_service:
@@ -93,5 +100,12 @@ services:
service_from_static_method:
class: Bar\FooClass
factory: [Bar\FooClass, getInstance]
+ factory_simple:
+ class: SimpleFactoryClass
+ public: false
+ arguments: ['foo']
+ factory_service_simple:
+ class: Bar
+ factory: ['@factory_simple', getInstance]
alias_for_foo: '@foo'
alias_for_alias: '@foo'
diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
index b04d09bf1f..5d91a9fd1e 100644
--- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
+++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php
@@ -312,6 +312,19 @@ class ObjectNormalizerTest extends \PHPUnit_Framework_TestCase
);
}
+ public function testIgnoredAttributesDenormalize()
+ {
+ $this->normalizer->setIgnoredAttributes(array('fooBar', 'bar', 'baz'));
+
+ $obj = new ObjectDummy();
+ $obj->setFoo('foo');
+
+ $this->assertEquals(
+ $obj,
+ $this->normalizer->denormalize(array('fooBar' => 'fooBar', 'foo' => 'foo', 'baz' => 'baz'), __NAMESPACE__.'\ObjectDummy')
+ );
+ }
+
public function provideCallbacks()
{
return array(
diff --git a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php
index 681b7bdbee..af956ee06b 100644
--- a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php
+++ b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php
@@ -34,7 +34,7 @@ class DateTimeValidator extends DateValidator
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\DateTime');
}
- if (null === $value || '' === $value || $value instanceof \DateTime) {
+ if (null === $value || '' === $value || $value instanceof \DateTimeInterface) {
return;
}
diff --git a/src/Symfony/Component/Validator/Constraints/DateValidator.php b/src/Symfony/Component/Validator/Constraints/DateValidator.php
index bfeb5fca30..ed836de9ac 100644
--- a/src/Symfony/Component/Validator/Constraints/DateValidator.php
+++ b/src/Symfony/Component/Validator/Constraints/DateValidator.php
@@ -47,7 +47,7 @@ class DateValidator extends ConstraintValidator
throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Date');
}
- if (null === $value || '' === $value || $value instanceof \DateTime) {
+ if (null === $value || '' === $value || $value instanceof \DateTimeInterface) {
return;
}
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php
index 28206025d5..8fb2024dd5 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/DateTimeValidatorTest.php
@@ -42,6 +42,13 @@ class DateTimeValidatorTest extends AbstractConstraintValidatorTest
$this->assertNoViolation();
}
+ public function testDateTimeImmutableClassIsValid()
+ {
+ $this->validator->validate(new \DateTimeImmutable(), new DateTime());
+
+ $this->assertNoViolation();
+ }
+
/**
* @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
*/
diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php
index 67bb2340c3..ec62de6281 100644
--- a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php
+++ b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php
@@ -42,6 +42,13 @@ class DateValidatorTest extends AbstractConstraintValidatorTest
$this->assertNoViolation();
}
+ public function testDateTimeImmutableClassIsValid()
+ {
+ $this->validator->validate(new \DateTimeImmutable(), new Date());
+
+ $this->assertNoViolation();
+ }
+
/**
* @expectedException \Symfony\Component\Validator\Exception\UnexpectedTypeException
*/
diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
index da6e51d6b4..ee70b9d0c7 100644
--- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
+++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php
@@ -128,6 +128,8 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface
$this->dumpLine(-1);
} catch (\Exception $exception) {
// Re-thrown below
+ } catch (\Throwable $exception) {
+ // Re-thrown below
}
if ($output) {
$this->setOutput($prevOutput);
diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php
index c45ba46b87..de1101f009 100644
--- a/src/Symfony/Component/Yaml/Parser.php
+++ b/src/Symfony/Component/Yaml/Parser.php
@@ -24,6 +24,7 @@ class Parser
const BLOCK_SCALAR_HEADER_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?';
private $offset = 0;
+ private $totalNumberOfLines;
private $lines = array();
private $currentLineNb = -1;
private $currentLine = '';
@@ -32,11 +33,13 @@ class Parser
/**
* Constructor.
*
- * @param int $offset The offset of YAML document (used for line numbers in error messages)
+ * @param int $offset The offset of YAML document (used for line numbers in error messages)
+ * @param int|null $totalNumberOfLines The overall number of lines being parsed
*/
- public function __construct($offset = 0)
+ public function __construct($offset = 0, $totalNumberOfLines = null)
{
$this->offset = $offset;
+ $this->totalNumberOfLines = $totalNumberOfLines;
}
/**
@@ -85,6 +88,10 @@ class Parser
$value = $this->cleanup($value);
$this->lines = explode("\n", $value);
+ if (null === $this->totalNumberOfLines) {
+ $this->totalNumberOfLines = count($this->lines);
+ }
+
if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) {
$mbEncoding = mb_internal_encoding();
mb_internal_encoding('UTF-8');
@@ -106,7 +113,7 @@ class Parser
$isRef = $mergeNode = false;
if (preg_match('#^\-((?P\s+)(?P.+?))?\s*$#u', $this->currentLine, $values)) {
if ($context && 'mapping' == $context) {
- throw new ParseException('You cannot define a sequence item when in a mapping');
+ throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine);
}
$context = 'sequence';
@@ -118,7 +125,7 @@ class Parser
// array
if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) {
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$data[] = $parser->parse($this->getNextEmbedBlock(null, true), $flags);
} else {
@@ -127,7 +134,7 @@ class Parser
) {
// this is a compact notation element, add to next block and parse
$c = $this->getRealCurrentLineNb();
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$block = $values['value'];
@@ -145,7 +152,7 @@ class Parser
}
} elseif (preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P.+?))?\s*$#u', $this->currentLine, $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'")))) {
if ($context && 'sequence' == $context) {
- throw new ParseException('You cannot define a mapping item when in a sequence');
+ throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine);
}
$context = 'mapping';
@@ -192,7 +199,7 @@ class Parser
$value = $this->getNextEmbedBlock();
}
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$parsed = $parser->parse($value, $flags);
@@ -243,7 +250,7 @@ class Parser
}
} else {
$c = $this->getRealCurrentLineNb() + 1;
- $parser = new self($c);
+ $parser = new self($c, $this->totalNumberOfLines);
$parser->refs = &$this->refs;
$value = $parser->parse($this->getNextEmbedBlock(), $flags);
// Spec: Keys MUST be unique; first one wins.
@@ -266,7 +273,7 @@ class Parser
} else {
// multiple documents are not supported
if ('---' === $this->currentLine) {
- throw new ParseException('Multiple documents are not supported.');
+ throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine);
}
// 1-liner optionally followed by newline(s)
@@ -511,7 +518,7 @@ class Parser
}
if (!array_key_exists($value, $this->refs)) {
- throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLine);
+ throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine);
}
return $this->refs[$value];
@@ -609,6 +616,8 @@ class Parser
if ($notEOF) {
$blockLines[] = '';
$this->moveToPreviousLine();
+ } elseif (!$notEOF && !$this->isCurrentLineLastLineInDocument()) {
+ $blockLines[] = '';
}
// folded style
@@ -715,6 +724,11 @@ class Parser
return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#';
}
+ private function isCurrentLineLastLineInDocument()
+ {
+ return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1);
+ }
+
/**
* Cleanups a YAML string to be parsed.
*
@@ -792,7 +806,7 @@ class Parser
*/
private function isStringUnIndentedCollectionItem()
{
- return 0 === strpos($this->currentLine, '- ');
+ return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- ');
}
/**
diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php
index bddf969744..4ebee0fd89 100644
--- a/src/Symfony/Component/Yaml/Tests/ParserTest.php
+++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php
@@ -633,7 +633,7 @@ EOF;
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
- * @expectedExceptionMessage Multiple documents are not supported.
+ * @expectedExceptionMessageRegExp /^Multiple documents are not supported.+/
*/
public function testMultipleDocumentsNotSupportedException()
{
@@ -665,6 +665,34 @@ EOF
);
}
+ public function testSequenceInMappingStartedBySingleDashLine()
+ {
+ $yaml = << array(
+ array(
+ 'b' => array(
+ array(
+ 'bar' => 'baz',
+ ),
+ ),
+ ),
+ 'foo',
+ ),
+ 'd' => 'e',
+ );
+
+ $this->assertSame($expected, $this->parser->parse($yaml));
+ }
+
/**
* @expectedException \Symfony\Component\Yaml\Exception\ParseException
*/
@@ -1014,6 +1042,7 @@ EOT
foo
# bar
baz
+
EOT
,
),
@@ -1042,7 +1071,7 @@ EOT;
$expected = array(
'foo' => array(
'bar' => array(
- 'scalar-block' => 'line1 line2>',
+ 'scalar-block' => "line1 line2>\n",
),
'baz' => array(
'foobar' => null,