Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 06c17cd

Browse filesBrowse files
Merge branch '3.4' into 4.2
* 3.4: Fix expired lock not cleaned [HttpFoundation] Fix SA/phpdoc JsonResponse 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 Fix binary operation `+`, `-` or `*` on string [VarDumper] fix dumping objects that implement __debugInfo() [Routing] fix absolute url generation when scheme is not known
2 parents 37fa45b + cfc8ac0 commit 06c17cd
Copy full SHA for 06c17cd

File tree

Expand file treeCollapse file tree

28 files changed

+285
-68
lines changed
Filter options
Expand file treeCollapse file tree

28 files changed

+285
-68
lines changed

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Adapter/AbstractAdapter.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ abstract class AbstractAdapter implements AdapterInterface, CacheInterface, Logg
3838

3939
protected function __construct(string $namespace = '', int $defaultLifetime = 0)
4040
{
41-
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':';
41+
$this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).static::getNsSeparator();
4242
if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength - 24) {
4343
throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, \strlen($namespace), $namespace));
4444
}

‎src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php
+8Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,12 @@ protected function doSave(array $values, $lifetime)
7575
{
7676
return $this->pool->setMultiple($values, 0 === $lifetime ? null : $lifetime);
7777
}
78+
79+
/**
80+
* @return string the namespace separator for cache keys
81+
*/
82+
protected static function getNsSeparator()
83+
{
84+
return '_';
85+
}
7886
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/MaxIdLengthAdapterTest.php
+1-1Lines 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/SimpleCacheAdapterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/SimpleCacheAdapterTest.php
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
1515
use Symfony\Component\Cache\Adapter\SimpleCacheAdapter;
16+
use Symfony\Component\Cache\Simple\ArrayCache;
1617
use Symfony\Component\Cache\Simple\Psr6Cache;
1718

1819
/**
@@ -28,4 +29,14 @@ public function createCachePool($defaultLifetime = 0)
2829
{
2930
return new SimpleCacheAdapter(new Psr6Cache(new FilesystemAdapter()), '', $defaultLifetime);
3031
}
32+
33+
public function testValidCacheKeyWithNamespace()
34+
{
35+
$cache = new SimpleCacheAdapter(new ArrayCache(), '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/AbstractTrait.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Traits/AbstractTrait.php
+16-8Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ public function clear()
107107
{
108108
$this->deferred = [];
109109
if ($cleared = $this->versioningIsEnabled) {
110-
$namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), ':', 5);
110+
$namespaceVersion = substr_replace(base64_encode(pack('V', mt_rand())), static::getNsSeparator(), 5);
111111
try {
112-
$cleared = $this->doSave(['/'.$this->namespace => $namespaceVersion], 0);
112+
$cleared = $this->doSave([static::getNsSeparator().$this->namespace => $namespaceVersion], 0);
113113
} catch (\Exception $e) {
114114
$cleared = false;
115115
}
@@ -242,14 +242,14 @@ private function getId($key)
242242
{
243243
if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
244244
$this->ids = [];
245-
$this->namespaceVersion = '1/';
245+
$this->namespaceVersion = '1'.static::getNsSeparator();
246246
try {
247-
foreach ($this->doFetch(['/'.$this->namespace]) as $v) {
247+
foreach ($this->doFetch([static::getNsSeparator().$this->namespace]) as $v) {
248248
$this->namespaceVersion = $v;
249249
}
250-
if ('1:' === $this->namespaceVersion) {
251-
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), ':', 5);
252-
$this->doSave(['@'.$this->namespace => $this->namespaceVersion], 0);
250+
if ('1'.static::getNsSeparator() === $this->namespaceVersion) {
251+
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::getNsSeparator(), 5);
252+
$this->doSave([static::getNsSeparator().$this->namespace => $this->namespaceVersion], 0);
253253
}
254254
} catch (\Exception $e) {
255255
}
@@ -266,7 +266,7 @@ private function getId($key)
266266
}
267267
if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) {
268268
// Use MD5 to favor speed over security, which is not an issue here
269-
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), ':', -(\strlen($this->namespaceVersion) + 2));
269+
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::getNsSeparator(), -(\strlen($this->namespaceVersion) + 2));
270270
$id = $this->namespace.$this->namespaceVersion.$id;
271271
}
272272

@@ -280,4 +280,12 @@ public static function handleUnserializeCallback($class)
280280
{
281281
throw new \DomainException('Class not found: '.$class);
282282
}
283+
284+
/**
285+
* @return string the namespace separator for cache keys
286+
*/
287+
protected static function getNsSeparator()
288+
{
289+
return ':';
290+
}
283291
}

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/Type/BirthdayType.php
+1-1Lines 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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Core/Type/DateType.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ public function configureOptions(OptionsResolver $resolver)
259259
};
260260

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

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php
+4-1Lines changed: 4 additions & 1 deletion
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
}

‎src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php
+58Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
use Symfony\Component\Form\FormInterface;
2525
use Symfony\Component\Form\SubmitButtonBuilder;
2626
use Symfony\Component\Translation\IdentityTranslator;
27+
use Symfony\Component\Validator\Constraints\Collection;
2728
use Symfony\Component\Validator\Constraints\GroupSequence;
2829
use Symfony\Component\Validator\Constraints\NotBlank;
2930
use Symfony\Component\Validator\Constraints\NotNull;
@@ -673,6 +674,63 @@ public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint()
673674
$this->assertSame($constraint, $context->getViolations()->get(0)->getConstraint());
674675
}
675676

677+
public function testNonCompositeConstraintValidatedOnce()
678+
{
679+
$form = $this
680+
->getBuilder('form', null, [
681+
'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])],
682+
'validation_groups' => ['foo', 'bar'],
683+
])
684+
->setCompound(false)
685+
->getForm();
686+
$form->submit('');
687+
688+
$context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator());
689+
$this->validator->initialize($context);
690+
$this->validator->validate($form, new Form());
691+
692+
$this->assertCount(1, $context->getViolations());
693+
$this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage());
694+
$this->assertSame('data', $context->getViolations()[0]->getPropertyPath());
695+
}
696+
697+
public function testCompositeConstraintValidatedInEachGroup()
698+
{
699+
$form = $this->getBuilder('form', null, [
700+
'constraints' => [
701+
new Collection([
702+
'field1' => new NotBlank([
703+
'groups' => ['field1'],
704+
]),
705+
'field2' => new NotBlank([
706+
'groups' => ['field2'],
707+
]),
708+
]),
709+
],
710+
'validation_groups' => ['field1', 'field2'],
711+
])
712+
->setData([])
713+
->setCompound(true)
714+
->setDataMapper(new PropertyPathMapper())
715+
->getForm();
716+
$form->add($this->getForm('field1'));
717+
$form->add($this->getForm('field2'));
718+
$form->submit([
719+
'field1' => '',
720+
'field2' => '',
721+
]);
722+
723+
$context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator());
724+
$this->validator->initialize($context);
725+
$this->validator->validate($form, new Form());
726+
727+
$this->assertCount(2, $context->getViolations());
728+
$this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage());
729+
$this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath());
730+
$this->assertSame('This value should not be blank.', $context->getViolations()[1]->getMessage());
731+
$this->assertSame('data[field2]', $context->getViolations()[1]->getPropertyPath());
732+
}
733+
676734
protected function createValidator()
677735
{
678736
return new FormValidator();

‎src/Symfony/Component/HttpFoundation/JsonResponse.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/JsonResponse.php
+14-3Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ public function __construct($data = null, int $status = 200, array $headers = []
5555
*
5656
* Example:
5757
*
58-
* return JsonResponse::create($data, 200)
58+
* return JsonResponse::create(['key' => 'value'])
5959
* ->setSharedMaxAge(300);
6060
*
61-
* @param mixed $data The json response data
61+
* @param mixed $data The JSON response data
6262
* @param int $status The response status code
6363
* @param array $headers An array of response headers
6464
*
@@ -70,7 +70,18 @@ public static function create($data = null, $status = 200, $headers = [])
7070
}
7171

7272
/**
73-
* Make easier the creation of JsonResponse from raw json.
73+
* Factory method for chainability.
74+
*
75+
* Example:
76+
*
77+
* return JsonResponse::fromJsonString('{"key": "value"}')
78+
* ->setSharedMaxAge(300);
79+
*
80+
* @param string|null $data The JSON response string
81+
* @param int $status The response status code
82+
* @param array $headers An array of response headers
83+
*
84+
* @return static
7485
*/
7586
public static function fromJsonString($data = null, $status = 200, $headers = [])
7687
{

‎src/Symfony/Component/HttpFoundation/Response.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpFoundation/Response.php
+2-2Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -684,7 +684,7 @@ public function getAge(): int
684684
return (int) $age;
685685
}
686686

687-
return max(time() - $this->getDate()->format('U'), 0);
687+
return max(time() - (int) $this->getDate()->format('U'), 0);
688688
}
689689

690690
/**
@@ -764,7 +764,7 @@ public function getMaxAge(): ?int
764764
}
765765

766766
if (null !== $this->getExpires()) {
767-
return (int) ($this->getExpires()->format('U') - $this->getDate()->format('U'));
767+
return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U');
768768
}
769769

770770
return null;

‎src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public function add(Response $response)
8585
$this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age);
8686

8787
$expires = $response->getExpires();
88-
$expires = null !== $expires ? $expires->format('U') - $response->getDate()->format('U') : null;
88+
$expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null;
8989
$this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0);
9090
}
9191

‎src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class DayOfYearTransformer extends Transformer
2525
*/
2626
public function format(\DateTime $dateTime, int $length): string
2727
{
28-
$dayOfYear = $dateTime->format('z') + 1;
28+
$dayOfYear = (int) $dateTime->format('z') + 1;
2929

3030
return $this->padLeft($dayOfYear, $length);
3131
}

‎src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ protected function calculateUnixTimestamp(\DateTime $dateTime, array $options)
315315
preg_match_all($this->regExp, $this->pattern, $matches);
316316
if (\in_array('yy', $matches[0])) {
317317
$dateTime->setTimestamp(time());
318-
$year = $year > $dateTime->format('y') + 20 ? 1900 + $year : 2000 + $year;
318+
$year = $year > (int) $dateTime->format('y') + 20 ? 1900 + $year : 2000 + $year;
319319
}
320320

321321
$dateTime->setDate($year, $month, $day);

‎src/Symfony/Component/Lock/Lock.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Lock/Lock.php
+10Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public function acquire($blocking = false)
8383
}
8484

8585
if ($this->key->isExpired()) {
86+
try {
87+
$this->release();
88+
} catch (\Exception $e) {
89+
// swallow exception to not hide the original issue
90+
}
8691
throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $this->key));
8792
}
8893

@@ -120,6 +125,11 @@ public function refresh($ttl = null)
120125
$this->dirty = true;
121126

122127
if ($this->key->isExpired()) {
128+
try {
129+
$this->release();
130+
} catch (\Exception $e) {
131+
// swallow exception to not hide the original issue
132+
}
123133
throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $this->key));
124134
}
125135

‎src/Symfony/Component/Lock/Store/CombinedStore.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Lock/Store/CombinedStore.php
+4-4Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
use Psr\Log\NullLogger;
1717
use Symfony\Component\Lock\Exception\InvalidArgumentException;
1818
use Symfony\Component\Lock\Exception\LockConflictedException;
19-
use Symfony\Component\Lock\Exception\LockExpiredException;
2019
use Symfony\Component\Lock\Exception\NotSupportedException;
2120
use Symfony\Component\Lock\Key;
2221
use Symfony\Component\Lock\StoreInterface;
@@ -30,6 +29,7 @@
3029
class CombinedStore implements StoreInterface, LoggerAwareInterface
3130
{
3231
use LoggerAwareTrait;
32+
use ExpiringStoreTrait;
3333

3434
/** @var StoreInterface[] */
3535
private $stores;
@@ -78,6 +78,8 @@ public function save(Key $key)
7878
}
7979
}
8080

81+
$this->checkNotExpired($key);
82+
8183
if ($this->strategy->isMet($successCount, $storesCount)) {
8284
return;
8385
}
@@ -125,9 +127,7 @@ public function putOffExpiration(Key $key, $ttl)
125127
}
126128
}
127129

128-
if ($key->isExpired()) {
129-
throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $key));
130-
}
130+
$this->checkNotExpired($key);
131131

132132
if ($this->strategy->isMet($successCount, $storesCount)) {
133133
return;
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\Lock\Store;
13+
14+
use Symfony\Component\Lock\Exception\LockExpiredException;
15+
use Symfony\Component\Lock\Key;
16+
17+
trait ExpiringStoreTrait
18+
{
19+
private function checkNotExpired(Key $key)
20+
{
21+
if ($key->isExpired()) {
22+
try {
23+
$this->delete($key);
24+
} catch (\Exception $e) {
25+
// swallow exception to not hide the original issue
26+
}
27+
throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $key));
28+
}
29+
}
30+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.