-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[Serializer] Add PSR-6 adapter #17446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Serializer\Mapping\Factory; | ||
|
||
use Psr\Cache\CacheItemPoolInterface; | ||
|
||
/** | ||
* Caches metadata using a PSR-6 implementation. | ||
* | ||
* @author Kévin Dunglas <dunglas@gmail.com> | ||
*/ | ||
class CacheClassMetadataFactory implements ClassMetadataFactoryInterface | ||
{ | ||
use ClassResolverTrait; | ||
|
||
/** | ||
* @var ClassMetadataFactoryInterface | ||
*/ | ||
private $decorated; | ||
|
||
/** | ||
* @var CacheItemPoolInterface | ||
*/ | ||
private $cacheItemPool; | ||
|
||
public function __construct(ClassMetadataFactoryInterface $decorated, CacheItemPoolInterface $cacheItemPool) | ||
{ | ||
$this->decorated = $decorated; | ||
$this->cacheItemPool = $cacheItemPool; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function getMetadataFor($value) | ||
{ | ||
$class = $this->getClass($value); | ||
// Key cannot contain backslashes according to PSR-6 | ||
$key = strtr($class, '\\', '_'); | ||
|
||
$item = $this->cacheItemPool->getItem($key); | ||
if ($item->isHit()) { | ||
return $item->get(); | ||
} | ||
|
||
$metadata = $this->decorated->getMetadataFor($value); | ||
$this->cacheItemPool->save($item->set($metadata)); | ||
|
||
return $metadata; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function hasMetadataFor($value) | ||
{ | ||
return $this->decorated->hasMetadataFor($value); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Serializer\Mapping\Factory; | ||
|
||
use Symfony\Component\Serializer\Exception\InvalidArgumentException; | ||
|
||
/** | ||
* Resolves a class name. | ||
* | ||
* @author Kévin Dunglas <dunglas@gmail.com> | ||
*/ | ||
trait ClassResolverTrait | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What about making this trait internal? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It can be useful for a userland MetadataFactory (like a Doctrine Cache one) what do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case they could use the |
||
{ | ||
/** | ||
* Gets a class name for a given class or instance. | ||
* | ||
* @param mixed $value | ||
* | ||
* @return string | ||
* | ||
* @throws InvalidArgumentException If the class does not exists | ||
*/ | ||
private function getClass($value) | ||
{ | ||
if (is_string($value)) { | ||
if (!class_exists($value) && !interface_exists($value)) { | ||
throw new InvalidArgumentException(sprintf('The class or interface "%s" does not exist.', $value)); | ||
} | ||
|
||
return ltrim($value, '\\'); | ||
} | ||
|
||
if (!is_object($value)) { | ||
throw new InvalidArgumentException(sprintf('Cannot create metadata for non-objects. Got: "%s"', gettype($value))); | ||
} | ||
|
||
return get_class($value); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<?php | ||
|
||
/* | ||
* This file is part of the Symfony package. | ||
* | ||
* (c) Fabien Potencier <fabien@symfony.com> | ||
* | ||
* For the full copyright and license information, please view the LICENSE | ||
* file that was distributed with this source code. | ||
*/ | ||
|
||
namespace Symfony\Component\Serializer\Tests\Mapping\Factory; | ||
|
||
use Symfony\Component\Cache\Adapter\ArrayAdapter; | ||
use Symfony\Component\Serializer\Mapping\ClassMetadata; | ||
use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; | ||
|
||
/** | ||
* @author Kévin Dunglas <dunglas@gmail.com> | ||
*/ | ||
class CacheMetadataFactoryTest extends \PHPUnit_Framework_TestCase | ||
{ | ||
public function testGetMetadataFor() | ||
{ | ||
$metadata = new ClassMetadata('Symfony\Component\Serializer\Tests\Fixtures\Dummy'); | ||
|
||
$decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
$decorated | ||
->expects($this->once()) | ||
->method('getMetadataFor') | ||
->will($this->returnValue($metadata)) | ||
; | ||
|
||
$factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); | ||
|
||
$this->assertEquals($metadata, $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); | ||
// The second call should retrieve the value from the cache | ||
$this->assertEquals($metadata, $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); | ||
} | ||
|
||
public function testHasMetadataFor() | ||
{ | ||
$decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); | ||
$decorated | ->expects($this->once()) | |
->method('hasMetadataFor') | ||
->will($this->returnValue(true)) | ||
; | ||
|
||
$factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); | ||
|
||
$this->assertTrue($factory->hasMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\Dummy')); | ||
} | ||
|
||
/** | ||
* @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException | ||
*/ | ||
public function testInvalidClassThrowsException() | ||
{ | ||
$decorated = $this->getMock('Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface'); | ||
$factory = new CacheClassMetadataFactory($decorated, new ArrayAdapter()); | ||
|
||
$factory->getMetadataFor('Not\Exist'); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,16 +23,18 @@ | |
"symfony/config": "~2.8|~3.0", | ||
"symfony/property-access": "~2.8|~3.0", | ||
"symfony/http-foundation": "~2.8|~3.0", | ||
"symfony/cache": "~3.1", | ||
"doctrine/annotations": "~1.0", | ||
"doctrine/cache": "~1.0" | ||
}, | ||
"suggest": { | ||
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", | ||
"doctrine/cache": "For using the default cached annotation reader and metadata cache.", | ||
"symfony/cache": "For using the metadata cache.", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On the validator PR, you added |
||
"symfony/yaml": "For using the default YAML mapping loader.", | ||
"symfony/config": "For using the XML mapping loader.", | ||
"symfony/property-access": "For using the ObjectNormalizer.", | ||
"symfony/http-foundation": "To use the DataUriNormalizer." | ||
"symfony/http-foundation": "To use the DataUriNormalizer.", | ||
"doctrine/annotations": "For using the annotation mapping. You will also need doctrine/cache.", | ||
"doctrine/cache": "For using the default cached annotation reader and metadata cache." | ||
}, | ||
"autoload": { | ||
"psr-4": { "Symfony\\Component\\Serializer\\": "" }, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems that you are as tired as I am 😉 The second FQN must be the new one (and BTW you can use sprintf with
__CLASS__
/ ::class)