Merge branch '3.3' into 3.4
* 3.3: [DI] use assertStringEqualsFile when possible [VarDumper] Adapt to php 7.2 changes [DI] Fix using private services in expressions [Form][TwigBridge] Don't render _method in form_rest() for a child form [Form] Static call TimezoneType::getTimezones Removed references for non existent validator constraints Suggest using quotes instead of Yaml::PARSE_KEYS_AS_STRINGS [DI] Fix test [Cache] Handle unserialization failures for Memcached Remove unused prop + added @deprecated Remove unused mocks/vars [DoctrineBridge][PropertyInfo] Added support for Doctrine Embeddables [Validator] Fix IbanValidator for ukrainian IBANs Router: allow HEAD method to be defined first [WebProfilerBundle] Display trace and context in the logger profiler Fixing a bug where if a core class was autowired, autowiring tried to autowire optional args as if they were required
This commit is contained in:
commit
4a3b3bef03
|
@ -367,8 +367,7 @@ Yaml
|
||||||
|
|
||||||
* Deprecated support for implicitly parsing non-string mapping keys as strings.
|
* Deprecated support for implicitly parsing non-string mapping keys as strings.
|
||||||
Mapping keys that are no strings will lead to a `ParseException` in Symfony
|
Mapping keys that are no strings will lead to a `ParseException` in Symfony
|
||||||
4.0. Use the `PARSE_KEYS_AS_STRINGS` flag to opt-in for keys to be parsed as
|
4.0. Use quotes to opt-in for keys to be parsed as strings.
|
||||||
strings.
|
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
|
@ -376,7 +375,6 @@ Yaml
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
null: null key
|
||||||
true: boolean true
|
true: boolean true
|
||||||
1: integer key
|
|
||||||
2.0: float key
|
2.0: float key
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
|
@ -388,13 +386,12 @@ Yaml
|
||||||
```php
|
```php
|
||||||
|
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
"null": null key
|
||||||
true: boolean true
|
"true": boolean true
|
||||||
1: integer key
|
"2.0": float key
|
||||||
2.0: float key
|
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS);
|
Yaml::parse($yaml);
|
||||||
```
|
```
|
||||||
|
|
||||||
* Omitting the key of a mapping is deprecated and will throw a `ParseException` in Symfony 4.0.
|
* Omitting the key of a mapping is deprecated and will throw a `ParseException` in Symfony 4.0.
|
||||||
|
|
|
@ -336,15 +336,12 @@ FrameworkBundle
|
||||||
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ValidateWorkflowsPass` class
|
* The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ValidateWorkflowsPass` class
|
||||||
has been removed. Use the `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass`
|
has been removed. Use the `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass`
|
||||||
class instead.
|
class instead.
|
||||||
|
|
||||||
* Using the `KERNEL_DIR` environment variable and the automatic guessing based
|
* Using the `KERNEL_DIR` environment variable and the automatic guessing based
|
||||||
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
|
on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()`
|
||||||
method implementation. Set the `KERNEL_CLASS` environment variable to the
|
method implementation. Set the `KERNEL_CLASS` environment variable to the
|
||||||
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
|
fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()`
|
||||||
or `KernelTestCase::getKernelClass()` method instead.
|
or `KernelTestCase::getKernelClass()` method instead.
|
||||||
|
|
||||||
* The methods `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()`
|
|
||||||
have been removed.
|
|
||||||
|
|
||||||
* The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed.
|
* The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed.
|
||||||
Use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead.
|
Use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead.
|
||||||
|
@ -556,10 +553,10 @@ TwigBridge
|
||||||
|
|
||||||
* The `TwigRendererEngine::setEnvironment()` method has been removed.
|
* The `TwigRendererEngine::setEnvironment()` method has been removed.
|
||||||
Pass the Twig Environment as second argument of the constructor instead.
|
Pass the Twig Environment as second argument of the constructor instead.
|
||||||
|
|
||||||
* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
|
* Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability
|
||||||
to pass a command name as first argument.
|
to pass a command name as first argument.
|
||||||
|
|
||||||
* Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
|
* Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability
|
||||||
to pass a command name as first argument.
|
to pass a command name as first argument.
|
||||||
|
|
||||||
|
@ -645,8 +642,8 @@ Yaml
|
||||||
throws a `ParseException`.
|
throws a `ParseException`.
|
||||||
|
|
||||||
* Removed support for implicitly parsing non-string mapping keys as strings.
|
* Removed support for implicitly parsing non-string mapping keys as strings.
|
||||||
Mapping keys that are no strings will result in a `ParseException`. Use the
|
Mapping keys that are no strings will result in a `ParseException`. Use
|
||||||
`PARSE_KEYS_AS_STRINGS` flag to opt-in for keys to be parsed as strings.
|
quotes to opt-in for keys to be parsed as strings.
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
|
@ -654,7 +651,6 @@ Yaml
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
null: null key
|
||||||
true: boolean true
|
true: boolean true
|
||||||
1: integer key
|
|
||||||
2.0: float key
|
2.0: float key
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
|
@ -666,13 +662,12 @@ Yaml
|
||||||
```php
|
```php
|
||||||
|
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
"null": null key
|
||||||
true: boolean true
|
"true": boolean true
|
||||||
1: integer key
|
"2.0": float key
|
||||||
2.0: float key
|
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS);
|
Yaml::parse($yaml);
|
||||||
```
|
```
|
||||||
|
|
||||||
* Omitting the key of a mapping is not supported anymore and throws a `ParseException`.
|
* Omitting the key of a mapping is not supported anymore and throws a `ParseException`.
|
||||||
|
|
|
@ -50,7 +50,17 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array_merge($metadata->getFieldNames(), $metadata->getAssociationNames());
|
$properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames());
|
||||||
|
|
||||||
|
if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && $metadata->embeddedClasses) {
|
||||||
|
$properties = array_filter($properties, function ($property) {
|
||||||
|
return false === strpos($property, '.');
|
||||||
|
});
|
||||||
|
|
||||||
|
$properties = array_merge($properties, array_keys($metadata->embeddedClasses));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -105,6 +115,10 @@ class DoctrineExtractor implements PropertyListExtractorInterface, PropertyTypeE
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && isset($metadata->embeddedClasses[$property])) {
|
||||||
|
return array(new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class']));
|
||||||
|
}
|
||||||
|
|
||||||
if ($metadata->hasField($property)) {
|
if ($metadata->hasField($property)) {
|
||||||
$typeOfField = $metadata->getTypeOfField($property);
|
$typeOfField = $metadata->getTypeOfField($property);
|
||||||
$nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property);
|
$nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property);
|
||||||
|
|
|
@ -66,6 +66,21 @@ class DoctrineExtractorTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testGetPropertiesWithEmbedded()
|
||||||
|
{
|
||||||
|
if (!class_exists('Doctrine\ORM\Mapping\Embedded')) {
|
||||||
|
$this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->assertEquals(
|
||||||
|
array(
|
||||||
|
'id',
|
||||||
|
'embedded',
|
||||||
|
),
|
||||||
|
$this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dataProvider typesProvider
|
* @dataProvider typesProvider
|
||||||
*/
|
*/
|
||||||
|
@ -74,6 +89,27 @@ class DoctrineExtractorTest extends TestCase
|
||||||
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, array()));
|
$this->assertEquals($type, $this->extractor->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, array()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExtractWithEmbedded()
|
||||||
|
{
|
||||||
|
if (!class_exists('Doctrine\ORM\Mapping\Embedded')) {
|
||||||
|
$this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$expectedTypes = array(new Type(
|
||||||
|
Type::BUILTIN_TYPE_OBJECT,
|
||||||
|
false,
|
||||||
|
'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineEmbeddable'
|
||||||
|
));
|
||||||
|
|
||||||
|
$actualTypes = $this->extractor->getTypes(
|
||||||
|
'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded',
|
||||||
|
'embedded',
|
||||||
|
array()
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->assertEquals($expectedTypes, $actualTypes);
|
||||||
|
}
|
||||||
|
|
||||||
public function typesProvider()
|
public function typesProvider()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\Column;
|
||||||
|
use Doctrine\ORM\Mapping\Embeddable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Embeddable
|
||||||
|
*
|
||||||
|
* @author Udaltsov Valentin <udaltsov.valentin@gmail.com>
|
||||||
|
*/
|
||||||
|
class DoctrineEmbeddable
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Column(type="string")
|
||||||
|
*/
|
||||||
|
protected $field;
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures;
|
||||||
|
|
||||||
|
use Doctrine\ORM\Mapping\Column;
|
||||||
|
use Doctrine\ORM\Mapping\Entity;
|
||||||
|
use Doctrine\ORM\Mapping\Id;
|
||||||
|
use Doctrine\ORM\Mapping\Embedded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Entity
|
||||||
|
*
|
||||||
|
* @author Udaltsov Valentin <udaltsov.valentin@gmail.com>
|
||||||
|
*/
|
||||||
|
class DoctrineWithEmbedded
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
* @Column(type="smallint")
|
||||||
|
*/
|
||||||
|
public $id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Embedded(class="DoctrineEmbeddable")
|
||||||
|
*/
|
||||||
|
protected $embedded;
|
||||||
|
}
|
|
@ -339,7 +339,7 @@
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{%- endfor %}
|
{%- endfor %}
|
||||||
|
|
||||||
{% if not form.methodRendered %}
|
{% if not form.methodRendered and form.parent is null %}
|
||||||
{%- do form.setMethodRendered() -%}
|
{%- do form.setMethodRendered() -%}
|
||||||
{% set method = method|upper %}
|
{% set method = method|upper %}
|
||||||
{%- if method in ["GET", "POST"] -%}
|
{%- if method in ["GET", "POST"] -%}
|
||||||
|
|
|
@ -71,10 +71,6 @@ class RouterDebugCommandTest extends TestCase
|
||||||
->will($this->returnValue($routeCollection))
|
->will($this->returnValue($routeCollection))
|
||||||
;
|
;
|
||||||
|
|
||||||
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader')
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
|
|
||||||
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
|
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
|
||||||
$container
|
$container
|
||||||
->expects($this->atLeastOnce())
|
->expects($this->atLeastOnce())
|
||||||
|
|
|
@ -70,10 +70,6 @@ class RouterMatchCommandTest extends TestCase
|
||||||
->will($this->returnValue($requestContext))
|
->will($this->returnValue($requestContext))
|
||||||
;
|
;
|
||||||
|
|
||||||
$loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader')
|
|
||||||
->disableOriginalConstructor()
|
|
||||||
->getMock();
|
|
||||||
|
|
||||||
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
|
$container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock();
|
||||||
$container
|
$container
|
||||||
->expects($this->atLeastOnce())
|
->expects($this->atLeastOnce())
|
||||||
|
|
|
@ -19,8 +19,6 @@ use Symfony\Component\Console\Tester\CommandTester;
|
||||||
*/
|
*/
|
||||||
class CachePoolClearCommandTest extends WebTestCase
|
class CachePoolClearCommandTest extends WebTestCase
|
||||||
{
|
{
|
||||||
private $application;
|
|
||||||
|
|
||||||
protected function setUp()
|
protected function setUp()
|
||||||
{
|
{
|
||||||
static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml'));
|
static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml'));
|
||||||
|
|
|
@ -61,7 +61,7 @@ class ConfigDebugCommandTest extends WebTestCase
|
||||||
public function testDumpUndefinedBundleOption()
|
public function testDumpUndefinedBundleOption()
|
||||||
{
|
{
|
||||||
$tester = $this->createCommandTester();
|
$tester = $this->createCommandTester();
|
||||||
$ret = $tester->execute(array('name' => 'TestBundle', 'path' => 'foo'));
|
$tester->execute(array('name' => 'TestBundle', 'path' => 'foo'));
|
||||||
|
|
||||||
$this->assertContains('Unable to find configuration for "test.foo"', $tester->getDisplay());
|
$this->assertContains('Unable to find configuration for "test.foo"', $tester->getDisplay());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,8 @@ class UserPasswordEncoderCommand extends ContainerAwareCommand
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* @deprecated since version 3.3, to be removed in 4.0
|
||||||
*/
|
*/
|
||||||
protected function getContainer()
|
protected function getContainer()
|
||||||
{
|
{
|
||||||
|
|
|
@ -224,31 +224,33 @@
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{% macro render_log_message(category, log_index, log) %}
|
{% macro render_log_message(category, log_index, log) %}
|
||||||
{% if log.context.exception.trace is defined %}
|
{% set has_context = log.context is defined and log.context is not empty %}
|
||||||
|
{% set has_trace = log.context.exception.trace is defined %}
|
||||||
|
|
||||||
|
{% if not has_context %}
|
||||||
|
{{ profiler_dump_log(log.message) }}
|
||||||
|
{% else %}
|
||||||
{{ profiler_dump_log(log.message, log.context) }}
|
{{ profiler_dump_log(log.message, log.context) }}
|
||||||
|
|
||||||
{% set context_id = 'context-' ~ category ~ '-' ~ log_index %}
|
<div class="text-small font-normal">
|
||||||
|
{% set context_id = 'context-' ~ category ~ '-' ~ log_index %}
|
||||||
|
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide context">Show context</a>
|
||||||
|
|
||||||
<span class="metadata">
|
{% if has_trace %}
|
||||||
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide trace">Show trace</a>
|
|
||||||
|
{% set trace_id = 'trace-' ~ category ~ '-' ~ log_index %}
|
||||||
|
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ trace_id }}" data-toggle-alt-content="Hide trace">Show trace</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden">
|
<div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden">
|
||||||
|
{{ profiler_dump(log.context, maxDepth=1) }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if has_trace %}
|
||||||
|
<div id="{{ trace_id }}" class="context sf-toggle-content sf-toggle-hidden">
|
||||||
{{ profiler_dump(log.context.exception.trace, maxDepth=1) }}
|
{{ profiler_dump(log.context.exception.trace, maxDepth=1) }}
|
||||||
</div>
|
</div>
|
||||||
</span>
|
{% endif %}
|
||||||
{% elseif log.context is defined and log.context is not empty %}
|
|
||||||
{{ profiler_dump_log(log.message, log.context) }}
|
|
||||||
|
|
||||||
{% set context_id = 'context-' ~ category ~ '-' ~ log_index %}
|
|
||||||
|
|
||||||
<span class="metadata">
|
|
||||||
<a class="btn btn-link text-small sf-toggle" data-toggle-selector="#{{ context_id }}" data-toggle-alt-content="Hide context">Show context</a>
|
|
||||||
|
|
||||||
<div id="{{ context_id }}" class="context sf-toggle-content sf-toggle-hidden">
|
|
||||||
{{ profiler_dump(log.context, maxDepth=1) }}
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
{% else %}
|
|
||||||
{{ profiler_dump_log(log.message) }}
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
|
@ -26,6 +26,7 @@ trait MemcachedTrait
|
||||||
'persistent_id' => null,
|
'persistent_id' => null,
|
||||||
'username' => null,
|
'username' => null,
|
||||||
'password' => null,
|
'password' => null,
|
||||||
|
'serializer' => 'php',
|
||||||
);
|
);
|
||||||
|
|
||||||
private $client;
|
private $client;
|
||||||
|
@ -194,7 +195,14 @@ trait MemcachedTrait
|
||||||
*/
|
*/
|
||||||
protected function doFetch(array $ids)
|
protected function doFetch(array $ids)
|
||||||
{
|
{
|
||||||
return $this->checkResultCode($this->client->getMulti($ids));
|
$unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback');
|
||||||
|
try {
|
||||||
|
return $this->checkResultCode($this->client->getMulti($ids));
|
||||||
|
} catch (\Error $e) {
|
||||||
|
throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine());
|
||||||
|
} finally {
|
||||||
|
ini_set('unserialize_callback_func', $unserializeCallbackHandler);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,8 +13,10 @@ namespace Symfony\Component\DependencyInjection\Compiler;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
|
use Symfony\Component\DependencyInjection\ExpressionLanguage;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\ExpressionLanguage\Expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run this pass before passes that need to know more about the relation of
|
* Run this pass before passes that need to know more about the relation of
|
||||||
|
@ -32,6 +34,7 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||||
private $repeatedPass;
|
private $repeatedPass;
|
||||||
private $onlyConstructorArguments;
|
private $onlyConstructorArguments;
|
||||||
private $lazy;
|
private $lazy;
|
||||||
|
private $expressionLanguage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
|
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
|
||||||
|
@ -79,6 +82,11 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||||
|
|
||||||
return $value;
|
return $value;
|
||||||
}
|
}
|
||||||
|
if ($value instanceof Expression) {
|
||||||
|
$this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
if ($value instanceof Reference) {
|
if ($value instanceof Reference) {
|
||||||
$targetDefinition = $this->getDefinition((string) $value);
|
$targetDefinition = $this->getDefinition((string) $value);
|
||||||
|
|
||||||
|
@ -143,4 +151,27 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
||||||
|
|
||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getExpressionLanguage()
|
||||||
|
{
|
||||||
|
if (null === $this->expressionLanguage) {
|
||||||
|
$providers = $this->container->getExpressionLanguageProviders();
|
||||||
|
$this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
|
||||||
|
if ('""' === substr_replace($arg, '', 1, -1)) {
|
||||||
|
$id = stripcslashes(substr($arg, 1, -1));
|
||||||
|
|
||||||
|
$this->graph->connect(
|
||||||
|
$this->currentId,
|
||||||
|
$this->currentDefinition,
|
||||||
|
$this->getDefinitionId($id),
|
||||||
|
$this->getDefinition($id)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('$this->get(%s)', $arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->expressionLanguage;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -273,6 +273,12 @@ class AutowirePass extends AbstractRecursivePass
|
||||||
|
|
||||||
// no default value? Then fail
|
// no default value? Then fail
|
||||||
if (!$parameter->isDefaultValueAvailable()) {
|
if (!$parameter->isDefaultValueAvailable()) {
|
||||||
|
// For core classes, isDefaultValueAvailable() can
|
||||||
|
// be false when isOptional() returns true. If the
|
||||||
|
// argument *is* optional, allow it to be missing
|
||||||
|
if ($parameter->isOptional()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" must have a type-hint or be given a value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
|
throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" must have a type-hint or be given a value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1723,7 +1723,15 @@ EOF;
|
||||||
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
|
||||||
}
|
}
|
||||||
$providers = $this->container->getExpressionLanguageProviders();
|
$providers = $this->container->getExpressionLanguageProviders();
|
||||||
$this->expressionLanguage = new ExpressionLanguage(null, $providers);
|
$this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
|
||||||
|
$id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null;
|
||||||
|
|
||||||
|
if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) {
|
||||||
|
return $this->getServiceCall($id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprintf('$this->get(%s)', $arg);
|
||||||
|
});
|
||||||
|
|
||||||
if ($this->container->isTrackingResources()) {
|
if ($this->container->isTrackingResources()) {
|
||||||
foreach ($providers as $provider) {
|
foreach ($providers as $provider) {
|
||||||
|
|
|
@ -25,10 +25,10 @@ class ExpressionLanguage extends BaseExpressionLanguage
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function __construct($cache = null, array $providers = array())
|
public function __construct($cache = null, array $providers = array(), callable $serviceCompiler = null)
|
||||||
{
|
{
|
||||||
// prepend the default provider to let users override it easily
|
// prepend the default provider to let users override it easily
|
||||||
array_unshift($providers, new ExpressionLanguageProvider());
|
array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler));
|
||||||
|
|
||||||
parent::__construct($cache, $providers);
|
parent::__construct($cache, $providers);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,17 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
|
||||||
*/
|
*/
|
||||||
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
|
class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface
|
||||||
{
|
{
|
||||||
|
private $serviceCompiler;
|
||||||
|
|
||||||
|
public function __construct(callable $serviceCompiler = null)
|
||||||
|
{
|
||||||
|
$this->serviceCompiler = $serviceCompiler;
|
||||||
|
}
|
||||||
|
|
||||||
public function getFunctions()
|
public function getFunctions()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
new ExpressionFunction('service', function ($arg) {
|
new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) {
|
||||||
return sprintf('$this->get(%s)', $arg);
|
return sprintf('$this->get(%s)', $arg);
|
||||||
}, function (array $variables, $value) {
|
}, function (array $variables, $value) {
|
||||||
return $variables['container']->get($value);
|
return $variables['container']->get($value);
|
||||||
|
|
|
@ -512,6 +512,23 @@ class AutowirePassTest extends TestCase
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testOptionalArgsNoRequiredForCoreClasses()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
|
||||||
|
$container->register('foo', \SplFileObject::class)
|
||||||
|
->addArgument('foo.txt')
|
||||||
|
->setAutowired(true);
|
||||||
|
|
||||||
|
(new AutowirePass())->process($container);
|
||||||
|
|
||||||
|
$definition = $container->getDefinition('foo');
|
||||||
|
$this->assertEquals(
|
||||||
|
array('foo.txt'),
|
||||||
|
$definition->getArguments()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public function testSetterInjection()
|
public function testSetterInjection()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
|
@ -138,7 +138,7 @@ class PhpDumperTest extends TestCase
|
||||||
{
|
{
|
||||||
$container = include self::$fixturesPath.'/containers/container9.php';
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
||||||
$dumper = new PhpDumper($container);
|
$dumper = new PhpDumper($container);
|
||||||
$this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services');
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testAddService()
|
public function testAddService()
|
||||||
|
@ -146,7 +146,7 @@ class PhpDumperTest extends TestCase
|
||||||
$container = include self::$fixturesPath.'/containers/container9.php';
|
$container = include self::$fixturesPath.'/containers/container9.php';
|
||||||
$container->compile();
|
$container->compile();
|
||||||
$dumper = new PhpDumper($container);
|
$dumper = new PhpDumper($container);
|
||||||
$this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services');
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services');
|
||||||
|
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
$container->register('foo', 'FooClass')->addArgument(new \stdClass());
|
$container->register('foo', 'FooClass')->addArgument(new \stdClass());
|
||||||
|
@ -599,6 +599,22 @@ class PhpDumperTest extends TestCase
|
||||||
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace('\\\\Dumper', '/Dumper', $dumper->dump(array('file' => self::$fixturesPath.'/php/services_array_params.php'))));
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace('\\\\Dumper', '/Dumper', $dumper->dump(array('file' => self::$fixturesPath.'/php/services_array_params.php'))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testExpressionReferencingPrivateService()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$container->register('private_bar', 'stdClass')
|
||||||
|
->setPublic(false);
|
||||||
|
$container->register('private_foo', 'stdClass')
|
||||||
|
->setPublic(false);
|
||||||
|
$container->register('public_foo', 'stdClass')
|
||||||
|
->addArgument(new Expression('service("private_foo")'));
|
||||||
|
|
||||||
|
$container->compile();
|
||||||
|
$dumper = new PhpDumper($container);
|
||||||
|
|
||||||
|
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump());
|
||||||
|
}
|
||||||
|
|
||||||
public function testDumpHandlesLiteralClassWithRootNamespace()
|
public function testDumpHandlesLiteralClassWithRootNamespace()
|
||||||
{
|
{
|
||||||
$container = new ContainerBuilder();
|
$container = new ContainerBuilder();
|
||||||
|
|
|
@ -356,7 +356,7 @@ class ProjectServiceContainer extends Container
|
||||||
if ($this->has('foobaz')) {
|
if ($this->has('foobaz')) {
|
||||||
$instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
|
$instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE));
|
||||||
}
|
}
|
||||||
$instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default"))));
|
$instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default"))));
|
||||||
|
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -348,7 +348,7 @@ class ProjectServiceContainer extends Container
|
||||||
|
|
||||||
$instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'});
|
$instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'});
|
||||||
$instance->setBar(NULL);
|
$instance->setBar(NULL);
|
||||||
$instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default"))));
|
$instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default"))));
|
||||||
|
|
||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
|
use Symfony\Component\DependencyInjection\Container;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\LogicException;
|
||||||
|
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||||
|
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProjectServiceContainer.
|
||||||
|
*
|
||||||
|
* This class has been auto-generated
|
||||||
|
* by the Symfony Dependency Injection Component.
|
||||||
|
*
|
||||||
|
* @final since Symfony 3.3
|
||||||
|
*/
|
||||||
|
class ProjectServiceContainer extends Container
|
||||||
|
{
|
||||||
|
private $parameters;
|
||||||
|
private $targetDirs = array();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->services = array();
|
||||||
|
$this->methodMap = array(
|
||||||
|
'private_foo' => 'getPrivateFooService',
|
||||||
|
'public_foo' => 'getPublicFooService',
|
||||||
|
);
|
||||||
|
$this->privates = array(
|
||||||
|
'private_foo' => true,
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->aliases = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function compile()
|
||||||
|
{
|
||||||
|
throw new LogicException('You cannot compile a dumped container that was already compiled.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isCompiled()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function isFrozen()
|
||||||
|
{
|
||||||
|
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the 'public_foo' service.
|
||||||
|
*
|
||||||
|
* This service is shared.
|
||||||
|
* This method always returns the same instance of the service.
|
||||||
|
*
|
||||||
|
* @return \stdClass A stdClass instance
|
||||||
|
*/
|
||||||
|
protected function getPublicFooService()
|
||||||
|
{
|
||||||
|
return $this->services['public_foo'] = new \stdClass(${($_ = isset($this->services['private_foo']) ? $this->services['private_foo'] : $this->getPrivateFooService()) && false ?: '_'});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the 'private_foo' 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 \stdClass A stdClass instance
|
||||||
|
*/
|
||||||
|
protected function getPrivateFooService()
|
||||||
|
{
|
||||||
|
return $this->services['private_foo'] = new \stdClass();
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,7 +72,7 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface
|
||||||
return $this->choiceList;
|
return $this->choiceList;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->choiceList = new ArrayChoiceList($this->getTimezones(), $value);
|
return $this->choiceList = new ArrayChoiceList(self::getTimezones(), $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -151,8 +151,6 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||||
case 'Symfony\Component\Validator\Constraints\Count':
|
case 'Symfony\Component\Validator\Constraints\Count':
|
||||||
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', array(), Guess::LOW_CONFIDENCE);
|
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', array(), Guess::LOW_CONFIDENCE);
|
||||||
|
|
||||||
case 'Symfony\Component\Validator\Constraints\True':
|
|
||||||
case 'Symfony\Component\Validator\Constraints\False':
|
|
||||||
case 'Symfony\Component\Validator\Constraints\IsTrue':
|
case 'Symfony\Component\Validator\Constraints\IsTrue':
|
||||||
case 'Symfony\Component\Validator\Constraints\IsFalse':
|
case 'Symfony\Component\Validator\Constraints\IsFalse':
|
||||||
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', array(), Guess::MEDIUM_CONFIDENCE);
|
return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', array(), Guess::MEDIUM_CONFIDENCE);
|
||||||
|
@ -171,7 +169,6 @@ class ValidatorTypeGuesser implements FormTypeGuesserInterface
|
||||||
switch (get_class($constraint)) {
|
switch (get_class($constraint)) {
|
||||||
case 'Symfony\Component\Validator\Constraints\NotNull':
|
case 'Symfony\Component\Validator\Constraints\NotNull':
|
||||||
case 'Symfony\Component\Validator\Constraints\NotBlank':
|
case 'Symfony\Component\Validator\Constraints\NotBlank':
|
||||||
case 'Symfony\Component\Validator\Constraints\True':
|
|
||||||
case 'Symfony\Component\Validator\Constraints\IsTrue':
|
case 'Symfony\Component\Validator\Constraints\IsTrue':
|
||||||
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
|
return new ValueGuess(true, Guess::HIGH_CONFIDENCE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,7 +307,7 @@ EOF;
|
||||||
if (in_array('GET', $methods)) {
|
if (in_array('GET', $methods)) {
|
||||||
// Since we treat HEAD requests like GET requests we don't need to match it.
|
// Since we treat HEAD requests like GET requests we don't need to match it.
|
||||||
$methodVariable = 'canonicalMethod';
|
$methodVariable = 'canonicalMethod';
|
||||||
$methods = array_filter($methods, function ($method) { return 'HEAD' !== $method; });
|
$methods = array_values(array_filter($methods, function ($method) { return 'HEAD' !== $method; }));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1 === count($methods)) {
|
if (1 === count($methods)) {
|
||||||
|
|
|
@ -57,6 +57,17 @@ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher
|
||||||
}
|
}
|
||||||
not_head_and_get:
|
not_head_and_get:
|
||||||
|
|
||||||
|
// get_and_head
|
||||||
|
if ('/get_and_head' === $pathinfo) {
|
||||||
|
if ('GET' !== $canonicalMethod) {
|
||||||
|
$allow[] = 'GET';
|
||||||
|
goto not_get_and_head;
|
||||||
|
}
|
||||||
|
|
||||||
|
return array('_route' => 'get_and_head');
|
||||||
|
}
|
||||||
|
not_get_and_head:
|
||||||
|
|
||||||
// post_and_head
|
// post_and_head
|
||||||
if ('/post_and_get' === $pathinfo) {
|
if ('/post_and_get' === $pathinfo) {
|
||||||
if (!in_array($requestMethod, array('POST', 'HEAD'))) {
|
if (!in_array($requestMethod, array('POST', 'HEAD'))) {
|
||||||
|
|
|
@ -297,6 +297,15 @@ class PhpMatcherDumperTest extends TestCase
|
||||||
array(),
|
array(),
|
||||||
'',
|
'',
|
||||||
array(),
|
array(),
|
||||||
|
array('HEAD', 'GET')
|
||||||
|
));
|
||||||
|
$headMatchCasesCollection->add('get_and_head', new Route(
|
||||||
|
'/get_and_head',
|
||||||
|
array(),
|
||||||
|
array(),
|
||||||
|
array(),
|
||||||
|
'',
|
||||||
|
array(),
|
||||||
array('GET', 'HEAD')
|
array('GET', 'HEAD')
|
||||||
));
|
));
|
||||||
$headMatchCasesCollection->add('post_and_head', new Route(
|
$headMatchCasesCollection->add('post_and_head', new Route(
|
||||||
|
|
|
@ -33,7 +33,7 @@ class IbanValidator extends ConstraintValidator
|
||||||
* a BBAN (Basic Bank Account Number) which has a fixed length per country and,
|
* a BBAN (Basic Bank Account Number) which has a fixed length per country and,
|
||||||
* included within it, a bank identifier with a fixed position and a fixed length per country
|
* included within it, a bank identifier with a fixed position and a fixed length per country
|
||||||
*
|
*
|
||||||
* @see http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
|
* @see https://www.swift.com/sites/default/files/resources/iban_registry.pdf
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
|
@ -129,7 +129,7 @@ class IbanValidator extends ConstraintValidator
|
||||||
'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste
|
'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste
|
||||||
'TN' => 'TN59\d{2}\d{3}\d{13}\d{2}', // Tunisia
|
'TN' => 'TN59\d{2}\d{3}\d{13}\d{2}', // Tunisia
|
||||||
'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey
|
'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey
|
||||||
'UA' => 'UA\d{2}[A-Z]{6}[\dA-Z]{19}', // Ukraine
|
'UA' => 'UA\d{2}\d{6}[\dA-Z]{19}', // Ukraine
|
||||||
'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British
|
'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British
|
||||||
'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands
|
'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands
|
||||||
'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo
|
'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo
|
||||||
|
|
|
@ -113,7 +113,7 @@ class IbanValidatorTest extends ConstraintValidatorTestCase
|
||||||
|
|
||||||
//Extended country list
|
//Extended country list
|
||||||
//http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
|
//http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html
|
||||||
// http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
|
// https://www.swift.com/sites/default/files/resources/iban_registry.pdf
|
||||||
array('AO06000600000100037131174'), //Angola
|
array('AO06000600000100037131174'), //Angola
|
||||||
array('AZ21NABZ00000000137010001944'), //Azerbaijan
|
array('AZ21NABZ00000000137010001944'), //Azerbaijan
|
||||||
array('BH29BMAG1299123456BH00'), //Bahrain
|
array('BH29BMAG1299123456BH00'), //Bahrain
|
||||||
|
@ -151,6 +151,7 @@ class IbanValidatorTest extends ConstraintValidatorTestCase
|
||||||
array('TL380080012345678910157'), //Timor-Leste
|
array('TL380080012345678910157'), //Timor-Leste
|
||||||
array('TN5914207207100707129648'), //Tunisia
|
array('TN5914207207100707129648'), //Tunisia
|
||||||
array('TR330006100519786457841326'), //Turkey
|
array('TR330006100519786457841326'), //Turkey
|
||||||
|
array('UA213223130000026007233566001'), //Ukraine
|
||||||
array('AE260211000000230064016'), //United Arab Emirates
|
array('AE260211000000230064016'), //United Arab Emirates
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -263,6 +264,7 @@ class IbanValidatorTest extends ConstraintValidatorTestCase
|
||||||
array('TL3800800123456789101571'), //Timor-Leste
|
array('TL3800800123456789101571'), //Timor-Leste
|
||||||
array('TN59142072071007071296481'), //Tunisia
|
array('TN59142072071007071296481'), //Tunisia
|
||||||
array('TR3300061005197864578413261'), //Turkey
|
array('TR3300061005197864578413261'), //Turkey
|
||||||
|
array('UA21AAAA1300000260072335660012'), //Ukraine
|
||||||
array('AE2602110000002300640161'), //United Arab Emirates
|
array('AE2602110000002300640161'), //United Arab Emirates
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -372,6 +374,7 @@ class IbanValidatorTest extends ConstraintValidatorTestCase
|
||||||
array('TL380080012345678910158'), //Timor-Leste
|
array('TL380080012345678910158'), //Timor-Leste
|
||||||
array('TN5914207207100707129649'), //Tunisia
|
array('TN5914207207100707129649'), //Tunisia
|
||||||
array('TR330006100519786457841327'), //Turkey
|
array('TR330006100519786457841327'), //Turkey
|
||||||
|
array('UA213223130000026007233566002'), //Ukraine
|
||||||
array('AE260211000000230064017'), //United Arab Emirates
|
array('AE260211000000230064017'), //United Arab Emirates
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ class Caster
|
||||||
$i = 0;
|
$i = 0;
|
||||||
$prefixedKeys = array();
|
$prefixedKeys = array();
|
||||||
foreach ($a as $k => $v) {
|
foreach ($a as $k => $v) {
|
||||||
if (isset($k[0]) && "\0" !== $k[0]) {
|
if (isset($k[0]) ? "\0" !== $k[0] : \PHP_VERSION_ID >= 70200) {
|
||||||
if (!isset($publicProperties[$class])) {
|
if (!isset($publicProperties[$class])) {
|
||||||
foreach (get_class_vars($class) as $prop => $v) {
|
foreach (get_class_vars($class) as $prop => $v) {
|
||||||
$publicProperties[$class][$prop] = true;
|
$publicProperties[$class][$prop] = true;
|
||||||
|
|
|
@ -488,7 +488,7 @@ object(Symfony\Component\VarDumper\Cloner\Data)#%i (6) {
|
||||||
EOTXT;
|
EOTXT;
|
||||||
ob_start();
|
ob_start();
|
||||||
var_dump($clone);
|
var_dump($clone);
|
||||||
$this->assertStringMatchesFormat($expected, ob_get_clean());
|
$this->assertStringMatchesFormat(\PHP_VERSION_ID >= 70200 ? str_replace('"1"', '1', $expected) : $expected, ob_get_clean());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testCaster()
|
public function testCaster()
|
||||||
|
|
|
@ -200,8 +200,22 @@ EOTXT
|
||||||
$var[] = &$v;
|
$var[] = &$v;
|
||||||
$var[''] = 2;
|
$var[''] = 2;
|
||||||
|
|
||||||
$this->assertDumpMatchesFormat(
|
if (\PHP_VERSION_ID >= 70200) {
|
||||||
<<<'EOTXT'
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
array:4 [
|
||||||
|
0 => {}
|
||||||
|
1 => &1 null
|
||||||
|
2 => &1 null
|
||||||
|
"" => 2
|
||||||
|
]
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
array:4 [
|
array:4 [
|
||||||
"0" => {}
|
"0" => {}
|
||||||
"1" => &1 null
|
"1" => &1 null
|
||||||
|
@ -209,9 +223,10 @@ array:4 [
|
||||||
"" => 2
|
"" => 2
|
||||||
]
|
]
|
||||||
EOTXT
|
EOTXT
|
||||||
,
|
,
|
||||||
$var
|
$var
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testObjectCast()
|
public function testObjectCast()
|
||||||
|
@ -219,16 +234,28 @@ EOTXT
|
||||||
$var = (object) array(1 => 1);
|
$var = (object) array(1 => 1);
|
||||||
$var->{1} = 2;
|
$var->{1} = 2;
|
||||||
|
|
||||||
$this->assertDumpMatchesFormat(
|
if (\PHP_VERSION_ID >= 70200) {
|
||||||
<<<'EOTXT'
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
|
{
|
||||||
|
+"1": 2
|
||||||
|
}
|
||||||
|
EOTXT
|
||||||
|
,
|
||||||
|
$var
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
$this->assertDumpMatchesFormat(
|
||||||
|
<<<'EOTXT'
|
||||||
{
|
{
|
||||||
+1: 1
|
+1: 1
|
||||||
+"1": 2
|
+"1": 2
|
||||||
}
|
}
|
||||||
EOTXT
|
EOTXT
|
||||||
,
|
,
|
||||||
$var
|
$var
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testClosedResource()
|
public function testClosedResource()
|
||||||
|
|
|
@ -17,8 +17,7 @@ CHANGELOG
|
||||||
|
|
||||||
* Deprecated support for implicitly parsing non-string mapping keys as strings.
|
* Deprecated support for implicitly parsing non-string mapping keys as strings.
|
||||||
Mapping keys that are no strings will lead to a `ParseException` in Symfony
|
Mapping keys that are no strings will lead to a `ParseException` in Symfony
|
||||||
4.0. Use the `PARSE_KEYS_AS_STRINGS` flag to opt-in for keys to be parsed as
|
4.0. Use quotes to opt-in for keys to be parsed as strings.
|
||||||
strings.
|
|
||||||
|
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
|
@ -26,7 +25,6 @@ CHANGELOG
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
null: null key
|
||||||
true: boolean true
|
true: boolean true
|
||||||
1: integer key
|
|
||||||
2.0: float key
|
2.0: float key
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
|
@ -38,13 +36,12 @@ CHANGELOG
|
||||||
```php
|
```php
|
||||||
|
|
||||||
$yaml = <<<YAML
|
$yaml = <<<YAML
|
||||||
null: null key
|
"null": null key
|
||||||
true: boolean true
|
"true": boolean true
|
||||||
1: integer key
|
"2.0": float key
|
||||||
2.0: float key
|
|
||||||
YAML;
|
YAML;
|
||||||
|
|
||||||
Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS);
|
Yaml::parse($yaml);
|
||||||
```
|
```
|
||||||
|
|
||||||
* Omitted mapping values will be parsed as `null`.
|
* Omitted mapping values will be parsed as `null`.
|
||||||
|
|
|
@ -494,7 +494,7 @@ class Inline
|
||||||
$evaluatedKey = self::evaluateScalar($key, $flags, $references);
|
$evaluatedKey = self::evaluateScalar($key, $flags, $references);
|
||||||
|
|
||||||
if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) {
|
if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) {
|
||||||
@trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', E_USER_DEPRECATED);
|
@trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -238,7 +238,7 @@ class Parser
|
||||||
|
|
||||||
if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) {
|
if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) {
|
||||||
$keyType = is_numeric($key) ? 'numeric key' : 'non-string key';
|
$keyType = is_numeric($key) ? 'numeric key' : 'non-string key';
|
||||||
@trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED);
|
@trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert float keys to strings, to avoid being converted to integers by PHP
|
// Convert float keys to strings, to avoid being converted to integers by PHP
|
||||||
|
|
|
@ -730,7 +730,7 @@ class InlineTest extends TestCase
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group legacy
|
* @group legacy
|
||||||
* @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.
|
* @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
|
||||||
* @dataProvider getNotPhpCompatibleMappingKeyData
|
* @dataProvider getNotPhpCompatibleMappingKeyData
|
||||||
*/
|
*/
|
||||||
public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected)
|
public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected)
|
||||||
|
|
|
@ -1081,7 +1081,7 @@ EOF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group legacy
|
* @group legacy
|
||||||
* @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.
|
* @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
|
||||||
*/
|
*/
|
||||||
public function testFloatKeys()
|
public function testFloatKeys()
|
||||||
{
|
{
|
||||||
|
@ -1103,7 +1103,7 @@ EOF;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @group legacy
|
* @group legacy
|
||||||
* @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.
|
* @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.
|
||||||
*/
|
*/
|
||||||
public function testBooleanKeys()
|
public function testBooleanKeys()
|
||||||
{
|
{
|
||||||
|
|
Reference in New Issue