Skip to content

Commit 6df2791

Browse files
Merge branch '4.4'
* 4.4: [Validator] Deprecated CacheInterface in favor of PSR-6. Fix wrong namespace [Mailer] Fix typo [Mailer] Fix an error message maintain sender/recipient name in SMTP envelopes [Mailer] Improve an exception when trying to send a RawMessage without an Envelope Fix #32148 TransportException was not thrown Add ErrorController to preview and render errors
2 parents 9f83a3c + c0293c0 commit 6df2791

10 files changed

+112
-35
lines changed

CHANGELOG.md

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

4143
4.3.0
4244
-----

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: 3 additions & 4 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\ValidatorBuilder;
1617

1718
class ValidatorBuilderTest extends TestCase
@@ -83,11 +84,9 @@ public function testDisableAnnotationMapping()
8384
$this->assertSame($this->builder, $this->builder->disableAnnotationMapping());
8485
}
8586

86-
public function testSetMetadataCache()
87+
public function testSetMappingCache()
8788
{
88-
$this->assertSame($this->builder, $this->builder->setMetadataCache(
89-
$this->getMockBuilder('Symfony\Component\Validator\Mapping\Cache\CacheInterface')->getMock())
90-
);
89+
$this->assertSame($this->builder, $this->builder->setMappingCache($this->createMock(CacheItemPoolInterface::class)));
9190
}
9291

9392
public function testSetConstraintValidatorFactory()

ValidatorBuilder.php

Lines changed: 8 additions & 7 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\Validator\Context\ExecutionContextFactory;
1920
use Symfony\Component\Validator\Exception\LogicException;
2021
use Symfony\Component\Validator\Exception\ValidatorException;
@@ -60,9 +61,9 @@ class ValidatorBuilder
6061
private $validatorFactory;
6162

6263
/**
63-
* @var CacheInterface|null
64+
* @var CacheItemPoolInterface|null
6465
*/
65-
private $metadataCache;
66+
private $mappingCache;
6667

6768
/**
6869
* @var TranslatorInterface|null
@@ -261,14 +262,14 @@ public function setMetadataFactory(MetadataFactoryInterface $metadataFactory)
261262
*
262263
* @return $this
263264
*/
264-
public function setMetadataCache(CacheInterface $cache)
265+
public function setMappingCache(CacheItemPoolInterface $cache)
265266
{
267+
$this->mappingCache = $cache;
268+
266269
if (null !== $this->metadataFactory) {
267-
throw new ValidatorException('You cannot set a custom metadata cache after setting a custom metadata factory. Configure your metadata factory instead.');
270+
throw new ValidatorException('You cannot set a custom mapping cache after setting a custom metadata factory. Configure your metadata factory instead.');
268271
}
269272

270-
$this->metadataCache = $cache;
271-
272273
return $this;
273274
}
274275

@@ -367,7 +368,7 @@ public function getValidator()
367368
$loader = $loaders[0];
368369
}
369370

370-
$metadataFactory = new LazyLoadingMetadataFactory($loader, $this->metadataCache);
371+
$metadataFactory = new LazyLoadingMetadataFactory($loader, $this->mappingCache);
371372
}
372373

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

0 commit comments

Comments
 (0)