Commit de9253f1 authored by Guillaume Perréal's avatar Guillaume Perréal

Refactorisation de la création des graphs.

parent 7e3455bc
This diff is collapsed.
......@@ -8,8 +8,18 @@
namespace Irstea\PlantUmlBundle\DependencyInjection;
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\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\DependencyInjection\Extension;
use Symfony\Component\DependencyInjection\Definition;
use Symfony\Component\DependencyInjection\DefinitionDecorator;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader;
use Symfony\Component\DependencyInjection\Reference;
/**
* Description of IrsteaPlantUmlExtension
......@@ -20,10 +30,192 @@ class IrsteaPlantUmlExtension extends Extension
{
public function load(array $configs, ContainerBuilder $container)
{
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
$loader->load('services.yml');
$configuration = new Configuration();
$config = $this->processConfiguration($configuration, $configs);
$container->setParameter('irstea_plant_uml.binaries', $config['binaries']);
$container->setParameter('irstea_plant_uml.graphs', $config['graphs']);
foreach($config['graphs'] as $key => $graph) {
$this->loadGraph($key, $graph, $container);
}
}
public function loadGraph($key, array $config, ContainerBuilder $container)
{
$id = "irstea_plant_uml.graph.$key";
$emName = $config['sources']['entity_manager'];
$em = new Reference("doctrine.orm.${emName}_entity_manager");
list($source, $defaultFilter) = $this->loadSources($id, $em, $config['sources'], $container);
$visitor = $this->addService(
$container,
"$id.visitor",
ClassVisitor::class,
[
$this->loadDecorator($id, $em, $config['decoration'], $defaultFilter, $container),
$this->loadFilter($id, $config['layout'], $container),
$this->loadNamespace($id, $em, $config['layout']['namespaces'], $container)
]
);
$container->setDefinition($id, new Definition(Graph::class, [$visitor, $source]))
->setPublic(true)
->setLazy(true);
}
/**
* @param string $id
* @param array $config
* @param ContainerBuilder $container
* @return Refernce[]
*/
protected function loadSources($id, Reference $em, array $config, ContainerBuilder $container)
{
$finderId = "$id.finder";
$filter = $this->loadFilter($finderId, $config, $container);
if ($filter) {
$inner = $this->loadFinder("$finderId.inner", $em, $config, $container);
$finder = $this->addService($container, $finderId, FilteringFinder::class, [$inner, $filter]);
} else {
$finder = $this->loadFinder($finderId, $em, $config, $container);
}
return [$finder, $filter];
}
/**
* @param string $id
* @param Reference $em
* @param array $config
* @param ContainerBuilder $container
* @return Reference
*/
protected function loadFinder($id, Reference $em, array $config, ContainerBuilder $container)
{
switch($config['type']) {
case 'entities':
return $this->addService($container, $id, EntityFinder::class, [$em]);
case 'classes':
return $this->addService($container, $id, ClassFinder::class, [$config['directories']]);
}
}
/**
*
* @param string $id
* @param Reference $em
* @param array $config
* @param Reference $defaultFilter
* @param ContainerBuilder $container
* @return Reference
*/
protected function loadDecorator($id, Reference $em, array $config, Reference $defaultFilter, ContainerBuilder $container)
{
if (empty($config['decorators'])) {
return new Reference('irstea.plant_uml.decorator.null');
}
$decoratorId = "$id.decorator";
$decorators = [];
foreach($config['decorators'] as $i => $type) {
$decorators[] = $this->loadTypedDecorator("$decoratorId.$i", $em, $type, $container);
}
if (count($decorators) === 1) {
$container->setAlias($decoratorId, "$decoratorId.0");
} else {
$container
->setDefinition($decoratorId, new DefinitionDecorator('irstea.plant_uml.decorator.composite.template'))
->replaceArgument(0, $decorators);
}
$filter = $this->loadFilter($decoratorId, $config, $container) ?: $defaultFilter;
if ($filter) {
$container
->setDefinition("$decoratorId.decorator", new DefinitionDecorator('irstea.plant_uml.decorator.filtered.template'))
->setDecoratedService($decoratorId, "inner_decorator")
->setArguments([new Reference("inner_decorator"), $filter]);
}
return new Reference($decoratorId);
}
/**
* @param string $id
* @param Reference $em
* @param string $type
* @param ContainerBuilder $container
* @return Reference
*/
protected function loadTypedDecorator($id, Reference $em, $type, ContainerBuilder $container)
{
if (in_array($type, ['entity', 'associations', 'fields'])) {
$container
->setDefinition($id, new DefinitionDecorator("irstea.plant_uml.decorator.$type.template"))
->replaceArgument(0, $em);
return new Reference($id);
}
return new Reference("irstea.plant_uml.decorator.$type");
}
/**
* @param string $id
* @param Reference $em
* @param string $type
* @param ContainerBuilder $container
* @return Reference
*/
protected function loadNamespace($id, Reference $em, $type, ContainerBuilder $container)
{
if ($type === "entities") {
$namespaceId = "$id.namespace";
$container
->setDefinition($namespaceId, new DefinitionDecorator('irstea.plant_uml.namespaces.entities.template'))
->replaceArgument(0, $em);
return new Reference($namespaceId);
}
return new Reference("irstea.plant_uml.namespaces.$type");
}
/**
* @param string $id
* @param array $config
* @param ContainerBuilder $container
* @return Reference
*/
protected function loadFilter($id, array $config, ContainerBuilder $container)
{
$filterId = "$id.filter";
$container
->setDefinition($filterId, new DefinitionDecorator("irstea.plant_uml.filter.template"))
->setArguments([
isset($config['include']) ? $config['include'] : [],
isset($config['exclude']) ? $config['exclude'] : [],
]);
return new Reference($filterId);
}
/**
*
* @param ContainerBuilder $container
* @param string $id
* @param Definition $def
* @return Reference
*/
protected function addService(ContainerBuilder $container, $id, $class, array $arguments = [])
{
$container
->setDefinition($id, new Definition($class, $arguments))
->setPublic(false);
return new Reference($id);
}
}
......@@ -8,6 +8,7 @@
namespace Irstea\PlantUmlBundle\Doctrine;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Mapping\ClassMetadataFactory;
use Irstea\PlantUmlBundle\Model\ClassVisitorInterface;
......@@ -27,9 +28,9 @@ abstract class AbstractDoctrineDecorator implements DecoratorInterface
*/
protected $metadataFactory;
public function __construct(ClassMetadataFactory $metadataFactory)
public function __construct(EntityManagerInterface $manager)
{
$this->metadataFactory = $metadataFactory;
$this->metadataFactory = $manager->getMetadataFactory();
}
public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor)
......
......@@ -17,8 +17,10 @@ class DoctrineNamespace extends \Irstea\PlantUmlBundle\Model\Namespace_\MappedNa
{
const SEPARATOR = '::';
public function __construct(array $entityNamespaces)
public function __construct(\Doctrine\ORM\EntityManagerInterface $em)
{
$entityNamespaces = $em->getConfiguration()->getEntityNamespaces();
$mapping = [];
foreach($entityNamespaces as $alias => $namespace) {
$mapping[$namespace.'\\'] = $alias.'::';
......
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Factory;
use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
use Irstea\PlantUmlBundle\Model\Filter\AcceptAllFilter;
use Irstea\PlantUmlBundle\Model\Filter\Composite\AllFilter;
use Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter;
use Irstea\PlantUmlBundle\Model\Filter\NamespaceFilter;
use Symfony\Component\HttpKernel\KernelInterface;
/**
* Description of FilterFactory
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class FilterFactory
{
/**
* @var KernelInterface
*/
private $kernel;
public function __construct(KernelInterface $kernel)
{
$this->kernel = $kernel;
}
/**
* @param array $include
* @param array $exclude
* @return ClassFilterInterface
*/
public function create($include = [], $exclude = [])
{
$filters = [];
if (!empty($include)) {
$filters[] = $this->createSubFilters($include, false);
}
if (!empty($exclude)) {
$filters[] = $this->createSubFilters($exclude, true);
}
$filters = array_merge($filters);
switch(count($filters)) {
case 0:
return AcceptAllFilter::instance();
case 1:
return $filters[0];
default:
return new AllFilter($filters);
}
}
protected function createSubFilters(array $config, $notFound)
{
$filters = [];
if (!empty($config['directories'])) {
$paths = $this->parseDirectories($config['directories']);
$filters[] = new DirectoryFilter($paths, $notFound);
}
if (!empty($config['namespaces'])) {
$namespaces = $this->parseNamespaces($config['namespaces']);
$filters[] = new NamespaceFilter($namespaces, $notFound);
}
return $filters;
}
/**
* @param array $paths
* @return array
*/
protected function parseDirectories(array $paths)
{
$actualPaths = [];
foreach($paths as $path) {
if (preg_match('/^@(\w+)(.*)$/', $path, $groups)) {
$bundle = $this->kernel->getBundle($groups[1]);
$path = $bundle->getPath() . $groups[2];
}
$actualPaths[] = realpath($path);
}
return $actualPaths;
}
/**
* @param array $paths
* @return array
*/
protected function parseNamespaces(array $namespaces)
{
$actualNamespaces = [];
foreach($namespaces as $namespace) {
if (preg_match('/^@(\w+)(.*)$/', $namespace, $groups)) {
$bundle = $this->kernel->getBundle($groups[1]);
$namespace = $bundle->getNamespace() . $groups[2];
}
$actualNamespaces[] = $namespace;
}
return $actualNamespaces;
}
}
parameters: ~
services:
irstea.plant_uml.filter.factory:
class: Irstea\PlantUmlBundle\Factory\FilterFactory
arguments: [@kernel]
irstea.plant_uml.filter.template:
class: Irstea\PlantUmlBundle\Model\ClassFilterInterface
abstract: true
factory: ["@irstea.plant_uml.filter.factory", create]
arguments: [[], []]
irstea.plant_uml.finder.classes.template:
class: Irstea\PlantUmlBundle\Finder\ClassFinder
abstract: true
arguments: [null]
irstea.plant_uml.finder.entities.template:
class: Irstea\PlantUmlBundle\Doctrine\EntityFinder
abstract: true
arguments: [null]
irstea.plant_uml.decorator.inheritance:
class: Irstea\PlantUmlBundle\Model\Decorator\InheritanceDecorator
irstea.plant_uml.decorator.interfaces:
class: Irstea\PlantUmlBundle\Model\Decorator\InterfaceDecorator
irstea.plant_uml.decorator.traits:
class: Irstea\PlantUmlBundle\Model\Decorator\TraitDecorator
irstea.plant_uml.decorator.attributes:
class: Irstea\PlantUmlBundle\Model\Decorator\AttributeDecorator
irstea.plant_uml.decorator.methods:
class: Irstea\PlantUmlBundle\Model\Decorator\MethodDecorator
irstea.plant_uml.decorator.null:
class: Irstea\PlantUmlBundle\Model\Decorator\NullDecorator
irstea.plant_uml.decorator.entity.template:
class: Irstea\PlantUmlBundle\Doctrine\EntityDecorator
abstract: true
arguments: [null]
irstea.plant_uml.decorator.associations.template:
class: Irstea\PlantUmlBundle\Doctrine\AssociationDecorator
abstract: true
arguments: [null]
irstea.plant_uml.decorator.fields.template:
class: Irstea\PlantUmlBundle\Doctrine\FieldDecorator
abstract: true
arguments: [null]
irstea.plant_uml.decorator.filtered.template:
class: Irstea\PlantUmlBundle\Model\Decorator\FilteringDecorator
abstract: true
public: false
irstea.plant_uml.decorator.composite.template:
class: Irstea\PlantUmlBundle\Model\Decorator\CompositeDecorator
abstract: true
public: false
arguments: [[]]
irstea.plant_uml.namespaces.php:
class: Irstea\PlantUmlBundle\Model\Namespace_\Php\RootNamespace
irstea.plant_uml.namespaces.php:
class: Irstea\PlantUmlBundle\Model\Namespace_\FlatNamespace
irstea.plant_uml.namespaces.bundles:
class: Irstea\PlantUmlBundle\Model\Namespace_\BundleNamespace
arguments: ["%kernel.bundles%"]
irstea.plant_uml.namespaces.entities.template:
class: Irstea\PlantUmlBundle\Doctrine\DoctrineNamespace
abstract: true
arguments: [null]
......@@ -15,7 +15,7 @@
{ "type": "composer", "url": "http://istest.lyon.cemagref.fr/satis" }
],
"require": {
"php": ">=5.4",
"php": ">=5.6",
"symfony/framework-bundle": "^2.6",
"doctrine/doctrine-bundle": "^1.6"
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment