Forked from HYCAR-Hydro / airGR
Source project has a limited visibility.
GenerateCommand.php 9.39 KiB
<?php
/*
 * Copyright (C) 2015 IRSTEA
 * All rights reserved.
 */
namespace Irstea\PlantUmlBundle\Command;
use Doctrine\ORM\EntityManagerInterface;
use Irstea\PlantUmlBundle\Doctrine\AssociationDecorator;
use Irstea\PlantUmlBundle\Doctrine\DoctrineNamespace;
use Irstea\PlantUmlBundle\Doctrine\EntityDecorator;
use Irstea\PlantUmlBundle\Doctrine\EntityFinder;
use Irstea\PlantUmlBundle\Doctrine\FieldDecorator;
use Irstea\PlantUmlBundle\Finder\ClassFinder;
use Irstea\PlantUmlBundle\Finder\FilteringFinder;
use Irstea\PlantUmlBundle\Finder\FinderInterface;
use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
use Irstea\PlantUmlBundle\Model\ClassVisitor;
use Irstea\PlantUmlBundle\Model\Decorator\CompositeDecorator;
use Irstea\PlantUmlBundle\Model\Decorator\FilteringDecorator;
use Irstea\PlantUmlBundle\Model\Decorator\InheritanceDecorator;
use Irstea\PlantUmlBundle\Model\Decorator\InterfaceDecorator;
use Irstea\PlantUmlBundle\Model\Decorator\NullDecorator;
use Irstea\PlantUmlBundle\Model\Decorator\TraitDecorator;
use Irstea\PlantUmlBundle\Model\DecoratorInterface;
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 Irstea\PlantUmlBundle\Model\Graph;
use Irstea\PlantUmlBundle\Model\Namespace_\BundleNamespace;
use Irstea\PlantUmlBundle\Model\Namespace_\FlatNamespace;
use Irstea\PlantUmlBundle\Model\Namespace_\Php\RootNamespace;
use Irstea\PlantUmlBundle\Model\NamespaceInterface;
use Irstea\PlantUmlBundle\Writer\OutputWriter;
use ReflectionClass;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Security\Core\Exception\InvalidArgumentException;
use Symfony\Component\Security\Core\Exception\RuntimeException;
/**
 * Description of ImportAffiliationCommand
 * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
class GenerateCommand extends ContainerAwareCommand
    /**
     * @var string[]
    private $bundles;
    /**
     * @var KernelInterface
    private $kernel;
    /**
     * @var EntityManagerInterface
    private $entityManager;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
protected function configure() { $this ->setName('irstea:plantuml:generate') ->setDescription("Génère un graphe en PlantUML.") ->addArgument('graph', InputArgument::REQUIRED, 'Nom du graphe à générer'); } protected function initialize(InputInterface $input, OutputInterface $output) { parent::initialize($input, $output); // @todo: DI $this->bundles = $this->getContainer()->getParameter('kernel.bundles'); $this->kernel = $this->getContainer()->get('kernel'); $this->entityManager = $this->getContainer()->get('doctrine.orm.entity_manager'); } /** * * @param InputInterface $input * @param OutputInterface $output * * @SuppressWarnings(UnusedFormalParameter) */ protected function execute(InputInterface $input, OutputInterface $output) { $name = $input->getArgument('graph'); $graphs = $this->getContainer()->getParameter('irstea_plant_uml.graphs'); if (!isset($graphs[$name])) { throw new InvalidArgumentException("Le graphe '$name' n'est pas défini."); } $config = $graphs[$name]; $graph = new Graph( new ClassVisitor( $this->buildDecorator($config['decoration']), $this->buildFilter($config['layout']), $this->buildNamespace($config['layout']['namespaces']) ), $this->buildFinder($config['sources']) ); $graph->visitAll(); $writer = new OutputWriter($output); $graph->writeTo($writer); } /** * @param array $config * @return FinderInterface */ protected function buildFinder(array $config) { switch($config['type']) { case 'entities': $finder = $this->buildEntityFinder($config['entity_manager']); break; case 'classes': $finder = $this->buildClassFinder($config['directories']); break; } $filter = $this->buildFilter($config); if (!$filter) { return $finder; }
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
return new FilteringFinder($finder, $filter); } /** * @param array $directories * @return FinderInterface */ protected function buildClassFinder(array $directories) { return new ClassFinder($this->parseDirectories($directories)); } /** * @param string $managerName * @return FinderInterface */ protected function buildEntityFinder($managerName) { return new EntityFinder( $this->getContainer()->get('doctrine')->getManager($managerName) ); } /** * @param array $config * @return DecoratorInterface * @throws RuntimeException */ protected function buildDecorator(array $config) { if (empty($config['decorators'])) { return NullDecorator::instance(); } $decorators = []; foreach($config['decorators'] as $type) { $decorators[] = $this->buildTypedDecorator($type); } if (count($decorators) === 1) { $decorator = $decorators[0]; } else { $decorator = new CompositeDecorator($decorators); } $filter = $this->buildFilter($config); if ($filter) { $decorator = new FilteringDecorator($decorator, $filter); } return $decorator; } /** * @param type $type * @return DecoratorInterface */ protected function buildTypedDecorator($type) { switch($type) { case 'inheritance': return new InheritanceDecorator(); case 'interfaces': return new InterfaceDecorator(); case 'traits': return new TraitDecorator(); case 'entity': return new EntityDecorator($this->entityManager->getMetadataFactory()); case 'associations':
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
return new AssociationDecorator($this->entityManager->getMetadataFactory()); case 'fields': return new FieldDecorator($this->entityManager->getMetadataFactory()); } } /** * @param string $config * @return NamespaceInterface */ protected function buildNamespace($config) { switch($config) { case 'php': return new RootNamespace(); case 'flat': return new FlatNamespace(); case 'entities': return new DoctrineNamespace($this->entityManager->getConfiguration()->getEntityNamespaces()); case 'bundles': return new BundleNamespace($this->bundles); } } /** * @param array $config * @return ClassFilterInterface|null */ protected function buildFilter(array $config) { $filters = array_merge( isset($config['include']) ? $this->buildSubFilters($config['include'], false) : [], isset($config['exclude']) ? $this->buildSubFilters($config['exclude'], true) : [] ); switch(count($filters)) { case 0: return null; case 1: return $filters[0]; default: return new AllFilter($filters); } } /** * @param array $config * @param boolean $notFound * @return ClassFilterInterface|null */ protected function buildSubFilters(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
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
*/ 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; } }