Merge branch '3.0' into 3.1
* 3.0: [Yaml] fix exception contexts People - person singularization [Yaml] properly handle unindented collections [Serializer] Add test for ignored attributes during denormalization chomp newlines only at the end of YAML documents Fixed server status command when port has been omitted Update UPGRADE FROM 2.x to 3.0 fix removed commands wording in upgrade file Catch \Throwable Catch \Throwable [DependencyInjection] Avoid generating call_user_func in more cases [Validator] Support for DateTimeImmutable [FrameworkBundle] update upgrade instructions Use levenshtein level for better Bundle matching [WebProfilerBundle] Fix CORS ajax security issues remove methods that were needed for PHP 5.3 [DX][DI] Make Autowiring exceptions more future friendly
This commit is contained in:
commit
330c09b390
@ -398,8 +398,11 @@ UPGRADE FROM 2.x to 3.0
|
||||
</service>
|
||||
```
|
||||
|
||||
* 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:
|
||||
|
@ -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));
|
||||
|
@ -142,6 +142,7 @@ class ControllerNameParser
|
||||
$lev = levenshtein($nonExistentBundleName, $bundleName);
|
||||
if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) {
|
||||
$alternative = $bundleName;
|
||||
$shortest = $lev;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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'),
|
||||
);
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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));
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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) : '');
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"];
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -84,6 +84,12 @@
|
||||
<service id="configured_service" class="stdClass">
|
||||
<configurator service="configurator_service" method="configureStdClass"/>
|
||||
</service>
|
||||
<service id="configurator_service_simple" class="ConfClass" public="false">
|
||||
<argument>bar</argument>
|
||||
</service>
|
||||
<service id="configured_service_simple" class="stdClass">
|
||||
<configurator service="configurator_service_simple" method="configureStdClass"/>
|
||||
</service>
|
||||
<service id="decorated" class="stdClass"/>
|
||||
<service id="decorator_service" class="stdClass" decorates="decorated"/>
|
||||
<service id="decorator_service_with_name" class="stdClass" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/>
|
||||
@ -103,6 +109,12 @@
|
||||
<service id="service_from_static_method" class="Bar\FooClass">
|
||||
<factory class="Bar\FooClass" method="getInstance"/>
|
||||
</service>
|
||||
<service id="factory_simple" class="SimpleFactoryClass" public="false">
|
||||
<argument>foo</argument>
|
||||
</service>
|
||||
<service id="factory_service_simple" class="Bar">
|
||||
<factory service="factory_simple" method="getInstance"/>
|
||||
</service>
|
||||
<service id="alias_for_foo" alias="foo"/>
|
||||
<service id="alias_for_alias" alias="foo"/>
|
||||
</services>
|
||||
|
@ -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'
|
||||
|
@ -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(
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -24,6 +24,7 @@ class Parser
|
||||
const BLOCK_SCALAR_HEADER_PATTERN = '(?P<separator>\||>)(?P<modifiers>\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P<comments> +#.*)?';
|
||||
|
||||
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<leadspaces>\s+)(?P<value>.+?))?\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<key>'.Inline::REGEX_QUOTED_STRING.'|[^ \'"\[\{].*?) *\:(\s+(?P<value>.+?))?\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, '- ');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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 = <<<EOT
|
||||
a:
|
||||
-
|
||||
b:
|
||||
-
|
||||
bar: baz
|
||||
- foo
|
||||
d: e
|
||||
EOT;
|
||||
$expected = array(
|
||||
'a' => 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,
|
||||
|
Reference in New Issue
Block a user