From bd67bea6912ff3cb64c057d0420f4d5f60b93a4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guillaume=20Perr=C3=A9al?= <guillaume.perreal@irstea.fr>
Date: Fri, 11 Mar 2016 16:01:11 +0100
Subject: [PATCH] =?UTF-8?q?Ajout=20d'un=20d=C3=A9corateur=20pour=20les=20c?=
 =?UTF-8?q?hamps=20Doctrine.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 Command/GenerateCommand.php              |  3 ++
 DependencyInjection/Configuration.php    |  4 +-
 Doctrine/AssociationDecorator.php        |  6 +++
 Doctrine/Field.php                       | 67 ++++++++++++++++++++++++
 Doctrine/FieldDecorator.php              | 46 ++++++++++++++++
 Model/Node/BaseNode.php                  | 31 +++++++++++
 Model/Node/Member/AttributeInterface.php | 17 ++++++
 Model/Node/Member/Member.php             | 44 ++++++++++++++++
 Model/Node/Member/MemberInterface.php    | 23 ++++++++
 Model/Node/Member/MethodInterface.php    | 17 ++++++
 Model/NodeInterface.php                  | 19 ++++++-
 Model/TypedSymbol.php                    | 63 ++++++++++++++++++++++
 12 files changed, 336 insertions(+), 4 deletions(-)
 create mode 100644 Doctrine/Field.php
 create mode 100644 Doctrine/FieldDecorator.php
 create mode 100644 Model/Node/Member/AttributeInterface.php
 create mode 100644 Model/Node/Member/Member.php
 create mode 100644 Model/Node/Member/MemberInterface.php
 create mode 100644 Model/Node/Member/MethodInterface.php
 create mode 100644 Model/TypedSymbol.php

diff --git a/Command/GenerateCommand.php b/Command/GenerateCommand.php
index 64eaba0..79f06f3 100644
--- a/Command/GenerateCommand.php
+++ b/Command/GenerateCommand.php
@@ -11,6 +11,7 @@ use Irstea\PlantUmlBundle\Doctrine\AssociationDecorator;
 use Irstea\PlantUmlBundle\Doctrine\DoctrineNamespace;
 use Irstea\PlantUmlBundle\Doctrine\EntityDecorator;
 use Irstea\PlantUmlBundle\Doctrine\EntityFinder;
+use Irstea\PlantUmlBundle\Doctrine\FieldDecorator;
 use Irstea\PlantUmlBundle\Finder\ClassFinder;
 use Irstea\PlantUmlBundle\Finder\FilteringFinder;
 use Irstea\PlantUmlBundle\Finder\FinderInterface;
@@ -208,6 +209,8 @@ class GenerateCommand extends ContainerAwareCommand
                 return new EntityDecorator($this->entityManager->getMetadataFactory());
             case 'associations':
                 return new AssociationDecorator($this->entityManager->getMetadataFactory());
+            case 'fields':
+                return new FieldDecorator($this->entityManager->getMetadataFactory());
         }
     }
 
diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php
index 2c8e19b..4cd2751 100644
--- a/DependencyInjection/Configuration.php
+++ b/DependencyInjection/Configuration.php
@@ -85,9 +85,9 @@ class Configuration implements ConfigurationInterface
                         ->addDefaultsIfNotSet()
                         ->children()
                             ->arrayNode('decorators')
-                                ->defaultValue(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods'])
+                                ->defaultValue(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods', 'fields'])
                                 ->prototype('enum')
-                                    ->values(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods'])
+                                    ->values(['inheritance', 'traits', 'interfaces', 'entity', 'associations', 'properties', 'methods', 'fields'])
                                 ->end()
                             ->end()
                             ->append($this->buildFilterNode('include'))
diff --git a/Doctrine/AssociationDecorator.php b/Doctrine/AssociationDecorator.php
index 9d15b70..ae4fb6b 100644
--- a/Doctrine/AssociationDecorator.php
+++ b/Doctrine/AssociationDecorator.php
@@ -11,6 +11,7 @@ namespace Irstea\PlantUmlBundle\Doctrine;
 use Doctrine\ORM\Mapping\ClassMetadata;
 use Irstea\PlantUmlBundle\Model\Arrow\BaseArrow;
 use Irstea\PlantUmlBundle\Model\ClassVisitorInterface;
+use Irstea\PlantUmlBundle\Model\Node\Member\Member;
 use Irstea\PlantUmlBundle\Model\NodeInterface;
 use ReflectionClass;
 
@@ -41,6 +42,11 @@ class AssociationDecorator extends AbstractDoctrineDecorator
 
         $target  = $visitor->visitClass($association['targetEntity']);
         if ($target === false) {
+            $type = $association['targetEntity'];
+            if ($association["type"] & ClassMetadata::TO_MANY != 0) {
+                $type .= '[]';
+            }
+            $node->addAttribute(new Member($association['fieldName'], $type));
             return;
         }
 
diff --git a/Doctrine/Field.php b/Doctrine/Field.php
new file mode 100644
index 0000000..ceb730a
--- /dev/null
+++ b/Doctrine/Field.php
@@ -0,0 +1,67 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Doctrine;
+
+use Irstea\PlantUmlBundle\Model\Node\Member\Member;
+use Irstea\PlantUmlBundle\Writer\WriterInterface;
+
+/**
+ * Description of Field
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class Field extends Member
+{
+    /**
+     * @var boolean
+     */
+    private $isUnique;
+
+    /**
+     * @var boolean
+     */
+    private $isNullable;
+
+    /**
+     * @var boolean
+     */
+    private $isIdentifier;
+
+    public function __construct($symbol, $type, $isUnique = false, $isNullable = false, $isIdentifier = false)
+    {
+        parent::__construct($symbol, $type);
+        $this->isUnique     = $isUnique;
+        $this->isNullable   = $isNullable;
+        $this->isIdentifier = $isIdentifier;
+    }
+
+    protected function writeSymbolTo(WriterInterface $writer)
+    {
+        if ($this->isIdentifier) {
+            $writer->write('<b>');
+        }
+        if (!$this->isNullable) {
+            $writer->write('<i>');
+        }
+        if ($this->isUnique) {
+            $writer->write('<u>');
+        }
+        parent::writeSymbolTo($writer);
+        if ($this->isUnique) {
+            $writer->write('</u>');
+        }
+        if (!$this->isNullable) {
+            $writer->write('</i>');
+        }
+        if ($this->isIdentifier) {
+            $writer->write('</b>');
+        }
+        return $this;
+    }
+}
diff --git a/Doctrine/FieldDecorator.php b/Doctrine/FieldDecorator.php
new file mode 100644
index 0000000..b21efad
--- /dev/null
+++ b/Doctrine/FieldDecorator.php
@@ -0,0 +1,46 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Doctrine;
+
+use Doctrine\ORM\Mapping\ClassMetadata;
+use Irstea\PlantUmlBundle\Model\ClassVisitorInterface;
+use Irstea\PlantUmlBundle\Model\NodeInterface;
+
+/**
+ * Description of RelationDecorator
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class FieldDecorator extends AbstractDoctrineDecorator
+{
+    protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor)
+    {
+        if(empty($metadata->fieldMappings)) {
+            return;
+        }
+
+        foreach($metadata->fieldMappings as $field) {
+            $this->visitField($node, $visitor, $field, $metadata->isIdentifier($field['fieldName']));
+        }
+    }
+
+    protected function visitField(NodeInterface $node, ClassVisitorInterface $visitor, array $field, $isIdentifier)
+    {
+        if (isset($field['inherited']) || isset($field['declared'])) {
+            return;
+        }
+        $node->addAttribute(new Field(
+            $field['fieldName'],
+            $field['type'],
+            $field['unique'],
+            $field['nullable'],
+            $isIdentifier
+        ));
+    }
+}
diff --git a/Model/Node/BaseNode.php b/Model/Node/BaseNode.php
index 1a5cd69..9ed589b 100644
--- a/Model/Node/BaseNode.php
+++ b/Model/Node/BaseNode.php
@@ -10,6 +10,8 @@ namespace Irstea\PlantUmlBundle\Model\Node;
 
 use Irstea\PlantUmlBundle\Model\ArrowInterface;
 use Irstea\PlantUmlBundle\Model\NamespaceInterface;
+use Irstea\PlantUmlBundle\Model\Node\Member\AttributeInterface;
+use Irstea\PlantUmlBundle\Model\Node\Member\MethodInterface;
 use Irstea\PlantUmlBundle\Model\NodeInterface;
 use Irstea\PlantUmlBundle\Writer\WriterInterface;
 
@@ -50,6 +52,17 @@ class BaseNode implements NodeInterface
      */
     private $namespace;
 
+    /**
+     * @var AttributeInterface[]
+     */
+    private $attributes = [];
+
+    /**
+     *
+     * @var MethodInterface[]
+     */
+    private $methods = [];
+
     /**
      * @param NamespaceInterface $namespace
      * @param string $name
@@ -80,6 +93,18 @@ class BaseNode implements NodeInterface
         return $this;
     }
 
+    public function addAttribute(AttributeInterface $attribute)
+    {
+        $this->attributes[] = $attribute;
+        return $this;
+    }
+
+    public function addMethod(MethodInterface $method)
+    {
+        $this->methods[] = $method;
+        return $this;
+    }
+
     public function setLabel($label)
     {
         $this->label = $label;
@@ -136,11 +161,17 @@ class BaseNode implements NodeInterface
 
     protected function writeAttributesTo(WriterInterface $writer)
     {
+        foreach($this->attributes as $attribute) {
+            $attribute->writeTo($writer);
+        }
         return $this;
     }
 
     protected function writeMethodsTo(WriterInterface $writer)
     {
+        foreach($this->methods as $method) {
+            $method->writeTo($writer);
+        }
         return $this;
     }
 
diff --git a/Model/Node/Member/AttributeInterface.php b/Model/Node/Member/AttributeInterface.php
new file mode 100644
index 0000000..49831fb
--- /dev/null
+++ b/Model/Node/Member/AttributeInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model\Node\Member;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+interface AttributeInterface extends MemberInterface
+{
+}
diff --git a/Model/Node/Member/Member.php b/Model/Node/Member/Member.php
new file mode 100644
index 0000000..c9aa15d
--- /dev/null
+++ b/Model/Node/Member/Member.php
@@ -0,0 +1,44 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model\Node\Member;
+
+use Irstea\PlantUmlBundle\Model\TypedSymbol;
+use Irstea\PlantUmlBundle\Writer\WriterInterface;
+
+/**
+ * Description of AbstractMember
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class Member extends TypedSymbol implements MethodInterface, AttributeInterface
+{
+    /**
+     * @var string
+     */
+    private $visibility;
+
+    public function __construct($symbol, $type = false, $visibility = self::UNKNOWN)
+    {
+        parent::__construct($symbol, $type);
+        $this->visibility = $visibility;
+    }
+
+    public function writeTo(WriterInterface $writer)
+    {
+        $writer->write($this->visibility);
+        $this->writeMemberTo($writer);
+        $writer->write("\n");
+        return $this;
+    }
+
+    protected function writeMemberTo(WriterInterface $writer)
+    {
+        return parent::writeTo($writer);
+    }
+}
diff --git a/Model/Node/Member/MemberInterface.php b/Model/Node/Member/MemberInterface.php
new file mode 100644
index 0000000..a58f302
--- /dev/null
+++ b/Model/Node/Member/MemberInterface.php
@@ -0,0 +1,23 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model\Node\Member;
+
+use Irstea\PlantUmlBundle\Writer\WritableInterface;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+interface MemberInterface extends WritableInterface
+{
+    const PRIVATE_ = '-';
+    const PROTECTED_ = '#';
+    const PUBLIC_ = '+';
+    const UNKNOWN = '';
+}
diff --git a/Model/Node/Member/MethodInterface.php b/Model/Node/Member/MethodInterface.php
new file mode 100644
index 0000000..823317b
--- /dev/null
+++ b/Model/Node/Member/MethodInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model\Node\Member;
+
+/**
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+interface MethodInterface extends MemberInterface
+{
+}
diff --git a/Model/NodeInterface.php b/Model/NodeInterface.php
index d74a344..31981a9 100644
--- a/Model/NodeInterface.php
+++ b/Model/NodeInterface.php
@@ -8,6 +8,8 @@
 
 namespace Irstea\PlantUmlBundle\Model;
 
+use Irstea\PlantUmlBundle\Model\Node\Member\AttributeInterface;
+use Irstea\PlantUmlBundle\Model\Node\Member\MethodInterface;
 use Irstea\PlantUmlBundle\Writer\WritableNodeInterface;
 
 /**
@@ -30,13 +32,26 @@ interface NodeInterface extends WritableNodeInterface
 
     /**
      * @param string $classifier
-     * @return string
+     * @return self
      */
     public function addClassifier($classifier);
 
     /**
      * @param string $stereotype
-     * @return string
+     * @return self
      */
     public function addStereotype($stereotype);
+
+    /**
+     * @param AttributeInterface $attribute
+     * @return self
+     */
+    public function addAttribute(AttributeInterface $attribute);
+
+
+    /**
+     * @param MethodInterface $method
+     * @return self
+     */
+    public function addMethod(MethodInterface $method);
 }
diff --git a/Model/TypedSymbol.php b/Model/TypedSymbol.php
new file mode 100644
index 0000000..f5ffea8
--- /dev/null
+++ b/Model/TypedSymbol.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * © 2016 IRSTEA
+ * Guillaume Perréal <guillaume.perreal@irstea.fr>
+ * Tous droits réservés.
+ */
+
+namespace Irstea\PlantUmlBundle\Model;
+
+use Irstea\PlantUmlBundle\Writer\WritableInterface;
+use Irstea\PlantUmlBundle\Writer\WriterInterface;
+
+/**
+ * Description of TypedSymbol
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class TypedSymbol implements WritableInterface
+{
+    /**
+     * @var string
+     */
+    private $type;
+
+    /**
+     * @var string
+     */
+    private $symbol;
+
+    /**
+     * @param type $symbol
+     * @param type $type
+     */
+    public function __construct($symbol, $type = false)
+    {
+        $this->type   = $type;
+        $this->symbol = $symbol;
+    }
+
+    /**
+     * @param WriterInterface $writer
+     * @return TypedSymbol
+     */
+    public function writeTo(WriterInterface $writer)
+    {
+        return $this->writeTypeTo($writer)->writeSymbolTo($writer);
+    }
+
+    protected function writeTypeTo(WriterInterface $writer)
+    {
+        if ($this->type) {
+            $writer->writeFormatted("%s ", $this->type);
+        }
+        return $this;
+    }
+
+    protected function writeSymbolTo(WriterInterface $writer)
+    {
+        $writer->write($this->symbol);
+        return $this;
+    }
+}
-- 
GitLab