<?php /* * © 2016 IRSTEA * Guillaume Perréal <guillaume.perreal@irstea.fr> * Tous droits réservés. */ namespace Irstea\PlantUmlBundle\DependencyInjection\Builder; use Irstea\PlantUmlBundle\Doctrine\EntityFinder; use Irstea\PlantUmlBundle\Finder\ClassFinder; use Irstea\PlantUmlBundle\Finder\FilteringFinder; use Irstea\PlantUmlBundle\Model\ClassVisitor; use Irstea\PlantUmlBundle\Model\Graph; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Reference; /** * Description of GraphDefinitionBuilder * * @author Guillaume Perréal <guillaume.perreal@irstea.fr> */ class GraphDefinitionBuilder { /** * @var ContainerBuilder */ private $container; /** * @var string */ private $baseId; /** * @var array */ private $config; /** * @var ClassFilterBuilder */ private $filterBuilder; /** * @var Reference */ private $entityManager; /** * * @var Definition */ private $definition = null; /** * * @param ContainerBuilder $container * @param string $baseId * @param array $config */ public function __construct(ContainerBuilder $container, $baseId, array $config, ClassFilterBuilder $filterBuilder) { $this->container = $container; $this->baseId = $baseId; $this->config = $config; $this->filterBuilder = $filterBuilder; $emId = $config['sources']['entity_manager']; $this->entityManager = new Reference("doctrine.orm.${emId}_entity_manager"); } /** * @return Definition */ public function build() { if (!$this->definition) { return $this->definition = $this->doBuild(); } return $this->definition; } /** * @return Definition */ protected function doBuild() { list($source, $sourceFilter) = $this->buildSources(); $layoutFilter = $this->filterBuilder->build($this->config['layout']) ?: $sourceFilter; $decorator = $this->buildFilteredDecorator(); $namespace = $this->buildNamespace(); $visitor = $this->setDefinition("visitor", ClassVisitor::class, $decorator, $layoutFilter, $namespace); return new Definition(Graph::class, [$visitor, $source]); } /** * @return Refernce[] */ protected function buildSources() { $finder = $this->buildFinder(); $filter = $this->filterBuilder->build($this->config['sources']); if ($filter) { $filtered = $this->setDefinition("finder", FilteringFinder::class, $finder, $filter); return [$filtered, $filter]; } return [$finder, null]; } /** * @return Reference */ protected function buildFinder() { $config = $this->config['sources']; switch($config['type']) { case 'entities': return $this->setDefinition("finder.entities", EntityFinder::class, $this->entityManager); case 'classes': return $this->setDefinition("finder.classes", ClassFinder::class, $config['directories']); } } /** * @return Reference */ protected function buildFilteredDecorator() { $decorator = $this->buildDecorator(); if (!$decorator) { return $decorator; } $filter = $this->filterBuilder->build($this->config['decoration']); if (!$filter) { return $decorator; } return $this->setDefinitionDecorator('decorator', 'irstea.plant_uml.decorator.filtered.template', $decorator, $filter); } /** * @return Reference */ protected function buildDecorator() { $config = $this->config['decoration']['decorators']; if (empty($config)) { return null; } if (count($config) === 1) { return $this->buildTypedDecorator($config[0]); } $decorators = []; foreach ($config as $type) { $decorators[] = $this->buildTypedDecorator($type); } return $this->setDefinitionDecorator( 'decorator.all', 'irstea.plant_uml.decorator.composite.template', $decorators ); } /** * @param string $type * @return Reference */ protected function buildTypedDecorator($type) { if (in_array($type, ['entity', 'associations', 'fields'])) { return $this->setDefinitionDecorator( "decorator.$type", "irstea.plant_uml.decorator.$type.template", $this->entityManager ); } return new Reference("irstea.plant_uml.decorator.$type"); } /** œ * @return Reference */ protected function buildNamespace() { $type = $this->config['layout']['namespaces']; if ($type === "entities") { return $this->setDefinitionDecorator( "namespace.$type", "irstea.plant_uml.namespaces.$type.template", $this->entityManager ); } return new Reference("irstea.plant_uml.namespaces.$type"); } /** * @param string $localId * @param string|Definition $classOrDef * @param array ...$arguments * @return Reference */ protected function setDefinition($localId, $classOrDef, ...$arguments) { if ($classOrDef instanceof Definition) { $definition = $classOrDef; } else { $definition = new Definition($classOrDef, $arguments); } $id = $this->globalId($localId); $this->container->setDefinition($id, $definition); return new Reference($id); } /** * @param string $localId * @param string $templateId * @param array ...$arguments * @return Reference */ protected function setDefinitionDecorator($localId, $templateId, ...$arguments) { $def = new DefinitionDecorator($templateId); $def->setArguments($arguments); return $this->setDefinition($localId, $def); } /** * @param string $localId * @return string */ protected function globalId($localId) { return "{$this->baseId}.$localId"; } }