Merge branch '3.4' into 4.2

* 3.4:
  [Serializer] Added check of constuctor modifiers to AbstractNormalizer
  [Intl] Simplify the compile binary
  [Routing] Fix routes annotation loading with glob pattern
  Fix hardcoded hotPathTagName
  [Validator] Improve constraint default option check
  [Validator] Fix annotation default for @Count and @Length
  Update composer.json
  Fix getSetMethodNormalizer to correctly ignore the attributes specified in "ignored_attributes"
  Add missing "vi" translations
  add missing German translations
  [Intl] Fix test
  added missing translation
  use behavior instead of behaviour
  [Validator] Translate JSON message to Hungarian
  [Validator] fix sr_Latn translations
  [FrameworkBundle][HttpFoundation] make session service resettable
This commit is contained in:
Fabien Potencier 2019-03-30 16:58:42 +01:00
commit 2fb2508cee
31 changed files with 210 additions and 43 deletions

View File

@ -15,6 +15,7 @@
<argument type="service" id="session.storage" />
<argument type="service" id="session.attribute_bag" />
<argument type="service" id="session.flash_bag" />
<tag name="kernel.reset" method="save" />
</service>
<service id="Symfony\Component\HttpFoundation\Session\SessionInterface" alias="session" />

View File

@ -23,7 +23,7 @@
"symfony/contracts": "^1.0.2",
"symfony/dependency-injection": "^4.2.5",
"symfony/event-dispatcher": "^4.1",
"symfony/http-foundation": "^4.1.2",
"symfony/http-foundation": "^4.2.5",
"symfony/http-kernel": "^4.2",
"symfony/polyfill-mbstring": "~1.0",
"symfony/filesystem": "~3.4|~4.0",

View File

@ -287,12 +287,12 @@ class XmlDumper extends Dumper
} elseif ($value instanceof Reference) {
$element->setAttribute('type', 'service');
$element->setAttribute('id', (string) $value);
$behaviour = $value->getInvalidBehavior();
if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behaviour) {
$behavior = $value->getInvalidBehavior();
if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behavior) {
$element->setAttribute('on-invalid', 'null');
} elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behaviour) {
} elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behavior) {
$element->setAttribute('on-invalid', 'ignore');
} elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behaviour) {
} elseif (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE == $behavior) {
$element->setAttribute('on-invalid', 'ignore_uninitialized');
}
} elseif ($value instanceof Definition) {

View File

@ -105,7 +105,7 @@ class RegisterListenersPass implements CompilerPassInterface
$definition->addMethodCall('addListener', $args);
if (isset($this->hotPathEvents[$args[0]])) {
$container->getDefinition($id)->addTag('container.hot_path');
$container->getDefinition($id)->addTag($this->hotPathTagName);
}
}
$extractingDispatcher->listeners = [];

View File

@ -190,10 +190,10 @@ CHANGELOG
* Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This
implementation is ESI compatible.
* Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire
behaviour of messages auto expiring after one page page load. Messages must
behavior of messages auto expiring after one page page load. Messages must
be retrieved by `get()` or `all()`.
* Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate
attributes storage behaviour from 2.0.x (default).
attributes storage behavior from 2.0.x (default).
* Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for
namespace session attributes.
* Flash API can stores messages in an array so there may be multiple messages

View File

@ -193,7 +193,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable
*/
public function save()
{
$this->storage->save();
if ($this->isStarted()) {
$this->storage->save();
}
}
/**

View File

@ -260,4 +260,14 @@ class SessionTest extends TestCase
$flash->get('hello');
$this->assertTrue($this->session->isEmpty());
}
public function testSaveIfNotStarted()
{
$storage = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface')->getMock();
$session = new Session($storage);
$storage->expects($this->once())->method('isStarted')->willReturn(false);
$storage->expects($this->never())->method('save');
$session->save();
}
}

View File

@ -1,12 +1,14 @@
#!/usr/bin/env bash
if [[ $1 == force || ! $(docker ps -a | grep symfony-intl) ]]; then
docker rm -f symfony-intl
docker create --name symfony-intl -it -v /tmp:/tmp -v $(pwd):/app -w /app jakzal/php-intl:7.2-63.1 bash
docker start symfony-intl
docker exec symfony-intl bash -xc "apt-get update && apt-get -y install build-essential"
else
docker start symfony-intl
if [[ $1 == force ]]; then
docker pull jakzal/php-intl
fi;
docker exec -u $(id -u):$(id -g) symfony-intl php src/Symfony/Component/Intl/Resources/bin/update-data.php
docker run \
-it --rm --name symfony-intl \
-u $(id -u):$(id -g) \
-v /tmp/symfony/icu:/tmp \
-v $(pwd):/symfony \
-w /symfony \
jakzal/php-intl:latest \
php src/Symfony/Component/Intl/Resources/bin/update-data.php

View File

@ -41,7 +41,7 @@ class IntlTest extends TestCase
public function testGetRegionBundleCreatesTheRegionBundle()
{
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\LocaleBundleInterface', Intl::getLocaleBundle());
$this->assertInstanceOf('Symfony\Component\Intl\ResourceBundle\RegionBundleInterface', Intl::getRegionBundle());
}
public function testGetIcuVersionReadsTheVersionOfInstalledIcuLibrary()

View File

@ -68,7 +68,7 @@ CHANGELOG
* [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and
will be removed in Symfony 3.0, since the performance gains were minimal and
it's hard to replicate the behaviour of PHP implementation.
it's hard to replicate the behavior of PHP implementation.
2.3.0
-----

View File

@ -56,6 +56,11 @@ class AnnotationFileLoader extends FileLoader
$collection = new RouteCollection();
if ($class = $this->findClass($path)) {
$refl = new \ReflectionClass($class);
if ($refl->isAbstract()) {
return;
}
$collection->addResource(new FileResource($path));
$collection->addCollection($this->loader->load($class, $type));
}

View File

@ -13,4 +13,9 @@ namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses;
abstract class AbstractClass
{
abstract public function abstractRouteAction();
public function routeAction($arg1, $arg2 = 'defaultValue2', $arg3 = 'defaultValue3')
{
}
}

View File

@ -72,6 +72,14 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest
$this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php');
}
public function testLoadAbstractClass()
{
$this->reader->expects($this->never())->method('getClassAnnotation');
$this->reader->expects($this->never())->method('getMethodAnnotations');
$this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/AbstractClass.php');
}
public function testSupports()
{
$fixture = __DIR__.'/../Fixtures/annotated.php';

View File

@ -22,8 +22,8 @@ use Symfony\Component\Security\Http\ParameterBagUtils;
/**
* Class with the default authentication failure handling logic.
*
* Can be optionally be extended from by the developer to alter the behaviour
* while keeping the default behaviour.
* Can be optionally be extended from by the developer to alter the behavior
* while keeping the default behavior.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Johannes M. Schmitt <schmittjoh@gmail.com>

View File

@ -32,6 +32,7 @@
"require-dev": {
"psr/container": "^1.0",
"symfony/finder": "~3.4|~4.0",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-icu": "~1.0",
"symfony/routing": "~3.4|~4.0",
"symfony/validator": "~3.4|~4.0",

View File

@ -388,6 +388,10 @@ abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerIn
$constructor = $this->getConstructor($data, $class, $context, $reflectionClass, $allowedAttributes);
if ($constructor) {
if (true !== $constructor->isPublic()) {
return $reflectionClass->newInstanceWithoutConstructor();
}
$constructorParameters = $constructor->getParameters();
$params = [];

View File

@ -110,7 +110,7 @@ class GetSetMethodNormalizer extends AbstractObjectNormalizer
$attributeName = lcfirst(substr($method->name, 0 === strpos($method->name, 'is') ? 2 : 3));
if ($this->isAllowedAttribute($object, $attributeName)) {
if ($this->isAllowedAttribute($object, $attributeName, $format, $context)) {
$attributes[] = $attributeName;
}
}

View File

@ -96,6 +96,23 @@ class GetSetMethodNormalizerTest extends TestCase
$this->assertTrue($obj->isBaz());
}
public function testIgnoredAttributesInContext()
{
$ignoredAttributes = ['foo', 'bar', 'baz', 'object'];
$this->normalizer->setIgnoredAttributes($ignoredAttributes);
$obj = new GetSetDummy();
$obj->setFoo('foo');
$obj->setBar('bar');
$obj->setCamelCase(true);
$this->assertEquals(
[
'fooBar' => 'foobar',
'camelCase' => true,
],
$this->normalizer->normalize($obj, 'any')
);
}
public function testDenormalizeWithObject()
{
$data = new \stdClass();

View File

@ -202,7 +202,7 @@ class TranslatorCacheTest extends TestCase
* messages provided by the loader. This must also be the case when these catalogues
* are (internally) read from a cache.
*
* Optimizations inside the translator must not change this behaviour.
* Optimizations inside the translator must not change this behavior.
*/
/*

View File

@ -105,6 +105,7 @@ abstract class Constraint
*/
public function __construct($options = null)
{
$defaultOption = $this->getDefaultOption();
$invalidOptions = [];
$missingOptions = array_flip((array) $this->getRequiredOptions());
$knownOptions = get_object_vars($this);
@ -112,8 +113,12 @@ abstract class Constraint
// The "groups" option is added to the object lazily
$knownOptions['groups'] = true;
if (\is_array($options) && \count($options) >= 1 && isset($options['value']) && !property_exists($this, 'value')) {
$options[$this->getDefaultOption()] = $options['value'];
if (\is_array($options) && isset($options['value']) && !property_exists($this, 'value')) {
if (null === $defaultOption) {
throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', \get_class($this)));
}
$options[$defaultOption] = $options['value'];
unset($options['value']);
}
@ -130,26 +135,24 @@ abstract class Constraint
}
}
} elseif (null !== $options && !(\is_array($options) && 0 === \count($options))) {
$option = $this->getDefaultOption();
if (null === $option) {
throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint %s', \get_class($this)));
if (null === $defaultOption) {
throw new ConstraintDefinitionException(sprintf('No default option is configured for constraint "%s".', \get_class($this)));
}
if (\array_key_exists($option, $knownOptions)) {
$this->$option = $options;
unset($missingOptions[$option]);
if (\array_key_exists($defaultOption, $knownOptions)) {
$this->$defaultOption = $options;
unset($missingOptions[$defaultOption]);
} else {
$invalidOptions[] = $option;
$invalidOptions[] = $defaultOption;
}
}
if (\count($invalidOptions) > 0) {
throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint %s', implode('", "', $invalidOptions), \get_class($this)), $invalidOptions);
throw new InvalidOptionsException(sprintf('The options "%s" do not exist in constraint "%s".', implode('", "', $invalidOptions), \get_class($this)), $invalidOptions);
}
if (\count($missingOptions) > 0) {
throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint %s', implode('", "', array_keys($missingOptions)), \get_class($this)), array_keys($missingOptions));
throw new MissingOptionsException(sprintf('The options "%s" must be set for constraint "%s".', implode('", "', array_keys($missingOptions)), \get_class($this)), array_keys($missingOptions));
}
}
@ -173,7 +176,7 @@ abstract class Constraint
return;
}
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, \get_class($this)), [$option]);
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]);
}
/**
@ -199,7 +202,7 @@ abstract class Constraint
return $this->groups;
}
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint %s', $option, \get_class($this)), [$option]);
throw new InvalidOptionsException(sprintf('The option "%s" does not exist in constraint "%s".', $option, \get_class($this)), [$option]);
}
/**
@ -256,7 +259,7 @@ abstract class Constraint
*
* By default, this is the fully qualified name of the constraint class
* suffixed with "Validator". You can override this method to change that
* behaviour.
* behavior.
*
* @return string
*/

View File

@ -43,6 +43,9 @@ class Count extends Constraint
'min' => $options,
'max' => $options,
];
} elseif (\is_array($options) && isset($options['value']) && !isset($options['min']) && !isset($options['max'])) {
$options['min'] = $options['max'] = $options['value'];
unset($options['value']);
}
parent::__construct($options);

View File

@ -47,6 +47,9 @@ class Length extends Constraint
'min' => $options,
'max' => $options,
];
} elseif (\is_array($options) && isset($options['value']) && !isset($options['min']) && !isset($options['max'])) {
$options['min'] = $options['max'] = $options['value'];
unset($options['value']);
}
parent::__construct($options);

View File

@ -330,6 +330,14 @@
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
<target>Diese internationale Bankleitzahl (BIC) ist nicht mit der IBAN {{ iban }} assoziiert.</target>
</trans-unit>
<trans-unit id="86">
<source>This value should be valid JSON.</source>
<target>Dieser Wert sollte gültiges JSON sein.</target>
</trans-unit>
<trans-unit id="87">
<source>This collection should contain only unique elements.</source>
<target>Diese Sammlung darf keine doppelten Elemente enthalten.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -334,6 +334,10 @@
<source>This value should be valid JSON.</source>
<target>This value should be valid JSON.</target>
</trans-unit>
<trans-unit id="87">
<source>This collection should contain only unique elements.</source>
<target>This collection should contain only unique elements.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -330,6 +330,10 @@
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
<target>Ez a Bankazonosító kód (BIC) nem kapcsolódik az IBAN kódhoz ({{ iban }}).</target>
</trans-unit>
<trans-unit id="86">
<source>This value should be valid JSON.</source>
<target>Ez az érték érvényes JSON kell, hogy legyen.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -220,7 +220,7 @@
</trans-unit>
<trans-unit id="58">
<source>Unsupported card type or invalid card number.</source>
<target>Tip kartije nije podržan ili broj kartice nije validan.</target>
<target>Tip kartice nije podržan ili broj kartice nije validan.</target>
</trans-unit>
<trans-unit id="59">
<source>This is not a valid International Bank Account Number (IBAN).</source>
@ -324,7 +324,7 @@
</trans-unit>
<trans-unit id="84">
<source>This value should be a multiple of {{ compared_value }}.</source>
<target>Ova vrednost bi trebalo da bude višestruko veća od {{ compared_value }}.</target>
<target>Ova vrednost bi trebalo da bude deljiva sa {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="85">
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>

View File

@ -278,6 +278,66 @@
<source>This value should not be identical to {{ compared_value_type }} {{ compared_value }}.</source>
<target>Giá trị không được phép giống như {{ compared_value_type }} {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="73">
<source>The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.</source>
<target>Tỷ lệ bức ảnh quá lớn ({{ ratio }}). Tỷ lệ tối đa cho phép là {{ max_ratio }}.</target>
</trans-unit>
<trans-unit id="74">
<source>The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.</source>
<target>Tỷ lệ bức ảnh quá nhỏ ({{ ratio }}). Tỷ lệ tối thiểu mong muốn là {{ min_ratio }}.</target>
</trans-unit>
<trans-unit id="75">
<source>The image is square ({{ width }}x{{ height }}px). Square images are not allowed.</source>
<target>Bức ảnh là hình vuông ({{ width }}x{{ height }}px). Ảnh hình vuông không được phép.</target>
</trans-unit>
<trans-unit id="76">
<source>The image is landscape oriented ({{ width }}x{{ height }}px). Landscape oriented images are not allowed.</source>
<target>Bức ảnh theo chiều ngang ({{ width }}x{{ height }}px). Ảnh chiều ngang không được phép.</target>
</trans-unit>
<trans-unit id="77">
<source>The image is portrait oriented ({{ width }}x{{ height }}px). Portrait oriented images are not allowed.</source>
<target>Bức ảnh theo chiều dọc ({{ width }}x{{ height }}px). Ảnh chiều dọc không được phép.</target>
</trans-unit>
<trans-unit id="78">
<source>An empty file is not allowed.</source>
<target>Một file rỗng không được phép.</target>
</trans-unit>
<trans-unit id="79">
<source>The host could not be resolved.</source>
<target>Máy chủ không thể được tìm thấy.</target>
</trans-unit>
<trans-unit id="80">
<source>This value does not match the expected {{ charset }} charset.</source>
<target>Giá trị này không đúng định dạng bộ ký tự mong muốn {{ charset }}.</target>
</trans-unit>
<trans-unit id="81">
<source>This is not a valid Business Identifier Code (BIC).</source>
<target>Giá trị này không đúng định dạng mã định danh doanh nghiệp (BIC).</target>
</trans-unit>
<trans-unit id="82">
<source>Error</source>
<target>Lỗi</target>
</trans-unit>
<trans-unit id="83">
<source>This is not a valid UUID.</source>
<target>Giá trị này không đúng định dạng UUID.</target>
</trans-unit>
<trans-unit id="84">
<source>This value should be a multiple of {{ compared_value }}.</source>
<target>Giá trị này nên là bội số của {{ compared_value }}.</target>
</trans-unit>
<trans-unit id="85">
<source>This Business Identifier Code (BIC) is not associated with IBAN {{ iban }}.</source>
<target>Mã định danh doanh nghiệp (BIC) này không liên kết với IBAN {{ iban }}.</target>
</trans-unit>
<trans-unit id="86">
<source>This value should be valid JSON.</source>
<target>Giá trị này nên đúng định dạng JSON.</target>
</trans-unit>
<trans-unit id="87">
<source>This collection should contain only unique elements.</source>
<target>Danh sách này chỉ nên chứa các phần tử khác nhau.</target>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -225,7 +225,7 @@ class ConstraintTest extends TestCase
/**
* @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException
* @expectedExceptionMessage The options "0", "5" do not exist
* @expectedExceptionMessage The options "0", "5" do not exist in constraint "Symfony\Component\Validator\Tests\Fixtures\ConstraintA".
*/
public function testInvalidOptions()
{
@ -242,4 +242,13 @@ class ConstraintTest extends TestCase
$this->assertEquals('foo', $constraint->property1);
}
/**
* @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException
* @expectedExceptionMessage No default option is configured for constraint "Symfony\Component\Validator\Tests\Fixtures\ConstraintB".
*/
public function testAnnotationSetUndefinedDefaultOption()
{
new ConstraintB(['value' => 1]);
}
}

View File

@ -195,4 +195,13 @@ abstract class CountValidatorTest extends ConstraintValidatorTestCase
$this->assertEquals(5, $constraint->min);
$this->assertEquals(5, $constraint->max);
}
public function testConstraintAnnotationDefaultOption()
{
$constraint = new Count(['value' => 5, 'exactMessage' => 'message']);
$this->assertEquals(5, $constraint->min);
$this->assertEquals(5, $constraint->max);
$this->assertEquals('message', $constraint->exactMessage);
}
}

View File

@ -237,11 +237,20 @@ class LengthValidatorTest extends ConstraintValidatorTestCase
}
}
public function testConstraintGetDefaultOption()
public function testConstraintDefaultOption()
{
$constraint = new Length(5);
$this->assertEquals(5, $constraint->min);
$this->assertEquals(5, $constraint->max);
}
public function testConstraintAnnotationDefaultOption()
{
$constraint = new Length(['value' => 5, 'exactMessage' => 'message']);
$this->assertEquals(5, $constraint->min);
$this->assertEquals(5, $constraint->max);
$this->assertEquals('message', $constraint->exactMessage);
}
}

View File

@ -72,7 +72,7 @@ yaml: |
- 2001-07-23
perl-busted: >
YAML.pm will be able to emulate this behavior soon. In this regard
it may be somewhat more correct than Python's native behaviour which
it may be somewhat more correct than Python's native behavior which
can only use tuples as mapping keys. PyYAML will also need to figure
out some clever way to roundtrip structured keys.
python: |