<?php
/**
* Compiler Pass
*
* @author Vincent van Waasbergen <v.vanwaasbergen@visualmedia.nl>
*/
namespace VisualMedia\LisaBundle\Component;
use Closure;
use ReflectionClass;
use Symfony\Component\DependencyInjection\Alias;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Finder\Finder;
/**
* Compiler Pass
*/
abstract class CompilerPass implements CompilerPassInterface
{
/**
* {@inheritdoc}
*/
public function process(ContainerBuilder $container): void
{
$projectDir = $container->getParameter('kernel.project_dir');
$bundles = $container->getParameter(Bundle::PARAMETER_BUNDLES);
$fs = new Filesystem();
foreach ($bundles as $name=>$namespace) {
$reflection = new ReflectionClass("{$namespace}\\{$name}");
$bundleDir = $reflection->getFileName();
$bundleDir = explode('/', $bundleDir);
$bundleDir = $bundleDir[count($bundleDir) - 5];
$bundleDir = strtolower(preg_replace('/\B([A-Z])/', '_$1', $bundleDir));
$namespaceDir = str_replace('\\', '/', $namespace);
$bundlePath = sprintf('%s/vendor/visualmedia/%s/src/%s/', $projectDir, $bundleDir, $namespaceDir);
$this->processBundle($container, $namespace, $bundlePath);
}
$bundlePath = sprintf('%s/src/', $projectDir);
$this->processBundle($container, 'App', $bundlePath);
}
/**
* @param string $namespace
* @param string $bundlePath
* @return void
*/
protected function processBundle(ContainerBuilder $container, $namespace, $bundlePath): void
{
// ...
}
/**
* @param ContainerBuilder $container
* @param string $namespace
* @param string $bundlePath
* @param string $component
* @param Closure $callback
* @return void
*/
protected function loadComponents(ContainerBuilder $container, $namespace, $bundlePath, $component, $callback, callable $aliasBuilder = null): void
{
$fs = new Filesystem();
if ($fs->exists($path = $bundlePath . $component)) {
$finder = new Finder();
foreach ($finder->files()->in($path)->depth('== 0') as $file) {
$class = $this->getClass($namespace, $component, $file->getFilename());
$definition = $container->hasDefinition($class) ? $container->getDefinition($class) : new Definition($class);
$definition->setPublic(true);
$definition->setAutowired(true);
if (defined(sprintf('%s::SERVICE_ALIAS_ID', $class))) {
$container->setAlias($class::SERVICE_ALIAS_ID, $class);
$alias = $container->getAlias($class::SERVICE_ALIAS_ID);
$alias->setPublic(true);
}
$callback($definition);
$container->setDefinition($class, $definition);
if($aliasBuilder !== null) {
if(null !== ($alias = $aliasBuilder($definition, $class) ?: null)) {
$container->setAlias($alias, $class);
$aliasFromContainer = $container->getAlias($alias);
$aliasFromContainer->setPublic($alias instanceof Alias ? $alias->isPublic() : true);
}
}
}
}
}
/**
* @param ContainerBuilder $container
* @param string $tag
* @return array
*/
protected function getServicesByTag(ContainerBuilder $container, $tag): array
{
$services = array();
foreach ($container->findTaggedServiceIds($tag) as $serviceName=>$tags) {
$definition = $container->getDefinition($serviceName);
$services[$definition->getClass()] = new Reference($definition->getClass());
}
return $services;
}
/**
* @param ContainerBuilder $container
* @param string $tag
* @param string $interfaceClass
* @return array
*/
protected function getServicesByTagAndInterface(ContainerBuilder $container, $tag, $interfaceClass): array
{
$services = array();
foreach ($container->findTaggedServiceIds($tag) as $serviceName=>$tags) {
$definition = $container->getDefinition($serviceName);
$reflection = new ReflectionClass($definition->getClass());
if ($reflection->implementsInterface($interfaceClass)) {
$services[$definition->getClass()] = new Reference($definition->getClass());
}
}
return $services;
}
/**
* @param string $namespace
* @param string $component
* @param string $filename
* @return string
*/
protected function getClass($namespace, $component, $filename): string
{
return str_replace('/', '\\', $namespace . '\\' . $component . '\\' . str_replace('.php', '', $filename));
}
/**
* @param string $filename
* @return string
*/
protected function getKey($filename): string
{
$splitted = preg_split('/(?=[A-Z])/', $filename);
array_shift($splitted);
return strtolower(str_replace('.php', '', implode('_', $splitted)));
}
}