Commit 1c471ae3 authored by Guillaume Perréal's avatar Guillaume Perréal
Browse files

Extraction des classes Graph et Finder de GenerateCommand.

parent bc58e9ca
......@@ -10,6 +10,10 @@ 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\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;
......@@ -23,6 +27,7 @@ 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;
......@@ -98,102 +103,62 @@ class GenerateCommand extends ContainerAwareCommand
$config = $graphs[$name];
$classes = $this->findClasses($config['sources']);
if (empty($classes)) {
$output->writeln("Nothing to analyze.");
return 0;
}
$namespace = $this->buildNamespace($config['layout']['namespaces']);
$displayFilter = $this->buildFilter($config['layout']);
$decorator = $this->buildDecorator($config['decoration']);
$visitor = new ClassVisitor($decorator, $displayFilter, $namespace);
$graph = new Graph(
new ClassVisitor(
$this->buildDecorator($config['decoration']),
$this->buildFilter($config['layout']),
$this->buildNamespace($config['layout']['namespaces'])
),
$this->buildFinder($config['sources'])
);
foreach($classes as $class) {
$visitor->visitClass($class);
}
$graph->visitAll();
$writer = new OutputWriter($output);
$writer->write("@startuml\n");
$visitor->outputTo($writer);
$writer->write("@enduml\n");
$graph->outputTo($writer);
}
/**
* @param ReflectionClass[]
* @param array $config
* @return FinderInterface
*/
protected function findClasses(array $config)
protected function buildFinder(array $config)
{
switch($config['type']) {
case 'entities':
$classes = $this->findEntities($config['entity_manager']);
$finder = $this->buildEntityFinder($config['entity_manager']);
break;
case 'classes':
$classes = $this->findClassesInDirectories($config['directories']);
$finder = $this->buildClassFinder($config['directories']);
break;
}
$filter = $this->buildFilter($config);
if ($filter) {
return array_filter($classes, [$filter, 'accept']);
if (!$filter) {
return $finder;
}
return $classes;
return new FilteringFinder($finder, $filter);
}
/**
* @return ReflectionClass[]
* @param array $directories
* @return FinderInterface
*/
protected function findEntities($managerName)
protected function buildClassFinder(array $directories)
{
$doctrine = $this->getContainer()->get('doctrine');
$this->entityManager = $doctrine->getManager($managerName);
$classes = [];
foreach($this->entityManager->getMetadataFactory()->getAllMetadata() as $metadata) {
$classes[$metadata->getName()] = $metadata->getReflectionClass();
}
return $classes;
return new ClassFinder($this->parseDirectories($directories));
}
/**
*
* @return ReflectionClass[]
* @param string $managerName
* @return FinderInterface
*/
protected function findClassesInDirectories($directories)
protected function buildEntityFinder($managerName)
{
$paths = $this->parseDirectories($directories);
$files = Finder::create()
->in($paths)
->files()
->name('*.php')
->getIterator();
foreach($files as $file)
{
/* @var $file SplFileInfo */
$path = $file->getPathname();
try {
irstea_plantmul_include($path);
} catch(Exception $ex) {
printf("%s: %s (%s)\n", $path, get_class($ex), $ex->getMessage());
}
}
$filter = new DirectoryFilter($paths);
$classes = [];
foreach(get_declared_classes() as $className) {
$class = new ReflectionClass($className);
if ($filter->accept($class)) {
$classes[$className] = $class;
}
}
return $classes;
return new EntityFinder(
$this->getContainer()->get('doctrine')->getManager($managerName)
);
}
/**
......@@ -203,32 +168,13 @@ class GenerateCommand extends ContainerAwareCommand
*/
protected function buildDecorator(array $config)
{
$decorators = [];
foreach($config['decorators'] as $decorator) {
switch($decorator) {
case 'inheritance':
$decorators[] = new InheritanceDecorator();
break;
case 'interfaces':
$decorators[] = new InterfaceDecorator();
break;
case 'traits':
$decorators[] = new TraitDecorator();
break;
case 'entity':
$decorators[] = new EntityDecorator($this->entityManager->getMetadataFactory());
break;
case 'associations':
$decorators[] = new AssociationDecorator($this->entityManager->getMetadataFactory());
break;
/*default:
throw new RuntimeException("Decorator '$decorator' not yet implemented");*/
}
if (empty($config['decorators'])) {
return NullDecorator::instance();
}
if (empty($decorators)) {
return NullDecorator::instance();
$decorators = [];
foreach($config['decorators'] as $type) {
$decorators[] = $this->buildTypedDecorator($type);
}
if (count($decorators) === 1) {
......@@ -245,6 +191,26 @@ class GenerateCommand extends ContainerAwareCommand
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':
return new AssociationDecorator($this->entityManager->getMetadataFactory());
}
}
/**
* @param string $config
* @return NamespaceInterface
......@@ -341,8 +307,3 @@ class GenerateCommand extends ContainerAwareCommand
}
}
\ No newline at end of file
function irstea_plantmul_include($filepath)
{
@include_once($filepath);
}
\ No newline at end of file
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Doctrine;
use ArrayIterator;
use Doctrine\ORM\EntityManager;
use Irstea\PlantUmlBundle\Finder\FinderInterface;
/**
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class EntityFinder implements FinderInterface
{
/**
* @var EntityManager
*/
private $entityManager;
public function __construct(EntityManager $entityManager)
{
$this->entityManager = $entityManager;
}
public function getIterator()
{
$classes = [];
foreach($this->entityManager->getMetadataFactory()->getAllMetadata() as $metadata) {
$classes[$metadata->getName()] = $metadata->getReflectionClass();
}
return new ArrayIterator($classes);
}
}
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Finder;
use ArrayIterator;
use Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter;
use ReflectionClass;
use Symfony\Component\Config\Definition\Exception\Exception;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Finder\SplFileInfo;
/**
* Description of ClassFinder
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class ClassFinder implements FinderInterface
{
/**
* @var string[]
*/
private $directories;
/**
*
* @var \ReflectionClass
*/
private $classes = null;
public function __construct($directories)
{
$this->directories = $directories;
}
private function initialize()
{
$files = Finder::create()
->in($this->directories)
->files()
->name('*.php')
->getIterator();
foreach($files as $file)
{
/* @var $file SplFileInfo */
$path = $file->getPathname();
try {
irstea_plantmul_include($path);
} catch(Exception $ex) {
printf("%s: %s (%s)\n", $path, get_class($ex), $ex->getMessage());
}
}
$filter = new DirectoryFilter($this->directories);
$this->classes = [];
foreach(get_declared_classes() as $className) {
$class = new ReflectionClass($className);
if ($filter->accept($class)) {
$this->classes[$className] = $class;
}
}
}
public function getIterator()
{
if ($this->classes === null) {
$this->initialize();
}
return new ArrayIterator($this->classes);
}
}
function irstea_plantmul_include($filepath)
{
@include_once($filepath);
}
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Finder;
use CallbackFilterIterator;
use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
/**
* Description of FilteringFinder
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class FilteringFinder implements FinderInterface
{
/**
* @var FinderInterface
*/
private $inner;
/**
* @var ClassFilterInterface
*/
private $filter;
public function __construct(FinderInterface $inner, ClassFilterInterface $filter)
{
$this->inner = $inner;
$this->filter = $filter;
}
public function getIterator()
{
return new CallbackFilterIterator($this->inner->getIterator(), [$this->filter, 'accept']);
}
}
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Finder;
/**
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
interface FinderInterface extends \Traversable, \IteratorAggregate
{
}
......@@ -23,7 +23,7 @@ use ReflectionClass;
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class ClassVisitor implements ClassVisitorInterface, WritableInterface
class ClassVisitor implements ClassVisitorInterface
{
/**
* @var NamespaceInterface
......
......@@ -8,13 +8,13 @@
namespace Irstea\PlantUmlBundle\Model;
use ReflectionClass;
use Irstea\PlantUmlBundle\Writer\WritableInterface;
/**
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
interface ClassVisitorInterface
interface ClassVisitorInterface extends WritableInterface
{
/**
* @param ReflectionClass|string
......
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Model;
use Irstea\PlantUmlBundle\Finder\FinderInterface;
use Irstea\PlantUmlBundle\Writer\WriterInterface;
/**
* Description of Graph
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class Graph implements GraphInterface
{
/**
* @var ClassVisitorInterface
*/
private $visitor;
/**
* @var FinderInterface
*/
private $finder;
public function __construct(ClassVisitorInterface $visitor, FinderInterface $finder)
{
$this->visitor = $visitor;
$this->finder = $finder;
}
public function visitAll()
{
foreach($this->finder->getIterator() as $class) {
$this->visitor->visitClass($class);
}
}
public function outputTo(WriterInterface $writer)
{
$writer->write("@startuml@\n");
$this->visitor->outputTo($writer);
$writer->write("@enduml@\n");
return $this;
}
}
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace Irstea\PlantUmlBundle\Model;
use Irstea\PlantUmlBundle\Writer\WritableInterface;
/**
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
interface GraphInterface extends WritableInterface
{
/**
* @return void
*/
public function visitAll();
}
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