From 89314b5992d0cf3c10d1e1f9554724c308e16041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4dlich?= Date: Fri, 10 Jul 2020 08:34:45 +0200 Subject: [PATCH 1/9] add vietnamese translation for html5 color validation --- .../Component/Form/Resources/translations/validators.vi.xlf | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf index b5b2f83a9a..1b689fa3ee 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf @@ -14,6 +14,10 @@ The CSRF token is invalid. Please try to resubmit the form. CSRF token không hợp lệ. Vui lòng thử lại. + + This value is not a valid HTML5 color. + Giá trị này không phải là màu HTML5 hợp lệ. + From 6eb836b6f9b98c3c1b3078af6afd14c8ab3296e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Fri, 10 Jul 2020 11:08:50 +0200 Subject: [PATCH 2/9] [OptionsResolver] Fix force prepend normalizer --- .../Component/OptionsResolver/OptionsResolver.php | 1 + .../OptionsResolver/Tests/OptionsResolverTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php index 3fb3c06f92..d1aad4619b 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php +++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php @@ -532,6 +532,7 @@ class OptionsResolver implements Options } if ($forcePrepend) { + $this->normalizers[$option] = $this->normalizers[$option] ?? []; array_unshift($this->normalizers[$option], $normalizer); } else { $this->normalizers[$option][] = $normalizer; diff --git a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php index 8e3c1d3331..1fa0e54645 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php +++ b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php @@ -1506,6 +1506,17 @@ class OptionsResolverTest extends TestCase $this->assertEquals(['foo' => '2nd-normalized-1st-normalized-bar'], $this->resolver->resolve()); } + public function testForcePrependNormalizerForResolverWithoutPreviousNormalizers() + { + // defined by superclass + $this->resolver->setDefault('foo', 'bar'); + $this->resolver->addNormalizer('foo', function (Options $options, $value) { + return '1st-normalized-'.$value; + }, true); + + $this->assertEquals(['foo' => '1st-normalized-bar'], $this->resolver->resolve()); + } + public function testAddNormalizerFailsIfUnknownOption() { $this->expectException('Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException'); From acea9be6d3167e587f24a2f4a0a56cefaf2b7387 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 10 Jul 2020 16:23:16 +0200 Subject: [PATCH 3/9] sync translations from master --- .../Resources/translations/validators.en.xlf | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.en.xlf b/src/Symfony/Component/Form/Resources/translations/validators.en.xlf index 89814258d1..97ed83fd47 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.en.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.en.xlf @@ -18,6 +18,102 @@ This value is not a valid HTML5 color. This value is not a valid HTML5 color. + + Please enter a valid birthdate. + Please enter a valid birthdate. + + + The selected choice is invalid. + The selected choice is invalid. + + + The collection is invalid. + The collection is invalid. + + + Please select a valid color. + Please select a valid color. + + + Please select a valid country. + Please select a valid country. + + + Please select a valid currency. + Please select a valid currency. + + + Please choose a valid date interval. + Please choose a valid date interval. + + + Please enter a valid date and time. + Please enter a valid date and time. + + + Please enter a valid date. + Please enter a valid date. + + + Please select a valid file. + Please select a valid file. + + + The hidden field is invalid. + The hidden field is invalid. + + + Please enter an integer. + Please enter an integer. + + + Please select a valid language. + Please select a valid language. + + + Please select a valid locale. + Please select a valid locale. + + + Please enter a valid money amount. + Please enter a valid money amount. + + + Please enter a number. + Please enter a number. + + + The password is invalid. + The password is invalid. + + + Please enter a percentage value. + Please enter a percentage value. + + + The values do not match. + The values do not match. + + + Please enter a valid time. + Please enter a valid time. + + + Please select a valid timezone. + Please select a valid timezone. + + + Please enter a valid URL. + Please enter a valid URL. + + + Please enter a valid search term. + Please enter a valid search term. + + + Please provide a valid phone number. + Please provide a valid phone number. + From 68e2b34a9f1ae1aba93013af8ab784f3bf68cacc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Sch=C3=A4dlich?= Date: Sat, 11 Jul 2020 12:37:37 +0200 Subject: [PATCH 4/9] [Form] Add missing vietnamese translations --- .../Resources/translations/validators.vi.xlf | 98 ++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf index 1b689fa3ee..4d060fbe0d 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.vi.xlf @@ -4,7 +4,7 @@ This form should not contain extra fields. - Mẫu này không nên chứa trường mở rộng + Mẫu này không nên chứa trường mở rộng. The uploaded file was too large. Please try to upload a smaller file. @@ -18,6 +18,102 @@ This value is not a valid HTML5 color. Giá trị này không phải là màu HTML5 hợp lệ. + + Please enter a valid birthdate. + Vui lòng nhập ngày sinh hợp lệ. + + + The selected choice is invalid. + Lựa chọn không hợp lệ. + + + The collection is invalid. + Danh sách không hợp lệ. + + + Please select a valid color. + Vui lòng chọn một màu hợp lệ. + + + Please select a valid country. + Vui lòng chọn đất nước hợp lệ. + + + Please select a valid currency. + Vui lòng chọn tiền tệ hợp lệ. + + + Please choose a valid date interval. + Vui lòng chọn một khoảng thời gian hợp lệ. + + + Please enter a valid date and time. + Vui lòng nhập ngày và thời gian hợp lệ. + + + Please enter a valid date. + Vui lòng nhập ngày hợp lệ. + + + Please select a valid file. + Vui lòng chọn tệp hợp lệ. + + + The hidden field is invalid. + Phạm vi ẩn không hợp lệ. + + + Please enter an integer. + Vui lòng nhập một số nguyên. + + + Please select a valid language. + Vui lòng chọn ngôn ngữ hợp lệ. + + + Please select a valid locale. + Vui lòng chọn miền hợp lệ. + + + Please enter a valid money amount. + Vui lòng nhập một khoảng tiền hợp lệ. + + + Please enter a number. + Vui lòng nhập một con số. + + + The password is invalid. + Mật khẩu không hợp lệ. + + + Please enter a percentage value. + Vui lòng nhập một giá trị phần trăm. + + + The values do not match. + Các giá trị không phù hợp. + + + Please enter a valid time. + Vui lòng nhập thời gian hợp lệ. + + + Please select a valid timezone. + Vui lòng chọn múi giờ hợp lệ. + + + Please enter a valid URL. + Vui lòng nhập một URL hợp lệ. + + + Please enter a valid search term. + Vui lòng nhập chuỗi tìm kiếm hợp lệ. + + + Please provide a valid phone number. + Vui lòng cung cấp số điện thoại hợp lệ. + From 1809b7c5eb2d091809c5c627e8aadda2ff893afe Mon Sep 17 00:00:00 2001 From: Marco Petersen Date: Fri, 10 Jul 2020 18:19:49 +0200 Subject: [PATCH 5/9] Add Tagalog translations for new form messages --- .../Resources/translations/validators.tl.xlf | 100 ++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf index 02def0bf31..950c4110d8 100644 --- a/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf +++ b/src/Symfony/Component/Form/Resources/translations/validators.tl.xlf @@ -14,6 +14,106 @@ The CSRF token is invalid. Please try to resubmit the form. Hindi balido ang CSRF token. Maagpasa muli ng isang pang porma. + + This value is not a valid HTML5 color. + Ang halagang ito ay hindi wastong HTML5 color. + + + Please enter a valid birthdate. + Pakilagay ang tamang petsa ng kapanganakan. + + + The selected choice is invalid. + Ang pinagpiliang sagot ay hindi tama. + + + The collection is invalid. + Hindi balido ang koleksyon. + + + Please select a valid color. + Pakipiliin ang nararapat na kulay. + + + Please select a valid country. + Pakipiliin ang nararapat na bansa. + + + Please select a valid currency. + Pakipiliin ang tamang pananalapi. + + + Please choose a valid date interval. + Piliin ang wastong agwat ng petsa. + + + Please enter a valid date and time. + Piliin ang wastong petsa at oras. + + + Please enter a valid date. + Ilagay ang wastong petsa. + + + Please select a valid file. + Piliin ang balidong file. + + + The hidden field is invalid. + Hindi balido ang field na nakatago. + + + Please enter an integer. + Pakilagay ang integer. + + + Please select a valid language. + Piliin ang nararapat na lengguwahe. + + + Please select a valid locale. + Pakipili ang nararapat na locale. + + + Please enter a valid money amount. + Pakilagay ang tamang halaga ng pera. + + + Please enter a number. + Ilagay ang numero. + + + The password is invalid. + Hindi balido ang password. + + + Please enter a percentage value. + Pakilagay ang tamang porsyento ng halaga. + + + The values do not match. + Hindi tugma ang mga halaga. + + + Please enter a valid time. + Pakilagay ang tamang oras. + + + Please select a valid timezone. + Pakilagay ang tamang sona ng oras. + + + Please enter a valid URL. + Pakilagay ang balidong URL. + + + Please enter a valid search term. + Pakilagay ang balidong katagang sinasaliksik. + + + Please provide a valid phone number. + Pakilagay ang balidong numero ng telepono. + From 2effda79ea4399883eaca11cdc47169c26280138 Mon Sep 17 00:00:00 2001 From: Vincent Langlet Date: Wed, 8 Jul 2020 12:13:35 +0200 Subject: [PATCH 6/9] [Form] Fix ChoiceType translation domain --- .../Form/Extension/Core/Type/ChoiceType.php | 2 +- .../Extension/Core/Type/ChoiceTypeTest.php | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 1e506bf168..fccb64b39d 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -386,7 +386,7 @@ class ChoiceType extends AbstractType 'value' => $choiceView->value, 'label' => $choiceView->label, 'attr' => $choiceView->attr, - 'translation_domain' => $options['translation_domain'], + 'translation_domain' => $options['choice_translation_domain'], 'block_name' => 'entry', ]; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php index 9b2b0e64a5..ce795517b8 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ChoiceTypeTest.php @@ -1994,6 +1994,24 @@ class ChoiceTypeTest extends BaseTypeTest $this->assertEquals('_09name', $view->vars['full_name']); } + public function testSubFormTranslationDomain() + { + $form = $this->factory->create(static::TESTED_TYPE, null, [ + 'label' => 'label', + 'translation_domain' => 'label_translation_domain', + 'choices' => [ + 'choice1' => true, + 'choice2' => false, + ], + 'choice_translation_domain' => 'choice_translation_domain', + 'expanded' => true, + ])->createView(); + + $this->assertCount(2, $form->children); + $this->assertSame('choice_translation_domain', $form->children[0]->vars['translation_domain']); + $this->assertSame('choice_translation_domain', $form->children[1]->vars['translation_domain']); + } + /** * @dataProvider provideTrimCases */ From 4273aedfae3f29c72b8ee500fe28c651cf231dc6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Jul 2020 12:21:23 +0200 Subject: [PATCH 7/9] Fix DBAL deprecation --- .../RememberMe/DoctrineTokenProvider.php | 18 +++++++++++++++--- .../RememberMe/DoctrineTokenProviderTest.php | 2 +- .../Component/Cache/Traits/PdoTrait.php | 18 +++++++++++++++--- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php index c6e4ab3a30..d407f8e0e8 100644 --- a/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php +++ b/src/Symfony/Bridge/Doctrine/Security/RememberMe/DoctrineTokenProvider.php @@ -81,7 +81,11 @@ class DoctrineTokenProvider implements TokenProviderInterface $sql = 'DELETE FROM rememberme_token WHERE series=:series'; $paramValues = ['series' => $series]; $paramTypes = ['series' => \PDO::PARAM_STR]; - $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + if (method_exists($this->conn, 'executeStatement')) { + $this->conn->executeStatement($sql, $paramValues, $paramTypes); + } else { + $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + } } /** @@ -101,7 +105,11 @@ class DoctrineTokenProvider implements TokenProviderInterface 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, 'series' => \PDO::PARAM_STR, ]; - $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + if (method_exists($this->conn, 'executeStatement')) { + $updated = $this->conn->executeStatement($sql, $paramValues, $paramTypes); + } else { + $updated = $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + } if ($updated < 1) { throw new TokenNotFoundException('No token found.'); } @@ -129,6 +137,10 @@ class DoctrineTokenProvider implements TokenProviderInterface 'value' => \PDO::PARAM_STR, 'lastUsed' => self::$useDeprecatedConstants ? Type::DATETIME : Types::DATETIME_MUTABLE, ]; - $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + if (method_exists($this->conn, 'executeStatement')) { + $this->conn->executeStatement($sql, $paramValues, $paramTypes); + } else { + $this->conn->executeUpdate($sql, $paramValues, $paramTypes); + } } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php index 9c86ecacb2..12db31ce8d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php @@ -72,7 +72,7 @@ class DoctrineTokenProviderTest extends TestCase 'driver' => 'pdo_sqlite', 'url' => 'sqlite:///:memory:', ]); - $connection->executeUpdate(<<< 'SQL' + $connection->{method_exists($this->conn, 'executeStatement') ? 'executeStatement' : 'executeUpdate'}(<<< 'SQL' CREATE TABLE rememberme_token ( series char(88) UNIQUE PRIMARY KEY NOT NULL, value char(88) NOT NULL, diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index aaf364304f..686d111d9b 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -107,7 +107,11 @@ trait PdoTrait $table->setPrimaryKey([$this->idCol]); foreach ($schema->toSql($conn->getDatabasePlatform()) as $sql) { - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } } return; @@ -138,7 +142,11 @@ trait PdoTrait throw new \DomainException(sprintf('Creating the cache table is currently not implemented for PDO driver "%s".', $this->driver)); } - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } } /** @@ -238,7 +246,11 @@ trait PdoTrait $sql = "DELETE FROM $this->table WHERE $this->idCol LIKE '$namespace%'"; } - $conn->exec($sql); + if (method_exists($conn, 'executeStatement')) { + $conn->executeStatement($sql); + } else { + $conn->exec($sql); + } return true; } From adc79e30351f4beb8a34e0321cc1455affc29007 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 12 Jul 2020 13:20:43 +0200 Subject: [PATCH 8/9] Fix typo --- .../Tests/Security/RememberMe/DoctrineTokenProviderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php index 12db31ce8d..73588ce2bb 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Security/RememberMe/DoctrineTokenProviderTest.php @@ -72,7 +72,7 @@ class DoctrineTokenProviderTest extends TestCase 'driver' => 'pdo_sqlite', 'url' => 'sqlite:///:memory:', ]); - $connection->{method_exists($this->conn, 'executeStatement') ? 'executeStatement' : 'executeUpdate'}(<<< 'SQL' + $connection->{method_exists($connection, 'executeStatement') ? 'executeStatement' : 'executeUpdate'}(<<< 'SQL' CREATE TABLE rememberme_token ( series char(88) UNIQUE PRIMARY KEY NOT NULL, value char(88) NOT NULL, From 49e9f3229c1441398f30d45393a1a99219b65f1c Mon Sep 17 00:00:00 2001 From: Philipp Kolesnikov Date: Wed, 8 Jul 2020 16:33:42 +1000 Subject: [PATCH 9/9] [Cache] Use the default expiry when saving (not when creating) items --- .../Cache/Adapter/AbstractAdapter.php | 9 +- .../Component/Cache/Adapter/ArrayAdapter.php | 9 +- .../Component/Cache/Adapter/ChainAdapter.php | 8 +- .../Component/Cache/Adapter/ProxyAdapter.php | 9 +- .../Cache/Adapter/TagAwareAdapter.php | 4 +- src/Symfony/Component/Cache/CacheItem.php | 5 +- .../Cache/Tests/Adapter/ChainAdapterTest.php | 120 +++++++++++++++++- .../Cache/Tests/Fixtures/ExternalAdapter.php | 4 +- 8 files changed, 141 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index ce1262ae17..4022307284 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -48,12 +48,11 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s").', $this->maxIdLength - 24, \strlen($namespace), $namespace)); } $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) use ($defaultLifetime) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; return $item; }, @@ -62,14 +61,16 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface ); $getId = function ($key) { return $this->getId((string) $key); }; $this->mergeByLifetime = \Closure::bind( - static function ($deferred, $namespace, &$expiredIds) use ($getId) { + static function ($deferred, $namespace, &$expiredIds) use ($getId, $defaultLifetime) { $byLifetime = []; $now = time(); $expiredIds = []; foreach ($deferred as $key => $item) { if (null === $item->expiry) { - $byLifetime[0 < $item->defaultLifetime ? $item->defaultLifetime : 0][$getId($key)] = $item->value; + $byLifetime[0 < $defaultLifetime ? $defaultLifetime : 0][$getId($key)] = $item->value; + } elseif (0 === $item->expiry) { + $byLifetime[0][$getId($key)] = $item->value; } elseif ($item->expiry > $now) { $byLifetime[$item->expiry - $now][$getId($key)] = $item->value; } else { diff --git a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php index 4c6695e267..ff826f47a2 100644 --- a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php @@ -25,6 +25,7 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable use ArrayTrait; private $createCacheItem; + private $defaultLifetime; /** * @param int $defaultLifetime @@ -32,14 +33,14 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable */ public function __construct($defaultLifetime = 0, $storeSerialized = true) { + $this->defaultLifetime = $defaultLifetime; $this->storeSerialized = $storeSerialized; $this->createCacheItem = \Closure::bind( - static function ($key, $value, $isHit) use ($defaultLifetime) { + static function ($key, $value, $isHit) { $item = new CacheItem(); $item->key = $key; $item->value = $value; $item->isHit = $isHit; - $item->defaultLifetime = $defaultLifetime; return $item; }, @@ -127,8 +128,8 @@ class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, Resettable return false; } } - if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { - $expiry = time() + $item["\0*\0defaultLifetime"]; + if (null === $expiry && 0 < $this->defaultLifetime) { + $expiry = time() + $this->defaultLifetime; } $this->values[$key] = $value; diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index c2c9f4a800..2bf89bcf96 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -61,14 +61,10 @@ class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableIn $this->syncItem = \Closure::bind( static function ($sourceItem, $item) use ($defaultLifetime) { $item->value = $sourceItem->value; - $item->expiry = $sourceItem->expiry; $item->isHit = $sourceItem->isHit; - if (0 < $sourceItem->defaultLifetime && $sourceItem->defaultLifetime < $defaultLifetime) { - $defaultLifetime = $sourceItem->defaultLifetime; - } - if (0 < $defaultLifetime && ($item->defaultLifetime <= 0 || $defaultLifetime < $item->defaultLifetime)) { - $item->defaultLifetime = $defaultLifetime; + if (0 < $defaultLifetime) { + $item->expiresAfter($defaultLifetime); } return $item; diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index f574826844..c89a760ed2 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -29,6 +29,7 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn private $namespaceLen; private $createCacheItem; private $poolHash; + private $defaultLifetime; /** * @param string $namespace @@ -40,11 +41,11 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn $this->poolHash = $poolHash = spl_object_hash($pool); $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace); $this->namespaceLen = \strlen($namespace); + $this->defaultLifetime = $defaultLifetime; $this->createCacheItem = \Closure::bind( - static function ($key, $innerItem) use ($defaultLifetime, $poolHash) { + static function ($key, $innerItem) use ($poolHash) { $item = new CacheItem(); $item->key = $key; - $item->defaultLifetime = $defaultLifetime; $item->poolHash = $poolHash; if (null !== $innerItem) { @@ -155,8 +156,8 @@ class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableIn } $item = (array) $item; $expiry = $item["\0*\0expiry"]; - if (null === $expiry && 0 < $item["\0*\0defaultLifetime"]) { - $expiry = time() + $item["\0*\0defaultLifetime"]; + if (null === $expiry && 0 < $this->defaultLifetime) { + $expiry = time() + $this->defaultLifetime; } if ($item["\0*\0poolHash"] === $this->poolHash && $item["\0*\0innerItem"]) { diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index ecdd0d6991..febe50900a 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -46,7 +46,6 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R $item = new CacheItem(); $item->key = $key; $item->value = $value; - $item->defaultLifetime = $protoItem->defaultLifetime; $item->expiry = $protoItem->expiry; $item->poolHash = $protoItem->poolHash; @@ -90,8 +89,7 @@ class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, R $this->invalidateTags = \Closure::bind( static function (AdapterInterface $tagsAdapter, array $tags) { foreach ($tags as $v) { - $v->defaultLifetime = 0; - $v->expiry = null; + $v->expiry = 0; $tagsAdapter->saveDeferred($v); } diff --git a/src/Symfony/Component/Cache/CacheItem.php b/src/Symfony/Component/Cache/CacheItem.php index b16ad0faf7..e802c30729 100644 --- a/src/Symfony/Component/Cache/CacheItem.php +++ b/src/Symfony/Component/Cache/CacheItem.php @@ -24,7 +24,6 @@ final class CacheItem implements CacheItemInterface protected $value; protected $isHit = false; protected $expiry; - protected $defaultLifetime; protected $tags = []; protected $prevTags = []; protected $innerItem; @@ -74,7 +73,7 @@ final class CacheItem implements CacheItemInterface public function expiresAt($expiration) { if (null === $expiration) { - $this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null; + $this->expiry = null; } elseif ($expiration instanceof \DateTimeInterface) { $this->expiry = (int) $expiration->format('U'); } else { @@ -92,7 +91,7 @@ final class CacheItem implements CacheItemInterface public function expiresAfter($time) { if (null === $time) { - $this->expiry = $this->defaultLifetime > 0 ? time() + $this->defaultLifetime : null; + $this->expiry = null; } elseif ($time instanceof \DateInterval) { $this->expiry = (int) \DateTime::createFromFormat('U', time())->add($time)->format('U'); } elseif (\is_int($time)) { diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php index 5e48930dd1..be811d6fd7 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php @@ -27,7 +27,7 @@ class ChainAdapterTest extends AdapterTestCase { public function createCachePool($defaultLifetime = 0) { - return new ChainAdapter([new ArrayAdapter($defaultLifetime), new ExternalAdapter(), new FilesystemAdapter('', $defaultLifetime)], $defaultLifetime); + return new ChainAdapter([new ArrayAdapter($defaultLifetime), new ExternalAdapter($defaultLifetime), new FilesystemAdapter('', $defaultLifetime)], $defaultLifetime); } public function testEmptyAdaptersException() @@ -65,6 +65,124 @@ class ChainAdapterTest extends AdapterTestCase $this->assertFalse($cache->prune()); } + public function testMultipleCachesExpirationWhenCommonTtlIsNotSet() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $adapter1 = new ArrayAdapter(4); + $adapter2 = new ArrayAdapter(2); + + $cache = new ChainAdapter([$adapter1, $adapter2]); + + $cache->save($cache->getItem('key')->set('value')); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertFalse($item->isHit()); + + $adapter2->save($adapter2->getItem('key1')->set('value1')); + + $item = $cache->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + $item = $adapter2->getItem('key1'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertFalse($item->isHit()); + } + + public function testMultipleCachesExpirationWhenCommonTtlIsSet() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $adapter1 = new ArrayAdapter(4); + $adapter2 = new ArrayAdapter(2); + + $cache = new ChainAdapter([$adapter1, $adapter2], 6); + + $cache->save($cache->getItem('key')->set('value')); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value', $item->get()); + + $item = $adapter2->getItem('key'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key'); + $this->assertFalse($item->isHit()); + + $adapter2->save($adapter2->getItem('key1')->set('value1')); + + $item = $cache->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + $item = $adapter2->getItem('key1'); + $this->assertFalse($item->isHit()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertTrue($item->isHit()); + $this->assertEquals('value1', $item->get()); + + sleep(2); + + $item = $adapter1->getItem('key1'); + $this->assertFalse($item->isHit()); + } + /** * @return MockObject|PruneableCacheInterface */ diff --git a/src/Symfony/Component/Cache/Tests/Fixtures/ExternalAdapter.php b/src/Symfony/Component/Cache/Tests/Fixtures/ExternalAdapter.php index 779a374ec7..be1f990121 100644 --- a/src/Symfony/Component/Cache/Tests/Fixtures/ExternalAdapter.php +++ b/src/Symfony/Component/Cache/Tests/Fixtures/ExternalAdapter.php @@ -24,9 +24,9 @@ class ExternalAdapter implements CacheItemPoolInterface { private $cache; - public function __construct() + public function __construct($defaultLifetime = 0) { - $this->cache = new ArrayAdapter(); + $this->cache = new ArrayAdapter($defaultLifetime); } public function getItem($key)