From 23467d72c421ee92bd1eeb675ac1e3d94bf20e3c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guillaume=20Perr=C3=A9al?= <guillaume.perreal@irstea.fr>
Date: Fri, 13 May 2016 13:20:09 +0200
Subject: [PATCH] =?UTF-8?q?N'affiche=20plus=20les=20asoociations=20et=20ch?=
 =?UTF-8?q?amps=20h=C3=A9rit=C3=A9s=20de=20Doctrine.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Doctrine/AbstractDoctrineDecorator.php        | 22 +++++---
 Doctrine/AssociationDecorator.php             | 20 +++----
 Doctrine/EntityDecorator.php                  | 21 +++++---
 Doctrine/FieldDecorator.php                   | 33 +++++++-----
 .../InheritableItemDecoratorTrait.php         | 54 +++++++++++++++++++
 5 files changed, 111 insertions(+), 39 deletions(-)
 create mode 100644 Model/Decorator/InheritableItemDecoratorTrait.php

diff --git a/Doctrine/AbstractDoctrineDecorator.php b/Doctrine/AbstractDoctrineDecorator.php
index 2110ff7..00730b4 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 c98e569..d562069 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 64d6522..7fed8f0 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 b21efad..43779cf 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 0000000..ae5bf6a
--- /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);
+}
-- 
GitLab