Skip to content

Commit c0293c0

Browse files
committed
[Validator] Deprecated CacheInterface in favor of PSR-6.
1 parent bbe221b commit c0293c0

10 files changed

+139
-29
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ CHANGELOG
2222
be used in the violation builder when both `min` and `max` are not null
2323
* added ability to use stringable objects as violation messages
2424
* Overriding the methods `ConstraintValidatorTestCase::setUp()` and `ConstraintValidatorTestCase::tearDown()` without the `void` return-type is deprecated.
25+
* deprecated `Symfony\Component\Validator\Mapping\Cache\CacheInterface` in favor of PSR-6.
26+
* deprecated `ValidatorBuilder::setMetadataCache`, use `ValidatorBuilder::setMappingCache` instead.
2527

2628
4.3.0
2729
-----

Mapping/Cache/CacheInterface.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@
1313

1414
use Symfony\Component\Validator\Mapping\ClassMetadata;
1515

16+
@trigger_error(sprintf('The "%s" interface is deprecated since Symfony 4.4.', CacheInterface::class), E_USER_DEPRECATED);
17+
1618
/**
1719
* Persists ClassMetadata instances in a cache.
1820
*
1921
* @author Bernhard Schussek <[email protected]>
22+
*
23+
* @deprecated since Symfony 4.4.
2024
*/
2125
interface CacheInterface
2226
{

Mapping/Cache/DoctrineCache.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
use Doctrine\Common\Cache\Cache;
1515
use Symfony\Component\Validator\Mapping\ClassMetadata;
1616

17+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4.', DoctrineCache::class), E_USER_DEPRECATED);
18+
1719
/**
1820
* Adapts a Doctrine cache to a CacheInterface.
1921
*
2022
* @author Florian Voutzinos <[email protected]>
23+
*
24+
* @deprecated since Symfony 4.4.
2125
*/
2226
final class DoctrineCache implements CacheInterface
2327
{

Mapping/Cache/Psr6Cache.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,14 @@
1414
use Psr\Cache\CacheItemPoolInterface;
1515
use Symfony\Component\Validator\Mapping\ClassMetadata;
1616

17+
@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.4.', Psr6Cache::class), E_USER_DEPRECATED);
18+
1719
/**
1820
* PSR-6 adapter.
1921
*
2022
* @author Kévin Dunglas <[email protected]>
23+
*
24+
* @deprecated since Symfony 4.4.
2125
*/
2226
class Psr6Cache implements CacheInterface
2327
{

Mapping/Factory/LazyLoadingMetadataFactory.php

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

1212
namespace Symfony\Component\Validator\Mapping\Factory;
1313

14+
use Psr\Cache\CacheItemPoolInterface;
1415
use Symfony\Component\Validator\Exception\NoSuchMetadataException;
1516
use Symfony\Component\Validator\Mapping\Cache\CacheInterface;
1617
use Symfony\Component\Validator\Mapping\ClassMetadata;
@@ -51,12 +52,17 @@ class LazyLoadingMetadataFactory implements MetadataFactoryInterface
5152
/**
5253
* Creates a new metadata factory.
5354
*
54-
* @param LoaderInterface|null $loader The loader for configuring new metadata
55-
* @param CacheInterface|null $cache The cache for persisting metadata
56-
* between multiple PHP requests
55+
* @param CacheItemPoolInterface|null $cache The cache for persisting metadata
56+
* between multiple PHP requests
5757
*/
58-
public function __construct(LoaderInterface $loader = null, CacheInterface $cache = null)
58+
public function __construct(LoaderInterface $loader = null, $cache = null)
5959
{
60+
if ($cache instanceof CacheInterface) {
61+
@trigger_error(sprintf('Passing a "%s" to "%s" is deprecated in Symfony 4.4 and will trigger a TypeError in 5.0. Please pass an implementation of "%s" instead.', \get_class($cache), __METHOD__, CacheItemPoolInterface::class), E_USER_DEPRECATED);
62+
} elseif (!$cache instanceof CacheItemPoolInterface && null !== $cache) {
63+
throw new \TypeError(sprintf('Expected an instance of %s, got %s.', CacheItemPoolInterface::class, \is_object($cache) ? \get_class($cache) : \gettype($cache)));
64+
}
65+
6066
$this->loader = $loader;
6167
$this->cache = $cache;
6268
}
@@ -92,11 +98,24 @@ public function getMetadataFor($value)
9298
throw new NoSuchMetadataException(sprintf('The class or interface "%s" does not exist.', $class));
9399
}
94100

95-
if (null !== $this->cache && false !== ($metadata = $this->cache->read($class))) {
96-
// Include constraints from the parent class
97-
$this->mergeConstraints($metadata);
101+
$cacheItem = null;
102+
if ($this->cache instanceof CacheInterface) {
103+
if ($metadata = $this->cache->read($class)) {
104+
// Include constraints from the parent class
105+
$this->mergeConstraints($metadata);
106+
107+
return $this->loadedClasses[$class] = $metadata;
108+
}
109+
} elseif (null !== $this->cache) {
110+
$cacheItem = $this->cache->getItem($this->escapeClassName($class));
111+
if ($cacheItem->isHit()) {
112+
$metadata = $cacheItem->get();
98113

99-
return $this->loadedClasses[$class] = $metadata;
114+
// Include constraints from the parent class
115+
$this->mergeConstraints($metadata);
116+
117+
return $this->loadedClasses[$class] = $metadata;
118+
}
100119
}
101120

102121
$metadata = new ClassMetadata($class);
@@ -105,8 +124,10 @@ public function getMetadataFor($value)
105124
$this->loader->loadClassMetadata($metadata);
106125
}
107126

108-
if (null !== $this->cache) {
127+
if ($this->cache instanceof CacheInterface) {
109128
$this->cache->write($metadata);
129+
} elseif (null !== $cacheItem) {
130+
$this->cache->save($cacheItem->set($metadata));
110131
}
111132

112133
// Include constraints from the parent class
@@ -162,4 +183,17 @@ public function hasMetadataFor($value)
162183

163184
return class_exists($class) || interface_exists($class, false);
164185
}
186+
187+
/**
188+
* Replaces backslashes by dots in a class name.
189+
*/
190+
private function escapeClassName(string $class): string
191+
{
192+
if (false !== strpos($class, '@')) {
193+
// anonymous class: replace all PSR6-reserved characters
194+
return str_replace(["\0", '\\', '/', '@', ':', '{', '}', '(', ')'], '.', $class);
195+
}
196+
197+
return str_replace('\\', '.', $class);
198+
}
165199
}

Tests/Mapping/Cache/DoctrineCacheTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
use Doctrine\Common\Cache\ArrayCache;
1515
use Symfony\Component\Validator\Mapping\Cache\DoctrineCache;
1616

17+
/**
18+
* @group legacy
19+
*/
1720
class DoctrineCacheTest extends AbstractCacheTest
1821
{
1922
protected function setUp(): void

Tests/Mapping/Cache/Psr6CacheTest.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
/**
1010
* @author Kévin Dunglas <[email protected]>
11+
*
12+
* @group legacy
1113
*/
1214
class Psr6CacheTest extends AbstractCacheTest
1315
{

Tests/Mapping/Factory/LazyLoadingMetadataFactoryTest.php

Lines changed: 39 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
namespace Symfony\Component\Validator\Tests\Mapping\Factory;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Psr\Cache\CacheItemPoolInterface;
16+
use Symfony\Component\Cache\Adapter\ArrayAdapter;
1517
use Symfony\Component\Validator\Constraints\Callback;
1618
use Symfony\Component\Validator\Mapping\ClassMetadata;
1719
use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory;
@@ -76,7 +78,36 @@ public function testMergeParentConstraints()
7678
$this->assertEquals($constraints, $metadata->getConstraints());
7779
}
7880

79-
public function testWriteMetadataToCache()
81+
public function testCachedMetadata()
82+
{
83+
$cache = new ArrayAdapter();
84+
$factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache);
85+
86+
$expectedConstraints = [
87+
new ConstraintA(['groups' => ['Default', 'EntityParent']]),
88+
new ConstraintA(['groups' => ['Default', 'EntityInterfaceA', 'EntityParent']]),
89+
];
90+
91+
$metadata = $factory->getMetadataFor(self::PARENT_CLASS);
92+
93+
$this->assertEquals(self::PARENT_CLASS, $metadata->getClassName());
94+
$this->assertEquals($expectedConstraints, $metadata->getConstraints());
95+
96+
$loader = $this->createMock(LoaderInterface::class);
97+
$loader->expects($this->never())->method('loadClassMetadata');
98+
99+
$factory = new LazyLoadingMetadataFactory($loader, $cache);
100+
101+
$metadata = $factory->getMetadataFor(self::PARENT_CLASS);
102+
103+
$this->assertEquals(self::PARENT_CLASS, $metadata->getClassName());
104+
$this->assertEquals($expectedConstraints, $metadata->getConstraints());
105+
}
106+
107+
/**
108+
* @group legacy
109+
*/
110+
public function testWriteMetadataToLegacyCache()
80111
{
81112
$cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
82113
$factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache);
@@ -115,7 +146,10 @@ public function testWriteMetadataToCache()
115146
$this->assertEquals($parentClassConstraints, $metadata->getConstraints());
116147
}
117148

118-
public function testReadMetadataFromCache()
149+
/**
150+
* @group legacy
151+
*/
152+
public function testReadMetadataFromLegacyCache()
119153
{
120154
$loader = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
121155
$cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
@@ -154,29 +188,19 @@ public function testNonClassNameStringValues()
154188
$this->expectException('Symfony\Component\Validator\Exception\NoSuchMetadataException');
155189
$testedValue = '[email protected]';
156190
$loader = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock();
157-
$cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
191+
$cache = $this->createMock(CacheItemPoolInterface::class);
158192
$factory = new LazyLoadingMetadataFactory($loader, $cache);
159193
$cache
160194
->expects($this->never())
161-
->method('read');
195+
->method('getItem');
162196
$factory->getMetadataFor($testedValue);
163197
}
164198

165199
public function testMetadataCacheWithRuntimeConstraint()
166200
{
167-
$cache = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock();
201+
$cache = new ArrayAdapter();
168202
$factory = new LazyLoadingMetadataFactory(new TestLoader(), $cache);
169203

170-
$cache
171-
->expects($this->any())
172-
->method('write')
173-
->willReturnCallback(function ($metadata) { serialize($metadata); })
174-
;
175-
176-
$cache->expects($this->any())
177-
->method('read')
178-
->willReturn(false);
179-
180204
$metadata = $factory->getMetadataFor(self::PARENT_CLASS);
181205
$metadata->addConstraint(new Callback(function () {}));
182206

Tests/ValidatorBuilderTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\Validator\Tests;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Psr\Cache\CacheItemPoolInterface;
1516
use Symfony\Component\Validator\Util\LegacyTranslatorProxy;
1617
use Symfony\Component\Validator\ValidatorBuilder;
1718
use Symfony\Component\Validator\ValidatorBuilderInterface;
@@ -85,6 +86,15 @@ public function testDisableAnnotationMapping()
8586
$this->assertSame($this->builder, $this->builder->disableAnnotationMapping());
8687
}
8788

89+
public function testSetMappingCache()
90+
{
91+
$this->assertSame($this->builder, $this->builder->setMappingCache($this->createMock(CacheItemPoolInterface::class)));
92+
}
93+
94+
/**
95+
* @group legacy
96+
* @expectedDeprecation Symfony\Component\Validator\ValidatorBuilder::setMetadataCache is deprecated since Symfony 4.4. Use setMappingCache() instead.
97+
*/
8898
public function testSetMetadataCache()
8999
{
90100
$this->assertSame($this->builder, $this->builder->setMetadataCache(

ValidatorBuilder.php

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Doctrine\Common\Annotations\CachedReader;
1616
use Doctrine\Common\Annotations\Reader;
1717
use Doctrine\Common\Cache\ArrayCache;
18+
use Psr\Cache\CacheItemPoolInterface;
1819
use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface;
1920
use Symfony\Component\Validator\Context\ExecutionContextFactory;
2021
use Symfony\Component\Validator\Exception\LogicException;
@@ -63,9 +64,9 @@ class ValidatorBuilder implements ValidatorBuilderInterface
6364
private $validatorFactory;
6465

6566
/**
66-
* @var CacheInterface|null
67+
* @var CacheItemPoolInterface|null
6768
*/
68-
private $metadataCache;
69+
private $mappingCache;
6970

7071
/**
7172
* @var TranslatorInterface|null
@@ -228,15 +229,37 @@ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
228229
}
229230

230231
/**
231-
* {@inheritdoc}
232+
* Sets the cache for caching class metadata.
233+
*
234+
* @return $this
235+
*
236+
* @deprecated since Symfony 4.4.
232237
*/
233238
public function setMetadataCache(CacheInterface $cache)
234239
{
240+
@trigger_error(sprintf('%s is deprecated since Symfony 4.4. Use setMappingCache() instead.', __METHOD__), E_USER_DEPRECATED);
241+
235242
if (null !== $this->metadataFactory) {
236243
throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
237244
}
238245

239-
$this->metadataCache = $cache;
246+
$this->mappingCache = $cache;
247+
248+
return $this;
249+
}
250+
251+
/**
252+
* Sets the cache for caching class metadata.
253+
*
254+
* @return $this
255+
*/
256+
public function setMappingCache(CacheItemPoolInterface $cache)
257+
{
258+
$this->mappingCache = $cache;
259+
260+
if (null !== $this->metadataFactory) {
261+
throw new ValidatorException('You cannot set a custom mapping cache after setting a custom metadata factory. Configure your metadata factory instead.');
262+
}
240263

241264
return $this;
242265
}
@@ -330,7 +353,7 @@ public function getValidator()
330353
$loader = $loaders[0];
331354
}
332355

333-
$metadataFactory = new LazyLoadingMetadataFactory($loader, $this->metadataCache);
356+
$metadataFactory = new LazyLoadingMetadataFactory($loader, $this->mappingCache);
334357
}
335358

336359
$validatorFactory = $this->validatorFactory ?: new ConstraintValidatorFactory();

0 commit comments

Comments
 (0)