diff --git a/Command/GenerateCommand.php b/Command/GenerateCommand.php index b17b5f0c6ea5cda817aed75237e4f4734e5bfc96..dbc497a21c8e177682876c2fc48630643af1b2a5 100644 --- a/Command/GenerateCommand.php +++ b/Command/GenerateCommand.php @@ -15,7 +15,9 @@ 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; @@ -208,6 +210,12 @@ class GenerateCommand extends ContainerAwareCommand 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; diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index e112708c847a7dc6161ff129832764fcbe9d9537..2c8e19be3c945c718807bc66224735e37b65ed5e 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -85,9 +85,9 @@ class Configuration implements ConfigurationInterface ->addDefaultsIfNotSet() ->children() ->arrayNode('decorators') - ->defaultValue(['inheritance', 'entity', 'associations', 'properties', 'methods']) + ->defaultValue(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods']) ->prototype('enum') - ->values(['inheritance', 'entity', 'associations', 'properties', 'methods']) + ->values(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods']) ->end() ->end() ->append($this->buildFilterNode('include')) diff --git a/Model/Decorator/AbstractRelationDecorator.php b/Model/Decorator/AbstractRelationDecorator.php new file mode 100644 index 0000000000000000000000000000000000000000..d91cd5788283348fb84c4f25a8e51aabfe41078f --- /dev/null +++ b/Model/Decorator/AbstractRelationDecorator.php @@ -0,0 +1,44 @@ +<?php + +/* + * © 2016 IRSTEA + * Guillaume Perréal <guillaume.perreal@irstea.fr> + * Tous droits réservés. + */ + +namespace Irstea\PlantUmlBundle\Model\Decorator; + +use Irstea\PlantUmlBundle\Model\ArrowInterface; +use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\DecoratorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; + +/** + * Description of InheritanceDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +abstract class AbstractRelationDecorator implements DecoratorInterface +{ + /** + * @param NodeInterface $source + * @param array $classNames + * @param ClassVisitorInterface $visitor + */ + protected function visitRelations(NodeInterface $source, array $classNames, ClassVisitorInterface $visitor) + { + foreach ($classNames as $className) { + $target = $visitor->visitClass($className); + if ($target) { + $source->addArrow($this->buildRelation($source, $target)); + } + } + } + + /** + * @param NodeInterface $source + * @param NodeInterface $target + * @return ArrowInterface + */ + abstract protected function buildRelation(NodeInterface $source, NodeInterface $target); +} diff --git a/Model/Decorator/InheritanceDecorator.php b/Model/Decorator/InheritanceDecorator.php index ff901f04a717f7c8281e3dd04028c5ab90dab4ae..0d5ef51424490930e722b2b57b27a639d25d5d06 100644 --- a/Model/Decorator/InheritanceDecorator.php +++ b/Model/Decorator/InheritanceDecorator.php @@ -8,6 +8,7 @@ namespace Irstea\PlantUmlBundle\Model\Decorator; +use Irstea\PlantUmlBundle\Model\Arrow\ExtendsClass; use Irstea\PlantUmlBundle\Model\ClassVisitor; use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; use Irstea\PlantUmlBundle\Model\DecoratorInterface; @@ -19,45 +20,18 @@ use ReflectionClass; * * @author Guillaume Perréal <guillaume.perreal@irstea.fr> */ -class InheritanceDecorator implements DecoratorInterface +class InheritanceDecorator extends AbstractRelationDecorator { public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) { $parent = $class->getParentClass(); - $traits = $class->getTraitNames(); - $interfaces = $class->getInterfaceNames(); - - $indirectInterfaces = array_filter( - array_map( - function ($i) { return $i->getInterfaceNames(); }, - $class->getInterfaces() - ) - ); - - if (!empty($indirectInterfaces)) { - $indirectInterfaces = call_user_func_array('array_merge', $indirectInterfaces); - $interfaces = array_diff($interfaces, $indirectInterfaces); - } - if ($parent) { - $traits = array_diff($traits, $parent->getTraitNames()); - $interfaces = array_diff($interfaces, $parent->getInterfaceNames()); - $this->visitRelations($node, [$parent->getName()], 'Irstea\PlantUmlBundle\Model\Arrow\ExtendsClass', $visitor); + $this->visitRelations($node, [$parent->getName()], $visitor); } - - $this->visitRelations($node, $interfaces, 'Irstea\PlantUmlBundle\Model\Arrow\ImplementsInterface', $visitor); - $this->visitRelations($node, $traits, 'Irstea\PlantUmlBundle\Model\Arrow\UsesTrait', $visitor); - - return $this; } - protected function visitRelations(NodeInterface $source, array $classNames, $relationClass, ClassVisitorInterface $visitor) + protected function buildRelation(NodeInterface $source, NodeInterface $target) { - foreach ($classNames as $className) { - $target = $visitor->visitClass($className); - if ($target) { - $source->addArrow(new $relationClass($source, $target)); - } - } + return new ExtendsClass($source, $target); } } diff --git a/Model/Decorator/InterfaceDecorator.php b/Model/Decorator/InterfaceDecorator.php new file mode 100644 index 0000000000000000000000000000000000000000..a2e19a6f1de44c0079cdb3f5660133a1c87cac6e --- /dev/null +++ b/Model/Decorator/InterfaceDecorator.php @@ -0,0 +1,54 @@ +<?php + +/* + * © 2016 IRSTEA + * Guillaume Perréal <guillaume.perreal@irstea.fr> + * Tous droits réservés. + */ + +namespace Irstea\PlantUmlBundle\Model\Decorator; + +use Irstea\PlantUmlBundle\Model\Arrow\ImplementsInterface; +use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\DecoratorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; + +/** + * Description of InheritanceDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class InterfaceDecorator extends AbstractRelationDecorator +{ + public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) + { + $interfaces = $class->getInterfaceNames(); + + $indirectInterfaces = array_filter( + array_map( + function ($i) { return $i->getInterfaceNames(); }, + $class->getInterfaces() + ) + ); + + if (!empty($indirectInterfaces)) { + $indirectInterfaces = call_user_func_array('array_merge', $indirectInterfaces); + $interfaces = array_diff($interfaces, $indirectInterfaces); + } + + $parent = $class->getParentClass(); + if ($parent) { + $interfaces = array_diff($interfaces, $parent->getInterfaceNames()); + } + + $this->visitRelations($node, $interfaces, $visitor); + + return $this; + } + + protected function buildRelation(NodeInterface $source, NodeInterface $target) + { + return new ImplementsInterface($source, $target); + } +} diff --git a/Model/Decorator/TraitDecorator.php b/Model/Decorator/TraitDecorator.php new file mode 100644 index 0000000000000000000000000000000000000000..c14d880fff879da9966445a3d6b47c17dfa56e59 --- /dev/null +++ b/Model/Decorator/TraitDecorator.php @@ -0,0 +1,42 @@ +<?php + +/* + * © 2016 IRSTEA + * Guillaume Perréal <guillaume.perreal@irstea.fr> + * Tous droits réservés. + */ + +namespace Irstea\PlantUmlBundle\Model\Decorator; + +use Irstea\PlantUmlBundle\Model\Arrow\UsesTrait; +use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\DecoratorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; + +/** + * Description of InheritanceDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class TraitDecorator extends AbstractRelationDecorator +{ + public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) + { + $traits = $class->getTraitNames(); + + $parent = $class->getParentClass(); + if ($parent) { + $traits = array_diff($traits, $parent->getTraitNames()); + } + + $this->visitRelations($node, $traits, $visitor); + + return $this; + } + + protected function buildRelation(NodeInterface $source, NodeInterface $target) + { + return new UsesTrait($source, $target); + } +}