diff --git a/Doctrine/AbstractDoctrineDecorator.php b/Doctrine/AbstractDoctrineDecorator.php index 2110ff71edd089210fece824da01557594e2fed8..00730b48e16bccb3108231bde9804f3784fbe9cb 100644 --- a/Doctrine/AbstractDoctrineDecorator.php +++ b/Doctrine/AbstractDoctrineDecorator.php @@ -33,14 +33,22 @@ abstract class AbstractDoctrineDecorator implements DecoratorInterface $this->metadataFactory = $manager->getMetadataFactory(); } - public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) + /** + * @param callable $callback + * @param ReflectionClass $class + * @return mixed + */ + protected function withMetadata($callback, ReflectionClass $class = null) { + if (!$class) { + return null; + } + $className = $class->getName(); - if ($this->metadataFactory->hasMetadataFor($className)) { - $this->decorateEntity($this->metadataFactory->getMetadataFor($className), $node, $visitor); + if (!$this->metadataFactory->hasMetadataFor($className)) { + return null; } - return $this; + + return $callback($this->metadataFactory->getMetadataFor($className)); } - - abstract protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor); -} \ No newline at end of file +} diff --git a/Doctrine/AssociationDecorator.php b/Doctrine/AssociationDecorator.php index c98e5697752784aecdece1c7901a68dc215329e0..d5620699cf49641a18ebf4c3515aaa66b6b3589c 100644 --- a/Doctrine/AssociationDecorator.php +++ b/Doctrine/AssociationDecorator.php @@ -22,19 +22,19 @@ use ReflectionClass; */ class AssociationDecorator extends AbstractDoctrineDecorator { - protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor) + use \Irstea\PlantUmlBundle\Model\Decorator\InheritableItemDecoratorTrait; + + protected function extractItems(ReflectionClass $class) { - $associations = $metadata->getAssociationMappings(); - if(empty($associations)) { - return; - } - - foreach($associations as $association) { - $this->visitAssociation($node, $visitor, $association); - } + return $this->withMetadata( + function ($metadata) { + return $metadata->getAssociationMappings(); + }, + $class + ); } - protected function visitAssociation(NodeInterface $node, ClassVisitorInterface $visitor, array $association) + protected function decorateItem(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor, $association) { if (!$association['isOwningSide']) { return; diff --git a/Doctrine/EntityDecorator.php b/Doctrine/EntityDecorator.php index 64d65222d6ad86d2bb7f7570cab533665d5e11cb..7fed8f017f5a11b5835cc8425d0bde8b7c954fb6 100644 --- a/Doctrine/EntityDecorator.php +++ b/Doctrine/EntityDecorator.php @@ -19,14 +19,19 @@ use Irstea\PlantUmlBundle\Model\NodeInterface; */ class EntityDecorator extends AbstractDoctrineDecorator { - protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor) + public function decorate(\ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) { - if ($metadata->isMappedSuperclass) { - $node->addStereotype('mappedSuperClass'); - } elseif($metadata->isEmbeddedClass) { - $node->addStereotype('embedded'); - } else { - $node->addStereotype('entity'); - } + $this->withMetadata( + function ($metadata) use($node) { + if ($metadata->isMappedSuperclass) { + $node->addStereotype('mappedSuperClass'); + } elseif($metadata->isEmbeddedClass) { + $node->addStereotype('embedded'); + } else { + $node->addStereotype('entity'); + } + }, + $class + ); } } diff --git a/Doctrine/FieldDecorator.php b/Doctrine/FieldDecorator.php index b21efad7c0919430f773983ab85fc761dc82ab86..43779cf8cf4a9eb38d9d23a9b8f9cd8bb2f6bc4e 100644 --- a/Doctrine/FieldDecorator.php +++ b/Doctrine/FieldDecorator.php @@ -11,6 +11,7 @@ namespace Irstea\PlantUmlBundle\Doctrine; use Doctrine\ORM\Mapping\ClassMetadata; use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; /** * Description of RelationDecorator @@ -19,28 +20,32 @@ use Irstea\PlantUmlBundle\Model\NodeInterface; */ class FieldDecorator extends AbstractDoctrineDecorator { - protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor) - { - if(empty($metadata->fieldMappings)) { - return; - } + use \Irstea\PlantUmlBundle\Model\Decorator\InheritableItemDecoratorTrait; - foreach($metadata->fieldMappings as $field) { - $this->visitField($node, $visitor, $field, $metadata->isIdentifier($field['fieldName'])); - } + protected function extractItems(ReflectionClass $class) + { + return $this->withMetadata( + function ($metadata) { + return $metadata->fieldMappings; + }, + $class + ); } - protected function visitField(NodeInterface $node, ClassVisitorInterface $visitor, array $field, $isIdentifier) + protected function decorateItem(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor, $field) { - if (isset($field['inherited']) || isset($field['declared'])) { - return; - } + $isIdentifier = $this->withMetadata( + function ($metadata) use ($field) { + return $metadata->isIdentifier($field['fieldName']); + }, + $class + ); + $node->addAttribute(new Field( $field['fieldName'], $field['type'], $field['unique'], - $field['nullable'], - $isIdentifier + $field['nullable'] )); } } diff --git a/Model/Decorator/InheritableItemDecoratorTrait.php b/Model/Decorator/InheritableItemDecoratorTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..ae5bf6a5619dfa70f36abd59d655e9727d987609 --- /dev/null +++ b/Model/Decorator/InheritableItemDecoratorTrait.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\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; + +/** + * Décorateur abstrait pour les éléments d'une classe qui peuvent être hérités d'une classe base. + * + * Ce décorateur s'assure de n'afficher que les éléments propres à la classe. + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +trait InheritableItemDecoratorTrait +{ + /** + * + * @param \ReflectionClass $class + * @param NodeInterface $node + * @param ClassVisitorInterface $visitor + * @return self + */ + public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) + { + $items = $this->extractItems($class); + if (empty($items)) { + return; + } + + $parent = $class->getParentClass(); + if ($parent) { + $parentItems = $this->extractItems($parent); + if (!empty($parentItems)) { + $items = array_diff_key($items, $parentItems); + } + } + + foreach($items as $item) { + $this->decorateItem($class, $node, $visitor, $item); + } + } + + abstract protected function extractItems(ReflectionClass $class); + + abstract protected function decorateItem(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor, $item); +}