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

Extraction des classes Graph et Finder de GenerateCommand.

No related merge requests found
Showing with 314 additions and 100 deletions
+314 -100
......@@ -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']);
$graph = new Graph(
new ClassVisitor(
$this->buildDecorator($config['decoration']),
$this->buildFilter($config['layout']),
$this->buildNamespace($config['layout']['namespaces'])
),
$this->buildFinder($config['sources'])
);
$visitor = new ClassVisitor($decorator, $displayFilter, $namespace);
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
......@@ -340,9 +306,4 @@ class GenerateCommand extends ContainerAwareCommand
return $actualNamespaces;
}
}
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();
}
Supports Markdown
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