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 953ac3e

Browse filesBrowse files
Merge branch '4.2' into 4.3
* 4.2: [Cache] replace getNsSeparator by NS_SEPARATOR on AbstractTrait [Cache] fix versioning with SimpleCacheAdapter 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 12b852f + 6b61439 commit 953ac3e
Copy full SHA for 953ac3e

File tree

30 files changed

+295
-68
lines changed
Filter options

30 files changed

+295
-68
lines changed

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

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Adapter/Psr16Adapter.php
+5Lines 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/Simple/AbstractCache.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Simple/AbstractCache.php
+5Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@
2727
*/
2828
abstract class AbstractCache implements Psr16CacheInterface, LoggerAwareInterface, ResettableInterface
2929
{
30+
/**
31+
* @internal
32+
*/
33+
protected const NS_SEPARATOR = ':';
34+
3035
use AbstractTrait {
3136
deleteItems as private;
3237
AbstractTrait::deleteItem as delete;

‎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/Psr16AdapterTest.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/Cache/Tests/Adapter/Psr16AdapterTest.php
+11Lines 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/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\SimpleCacheAdapter;
1515
use Symfony\Component\Cache\Simple\FilesystemCache;
16+
use Symfony\Component\Cache\Simple\ArrayCache;
1617

1718
/**
1819
* @group time-sensitive
@@ -28,4 +29,14 @@ public function createCachePool($defaultLifetime = 0)
2829
{
2930
return new SimpleCacheAdapter(new FilesystemCache(), '', $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
+8-8Lines changed: 8 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::NS_SEPARATOR, 5);
111111
try {
112-
$cleared = $this->doSave(['/'.$this->namespace => $namespaceVersion], 0);
112+
$cleared = $this->doSave([static::NS_SEPARATOR.$this->namespace => $namespaceVersion], 0);
113113
} catch (\Exception $e) {
114114
$cleared = false;
115115
}
@@ -243,14 +243,14 @@ private function getId($key)
243243
{
244244
if ($this->versioningIsEnabled && '' === $this->namespaceVersion) {
245245
$this->ids = [];
246-
$this->namespaceVersion = '1/';
246+
$this->namespaceVersion = '1'.static::NS_SEPARATOR;
247247
try {
248-
foreach ($this->doFetch(['/'.$this->namespace]) as $v) {
248+
foreach ($this->doFetch([static::NS_SEPARATOR.$this->namespace]) as $v) {
249249
$this->namespaceVersion = $v;
250250
}
251-
if ('1:' === $this->namespaceVersion) {
252-
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), ':', 5);
253-
$this->doSave(['@'.$this->namespace => $this->namespaceVersion], 0);
251+
if ('1'.static::NS_SEPARATOR === $this->namespaceVersion) {
252+
$this->namespaceVersion = substr_replace(base64_encode(pack('V', time())), static::NS_SEPARATOR, 5);
253+
$this->doSave([static::NS_SEPARATOR.$this->namespace => $this->namespaceVersion], 0);
254254
}
255255
} catch (\Exception $e) {
256256
}
@@ -267,7 +267,7 @@ private function getId($key)
267267
}
268268
if (\strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) {
269269
// Use MD5 to favor speed over security, which is not an issue here
270-
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), ':', -(\strlen($this->namespaceVersion) + 2));
270+
$this->ids[$key] = $id = substr_replace(base64_encode(hash('md5', $key, true)), static::NS_SEPARATOR, -(\strlen($this->namespaceVersion) + 2));
271271
$id = $this->namespace.$this->namespaceVersion.$id;
272272
}
273273

‎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;
@@ -714,6 +715,63 @@ public function testCauseForNotAllowedExtraFieldsIsTheFormConstraint()
714715
$this->assertSame($constraint, $context->getViolations()->get(0)->getConstraint());
715716
}
716717

718+
public function testNonCompositeConstraintValidatedOnce()
719+
{
720+
$form = $this
721+
->getBuilder('form', null, [
722+
'constraints' => [new NotBlank(['groups' => ['foo', 'bar']])],
723+
'validation_groups' => ['foo', 'bar'],
724+
])
725+
->setCompound(false)
726+
->getForm();
727+
$form->submit('');
728+
729+
$context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator());
730+
$this->validator->initialize($context);
731+
$this->validator->validate($form, new Form());
732+
733+
$this->assertCount(1, $context->getViolations());
734+
$this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage());
735+
$this->assertSame('data', $context->getViolations()[0]->getPropertyPath());
736+
}
737+
738+
public function testCompositeConstraintValidatedInEachGroup()
739+
{
740+
$form = $this->getBuilder('form', null, [
741+
'constraints' => [
742+
new Collection([
743+
'field1' => new NotBlank([
744+
'groups' => ['field1'],
745+
]),
746+
'field2' => new NotBlank([
747+
'groups' => ['field2'],
748+
]),
749+
]),
750+
],
751+
'validation_groups' => ['field1', 'field2'],
752+
])
753+
->setData([])
754+
->setCompound(true)
755+
->setDataMapper(new PropertyPathMapper())
756+
->getForm();
757+
$form->add($this->getForm('field1'));
758+
$form->add($this->getForm('field2'));
759+
$form->submit([
760+
'field1' => '',
761+
'field2' => '',
762+
]);
763+
764+
$context = new ExecutionContext(Validation::createValidator(), $form, new IdentityTranslator());
765+
$this->validator->initialize($context);
766+
$this->validator->validate($form, new Form());
767+
768+
$this->assertCount(2, $context->getViolations());
769+
$this->assertSame('This value should not be blank.', $context->getViolations()[0]->getMessage());
770+
$this->assertSame('data[field1]', $context->getViolations()[0]->getPropertyPath());
771+
$this->assertSame('This value should not be blank.', $context->getViolations()[1]->getMessage());
772+
$this->assertSame('data[field2]', $context->getViolations()[1]->getPropertyPath());
773+
}
774+
717775
protected function createValidator()
718776
{
719777
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;

0 commit comments

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