Skip to content

Commit

Permalink
Use aliases instead of replacing the service id of converters
Browse files Browse the repository at this point in the history
  • Loading branch information
guvra committed Feb 13, 2024
1 parent eb9f393 commit 2aa1eb6
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 16 deletions.
3 changes: 1 addition & 2 deletions app/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ services:
Smile\GdprDump\Config\Compiler\Processor\ProcessorInterface:
tags: ['config.compiler_processor']
Smile\GdprDump\Converter\ConverterInterface:
public: true # fetched with `$container->get` by the converter factory
shared: false
tags: ['converter']
Smile\GdprDump\Phar\Minify\MinifierInterface:
tags: ['compiler.minifier']

# Service id will be replaced by an alias during ConverterAliasPass
# The pass "ConverterAliasPass" will create an alias for each converter, to allow getting them by name
Smile\GdprDump\Converter\:
resource: '../../src/Converter'

Expand Down
39 changes: 25 additions & 14 deletions src/DependencyInjection/Compiler/ConverterAliasPass.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,52 @@
namespace Smile\GdprDump\DependencyInjection\Compiler;

use RuntimeException;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Definition;

class ConverterAliasPass implements CompilerPassInterface
{
public const ALIAS_PREFIX = 'converter.';

/**
* Replace the default service id of converters (class names) by an alias.
* Add an alias for data converters (e.g. "converter.randomizeText").
*
* Using an alias as the service id allows the converter factory to fetch a converter
* with the alias specified in the config file (e.g. "randomizeText").
* This allows the converter factory to create containers from the name
* specified in the config file (e.g. "randomizeText").
*
* @throws RuntimeException
*/
public function process(ContainerBuilder $container): void
{
foreach (array_keys($container->findTaggedServiceIds('converter')) as $serviceId) {
$definition = $container->getDefinition($serviceId);
$name = $this->getConverterAlias($definition);
$container->setDefinition($name, $definition);
$className = $definition->getClass();
if ($className === null) {
throw new RuntimeException(
sprintf('Failed to find the class name of the service "%s".', $serviceId)
);
}

$aliasName = $this->getAliasName($className);
if ($container->hasDefinition($aliasName)) {
throw new RuntimeException(
sprintf('The alias "%s" conflicts with an existing service.', $aliasName)
);
}

$alias = new Alias($className, true);
$container->setAlias($aliasName, $alias);
}
}

/**
* Get converter alias (class name with first letter in lower caps).
* Get a converter alias name (class name with first letter in lower caps).
*
* @throws RuntimeException
* The alias name contains a prefix to prevent any conflict with other services.
*/
private function getConverterAlias(Definition $definition): string
private function getAliasName(string $className): string
{
$className = $definition->getClass();
if ($className === null) {
throw new RuntimeException('Invalid service definition.');
}

$parts = explode('\\', $className);

// Add a prefix to prevent any conflict with other services
Expand Down

0 comments on commit 2aa1eb6

Please sign in to comment.