8000 Merge branch '4.4' · symfony/symfony@fa29a56 · GitHub
[go: up one dir, main page]

Skip to content

Commit fa29a56

Browse files
Merge branch '4.4'
* 4.4: [Cache] replace getNsSeparator by NS_SEPARATOR on AbstractTrait [Cache] fix versioning with SimpleCacheAdapter [Messenger] fix AMQP delay queue to be per exchange Fix expired lock not cleaned Fine tune constructor types [HttpClient] throw DecodingExceptionInterface when toArray() fails because of content-type error [HttpFoundation] Fix SA/phpdoc JsonResponse [DI] Show the right class autowired when providing a non-existing class in constructor SimpleCacheAdapter fails to cache any item if a namespace is used validate composite constraints in all groups [Serializer] Handle true and false appropriately in CSV encoder [Messenger] improve logs [Messenger] fix delay delivery for non-fanout exchanges Parameterize Mailgun's region Fix binary operation `+`, `-` or `*` on string [VarDumper] fix dumping objects that implement __debugInfo() [HttpClient] Don't use CurlHttpClient on Windows when curl.cainfo is not set Add statement to fileLink to ignore href code when no fileLink. [Routing] fix absolute url generation when scheme is not known
2 parents ac7d168 + 651de17 commit fa29a56

File tree

69 files changed

+630
-290
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+630
-290
lines changed

src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,11 @@ private function formatControllerLink($controller, string $anchorText): string
557557
}
558558

559559
$fileLink = $this->fileLinkFormatter->format($r->getFileName(), $r->getStartLine());
560+
if ($fileLink) {
561+
return sprintf('<href=%s>%s</>', $fileLink, $anchorText);
562+
}
560563

561-
return sprintf('<href=%s>%s</>', $fileLink, $anchorText);
564+
return $anchorText;
562565
}
563566

564567
private function formatCallable($callable): string

src/Symfony/Component/Cache/Adapter/AbstractAdapter.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@
2626
*/
2727
abstract class AbstractAdapter implements AdapterInterface, CacheInterface, LoggerAwareInterface, ResettableInterface
2828
{
29+
/**
30+
* @internal
31+
*/
32+
protected const NS_SEPARATOR = ':';
33+
2934
use AbstractAdapterTrait;
3035
use ContractsTrait;
3136

@@ -34,7 +39,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
3439

3540
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
3641
{
37-
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
42+
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::NS_SEPARATOR;
3843
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
3944
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace));
4045
}

src/Symfony/Component/Cache/Adapter/Psr16Adapter.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
*/
2424
class Psr16Adapter extends AbstractAdapter implements PruneableInterface, ResettableInterface
2525
{
26+
/**
27+
* @internal
28+
*/
29+
protected const NS_SEPARATOR = '_';
30+
2631
use ProxyTrait;
2732

2833
private $miss;

src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public function testLongKeyVersioning()
5656
$reflectionProperty->setValue($cache, true);
5757

5858
// Versioning enabled
59-
$this->assertEquals('--------------------------:1/------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]));
59+
$this->assertEquals('--------------------------:1:------------', $reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)]));
6060
$this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 12)])));
6161
$this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 23)])));
6262
$this->assertLessThanOrEqual(50, \strlen($reflectionMethod->invokeArgs($cache, [str_repeat('-', 40)])));

src/Symfony/Component/Cache/Tests/Adapter/Psr16AdapterTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\Cache\Tests\Adapter;
1313

14+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1415
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
1516
use Symfony\Component\Cache\Adapter\Psr16Adapter;
1617
use Symfony\Component\Cache\Psr16Cache;
@@ -28,4 +29,14 @@ public function createCachePool($defaultLifetime = 0)
2829
{
2930
return new Psr16Adapter(new Psr16Cache(new FilesystemAdapter()), '', $defaultLifetime);
3031
}
32+
33+
public function testValidCacheKeyWithNamespace()
34+
{
35+
$cache = new Psr16Adapter(new Psr16Cache(new ArrayAdapter()), 'some_namespace', 0);
36+
$item = $cache->getItem('my_key');
37+
$item->set('someValue');
38+
$cache->save($item);
39+
40+
$this->assertTrue($cache->getItem('my_key')->isHit(), 'Stored item is successfully retrieved.');
41+
}
3142
}

src/Symfony/Component/Cache/Traits/AbstractAdapterTrait.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,9 @@ public function clear()
118118
{
119119
$this->deferred = [];
120120
if ($cleared = $this->versioningIsEnabled) {
121-
$namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), ':', 5);
121+
$namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::NS_SEPARATOR, 5);
122122
try {
123-
$cleared = $this->doSave(['/'.$this->namespace => $namespaceVersion], 0);
123+
$cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0);
124124
} catch (\Exception $e) {
125125
$cleared = false;
126126
}
@@ -327,14 +327,14 @@ private function getId($key)
327327
{
328328
if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
329329
$this->ids = [];
330-
$this->namespaceVersion = '1/';
330+
$this->namespaceVersion = '1'.static::NS_SEPARATOR;
331331
try {
332-
foreach ($this->doFetch(['/'.$this->namespace]) as $v) {
332+
foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) {
333333
$this->namespaceVersion = $v;
334334
}
335-
if ('1:' === $this->namespaceVersion) {
336-
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), ':', 5);
337-
$this->doSave(['@'.$this->namespace => $this->namespaceVersion], 0);
335+
if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) {
336+
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5);
337+
$this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0);
338338
}
339339
} catch (\Exception $e) {
340340
}
@@ -351,7 +351,7 @@ private function getId($key)
351351
}
352352
if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) {
353353
// Use MD5 to favor speed over security, which is not an issue here
354-
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), ':', -(\strlen($this->namespaceVersion) + 2));
354+
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2));
355355
$id = $this->namespace.$this->namespaceVersion.$id;
356356
}
357357

src/Symfony/Component/Config/Definition/BaseNode.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ abstract class BaseNode implements NodeInterface
4747
*/
4848
public function __construct(?string $name, NodeInterface $parent = null, string $pathSeparator = self::DEFAULT_PATH_SEPARATOR)
4949
{
50-
if (false !== strpos($name = (string) $name, $pathSeparator)) {
50+
if (null === $name) {
51+
$name = '';
52+
}
53+
if (false !== strpos($name, $pathSeparator)) {
5154
throw new \InvalidArgumentException('The name must not contain "'.$pathSeparator.'".');
5255
}
5356

src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ abstract class NodeDefinition implements NodeParentInterface
4141
public function __construct(?string $name, NodeParentInterface $parent = null)
4242
{ 97AE
4343
$this->parent = $parent;
44-
$this->name = $name;
44+
$this->name = $name ?? '';
4545
}
4646

4747
/**

src/Symfony/Component/Config/Resource/GlobResource.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class GlobResource implements \IteratorAggregate, SelfCheckingResourceInterface
3939
*
4040
* @throws \InvalidArgumentException
4141
*/
42-
public function __construct(?string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = [])
42+
public function __construct(string $prefix, string $pattern, bool $recursive, bool $forExclusion = false, array $excludedPrefixes = [])
4343
{
4444
$this->prefix = realpath($prefix) ?: (file_exists($prefix) ? $prefix : false);
4545
$this->pattern = $pattern;

src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ public function testImportWithFileLocatorDelegation()
7171
public function testImportWithGlobLikeResource()
7272
{
7373
$locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
74+
$locatorMock->expects($this->once())->method('locate')->willReturn('');
7475
$loader = new TestFileLoader($locatorMock);
7576

7677
$this->assertSame('[foo]', $loader->import('[foo]'));
@@ -79,6 +80,7 @@ public function testImportWithGlobLikeResource()
7980
public function testImportWithNoGlobMatch()
8081
{
8182
$locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock();
83+
$locatorMock->expects($this->once())->method('locate')->willReturn('');
8284
$loader = new TestFileLoader($locatorMock);
8385

8486
$this->assertNull($loader->import('./*.abc'));

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -379,13 +379,14 @@ private function createTypeNotFoundMessageCallback(TypedReference $reference, $l
379379
$container->setAliases($this->container->getAliases());
380380
$container->setDefinitions($this->container->getDefinitions());
381381
$container->setResourceTracking(false);
382+
$currentId = $this->currentId;
382383

383-
return function () use ($container, $reference, $label) {
384-
return $this->createTypeNotFoundMessage($container, $reference, $label);
384+
return function () use ($container, $reference, $label, $currentId) {
385+
return $this->createTypeNotFoundMessage($container, $reference, $label, $currentId);
385386
};
386387
}
387388

388-
private function createTypeNotFoundMessage(ContainerBuilder $container, TypedReference $reference, $label)
389+
private function createTypeNotFoundMessage(ContainerBuilder $container, TypedReference $reference, $label, string $currentId)
389390
{
390391
if (!$r = $container->getReflectionClass($type = $reference->getType(), false)) {
391392
// either $type does not exist or a parent class does not exist
@@ -409,7 +410,7 @@ private function createTypeNotFoundMessage(ContainerBuilder $container, TypedRef
409410
}
410411
}
411412

412-
$message = sprintf('Cannot autowire service "%s": %s %s', $this->currentId, $label, $message);
413+
$message = sprintf('Cannot autowire service "%s": %s %s', $currentId, $label, $message);
413414

414415
if (null !== $this->lastFailure) {
415416
$message = $this->lastFailure."\n".$message;

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,22 @@ public function testProcess()
5050
$this->assertEquals(Foo::class, (string) $container->getDefinition('bar')->getArgument(0));
5151
}
5252

53+
/**
54+
* @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException
55+
* @expectedExceptionMessage Cannot autowire service "Symfony\Component\DependencyInjection\Tests\CompilerEslaAction": argument "$notExisting" of method "Symfony\Component\DependencyInjection\Tests\Compiler\ElsaAction::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotExisting" but this class was not found.
56+
*/
57+
public function testProcessNotExistingActionParam()
58+
{
59+
$container = new ContainerBuilder();
60+
61+
$container->register(Foo::class);
62+
$barDefinition = $container->register(__NAMESPACE__.'EslaAction', __NAMESPACE__.'\ElsaAction');
63+
$barDefinition->setAutowired(true);
64+
65+
(new ResolveClassPass())->process($container);
66+
(new AutowirePass())->process($container);
67+
}
68+
5369
public function testProcessVariadic()
5470
{
5571
$container = new ContainerBuilder();
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
namespace Symfony\Component\DependencyInjection\Tests\Fixtures;
4+
5+
class ConstructNotExists
6+
{
7+
public function __construct(NotExist $notExist)
8+
{
9+
}
10+
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,3 +419,10 @@ public function __construct(LoggerInterface $logger, DecoratorInterface $decorat
419419
{
420420
}
421421
}
422+
423+
final class ElsaAction
424+
{
425+
public function __construct(NotExisting $notExisting)
426+
{
427+
}
428+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
services:
2+
_defaults:
3+
public: true
4+
autowire: true
5+
autoconfigure: true
6+
7+
Symfony\Component\DependencyInjection\Tests\Fixtures\ConstructNotExists: ~

src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -781,6 +781,18 @@ public function testBindings()
781781
], array_map(function (BoundArgument $v) { return $v->getValues()[0]; }, $definition->getBindings()));
782782
}
783783

784+
/**
785+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
786+
* @expectedExceptionMessage Cannot autowire service "Symfony\Component\DependencyInjection\Tests\Fixtures\ConstructNotExists": argument "$notExist" of method "__construct()" has type "Symfony\Component\DependencyInjection\Tests\Fixtures\NotExist" but this class was not found.
787+
*/
788+
public function testProcessNotExistingActionParam()
789+
{
790+
$container = new ContainerBuilder();
791+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
792+
$loader->load('services_not_existing.yml');
793+
$container->compile();
794+
}
795+
784796
public function testFqcnLazyProxy()
785797
{
786798
$container = new ContainerBuilder();

src/Symfony/Component/DomCrawler/AbstractUriElement.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ abstract class AbstractUriElement
2424
protected $node;
2525

2626
/**
27-
* @var string The method to use for the element
27+
* @var string|null The method to use for the element
2828
*/
2929
protected $method;
3030

@@ -36,7 +36,7 @@ abstract class AbstractUriElement
3636
/**
3737
* @param \DOMElement $node A \DOMElement instance
3838
* @param string $currentUri The URI of the page where the link is embedded (or the base href)
39-
* @param string $method The method to use for the link (GET by default)
39+
* @param string|null $method The method to use for the link (GET by default)
4040
*
4141
* @throws \InvalidArgumentException if the node is not a link
4242
*/
@@ -70,7 +70,7 @@ public function getNode()
7070
*/
7171
public function getMethod()
7272
{
73-
return $this->method;
73+
return $this->method ?? 'GET';
7474
}
7575

7676
/**

src/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class BirthdayType extends AbstractType
2121
*/
2222
public function configureOptions(OptionsResolver $resolver)
2323
{
24-
$resolver->setDefault('years', range(date('Y') - 120, date('Y')));
24+
$resolver->setDefault('years', range((int) date('Y') - 120, date('Y')));
2525

2626
$resolver->setAllowedTypes('years', 'array');
2727
}

src/Symfony/Component/Form/Extension/Core/Type/DateType.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ public function configureOptions(OptionsResolver $resolver)
260260
};
261261

262262
$resolver->setDefaults([
263-
'years' => range(date('Y') - 5, date('Y') + 5),
263+
'years' => range((int) date('Y') - 5, (int) date('Y') + 5),
264264
'months' => range(1, 12),
265265
'days' => range(1, 31),
266266
'widget' => 'choice',

src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Form\FormInterface;
1515
use Symfony\Component\Validator\Constraint;
16+
use Symfony\Component\Validator\Constraints\Composite;
1617
use Symfony\Component\Validator\Constraints\GroupSequence;
1718
use Symfony\Component\Validator\Constraints\Valid;
1819
use Symfony\Component\Validator\ConstraintValidator;
@@ -90,7 +91,9 @@ public function validate($form, Constraint $formConstraint)
9091
$validator->atPath('data')->validate($form->getData(), $constraint, $group);
9192

9293
// Prevent duplicate validation
93-
continue 2;
94+
if (!$constraint instanceof Composite) {
95+
continue 2;
96+
}
9497
}
9598
}
9699
}
@@ -137,7 +140,7 @@ public function validate($form, Constraint $formConstraint)
137140
// Mark the form with an error if it contains extra fields
138141
if (!$config->getOption('allow_extra_fields') && \count($form->getExtraData()) > 0) {
139142
$this->context->setConstraint($formConstraint);
140-
$this->context->buildViolation($config->getOption('extra_fields_message'))
143+
$this->context->buildViolation($config->getOption('extra_fields_message', ''))
141144
->setParameter('{{ extra_fields }}', '"'.implode('", "', array_keys($form->getExtraData())).'"')
142145
->setInvalidValue($form->getExtraData())
143146
->setCode(Form::NO_SUCH_FIELD_ERROR)

src/Symfony/Component/Form/Form.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class Form implements \IteratorAggregate, FormInterface, ClearableErrorsInterfac
145145
private $lockSetData = false;
146146

147147
/**
148-
* @var string|int|null
148+
* @var string|null
149149
*/
150150
private $name;
151151

@@ -846,6 +846,8 @@ public function add($child, $type = null, array $options = [])
846846
throw new UnexpectedTypeException($child, 'string, integer or Symfony\Component\Form\FormInterface');
847847
}
848848

849+
$child = (string) $child;
850+
849851
if (null !== $type && !\is_string($type) && !$type instanceof FormTypeInterface) {
850852
throw new UnexpectedTypeException($type, 'string or Symfony\Component\Form\FormTypeInterface');
851853
}

0 commit comments

Comments
 (0)
0