Skip to content

Instantly share code, notes, and snippets.

@xphere
Created December 17, 2015 10:30
Show Gist options
  • Save xphere/7b6f80d26d9874aafd41 to your computer and use it in GitHub Desktop.
Save xphere/7b6f80d26d9874aafd41 to your computer and use it in GitHub Desktop.
Expands incomplete `jms_serializer.handler` tagged services
<?php
namespace Shopery\Bundle\ShoperyBundle\CompilerPass;
use Shopery\Bundle\ShoperyBundle\Serializer\Deserializer;
use Shopery\Bundle\ShoperyBundle\Serializer\Serializer;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;
/**
* Class SerializerCompilerPass
*
* @author Berny Cantos <[email protected]>
*/
class SerializerCompilerPass implements CompilerPassInterface
{
/**
* @var string
*/
private $tagName = 'jms_serializer.handler';
/**
* @var string[]
*/
private $formats;
/**
* @param string[] $formats
*/
public function __construct(array $formats)
{
$this->formats = $formats;
}
/**
* You can modify the container here before it is dumped to PHP code.
*
* @param ContainerBuilder $container
*
* @api
*/
public function process(ContainerBuilder $container)
{
$tagsByServiceId = $container->findTaggedServiceIds($this->tagName);
foreach ($tagsByServiceId as $serviceId => $tags) {
if (!$this->hasOnlyIncompleteTag($tags)) {
continue;
}
$definition = $container->getDefinition($serviceId);
$expandedTags = $this->expandTag($definition, $tags);
if (empty($expandedTags)) {
throw new Exception(sprintf('Service "%s" has an incomplete "%s" tag and should implement "%s" and/or "%s"', $serviceId, $this->tagName, Serializer::class, Deserializer::class));
}
$this->replaceTagsForName($definition, $expandedTags);
$container->addClassResource(new \ReflectionClass($definition->getClass()));
}
}
/**
* Check if is valid to fill incomplete serializer tags
*
* @param array $tags
*
* @return bool
*/
private function hasOnlyIncompleteTag(array $tags)
{
return count($tags) === 1 && isset($tags[0]['type']) && !isset($tags[0]['format']);
}
/**
* Expand an incomplete tag into multiple complete ones
*
* @param Definition $definition
* @param array $tags
*
* @return array
*/
private function expandTag(Definition $definition, array $tags)
{
$result = [];
foreach ($tags as $tag) {
$type = $tag['type'];
$class = $definition->getClass();
foreach ($this->formats as $format) {
if (is_a($class, Serializer::class, true)) {
$result[] = [
'type' => $type,
'format' => $format,
'direction' => 'serialization',
'method' => 'serialize'
];
}
if (is_a($class, Deserializer::class, true)) {
$result[] = [
'type' => $type,
'format' => $format,
'direction' => 'serialization',
'method' => 'serialize'
];
}
}
}
return $result;
}
/**
* Replace tags in a definition
*
* @param Definition $definition
* @param array $expandedTags
*/
private function replaceTagsForName(Definition $definition, array $expandedTags)
{
$definition->clearTag($this->tagName);
foreach ($expandedTags as $tag) {
$definition->addTag($this->tagName, $tag);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment