From e721fb6af5b796305c2930ae8cf65242951a7209 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guillaume=20Perr=C3=A9al?= <guillaume.perreal@irstea.fr> Date: Wed, 9 Mar 2016 16:09:40 +0100 Subject: [PATCH] =?UTF-8?q?Ajout=20des=20premiers=20d=C3=A9corateurs=20Doc?= =?UTF-8?q?trine.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Command/EntitySchemaCommand.php | 9 ++- Doctrine/AbstractDoctrineDecorator.php | 45 +++++++++++++++ Doctrine/AssociationDecorator.php | 78 ++++++++++++++++++++++++++ Doctrine/EntityDecorator.php | 32 +++++++++++ Model/Node/BaseNode.php | 16 +++++- Model/NodeInterface.php | 12 ++++ 6 files changed, 188 insertions(+), 4 deletions(-) create mode 100644 Doctrine/AbstractDoctrineDecorator.php create mode 100644 Doctrine/AssociationDecorator.php create mode 100644 Doctrine/EntityDecorator.php diff --git a/Command/EntitySchemaCommand.php b/Command/EntitySchemaCommand.php index be44af3..a47536c 100644 --- a/Command/EntitySchemaCommand.php +++ b/Command/EntitySchemaCommand.php @@ -8,11 +8,12 @@ namespace Irstea\PlantUmlBundle\Command; use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\Mapping\ClassMetadata; +use Irstea\PlantUmlBundle\Doctrine\AssociationDecorator; +use Irstea\PlantUmlBundle\Doctrine\EntityDecorator; 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\NullDecorator; use Irstea\PlantUmlBundle\Model\Filter\Whitelist; use Irstea\PlantUmlBundle\Writer\OutputWriter; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; @@ -55,7 +56,11 @@ class EntitySchemaCommand extends ContainerAwareCommand ); $decorator = new FilteringDecorator( - new InheritanceDecorator(), + new CompositeDecorator([ + new InheritanceDecorator(), + new EntityDecorator($factory), + new AssociationDecorator($factory), + ]), new Whitelist($classes) ); diff --git a/Doctrine/AbstractDoctrineDecorator.php b/Doctrine/AbstractDoctrineDecorator.php new file mode 100644 index 0000000..6494d51 --- /dev/null +++ b/Doctrine/AbstractDoctrineDecorator.php @@ -0,0 +1,45 @@ +<?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 Doctrine\ORM\Mapping\ClassMetadataFactory; +use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\DecoratorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; + +/** + * Description of AbstractDoctrineDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +abstract class AbstractDoctrineDecorator implements DecoratorInterface +{ + /** + * @var ClassMetadataFactory + */ + protected $metadataFactory; + + public function __construct(ClassMetadataFactory $metadataFactory) + { + $this->metadataFactory = $metadataFactory; + } + + public function decorate(ReflectionClass $class, NodeInterface $node, ClassVisitorInterface $visitor) + { + $className = $class->getName(); + if ($this->metadataFactory->hasMetadataFor($className)) { + $this->decorateEntity($this->metadataFactory->getMetadataFor($className), $node, $visitor); + } + return $this; + } + + 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 new file mode 100644 index 0000000..a5027fd --- /dev/null +++ b/Doctrine/AssociationDecorator.php @@ -0,0 +1,78 @@ +<?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\Arrow\BaseArrow; +use Irstea\PlantUmlBundle\Model\ClassVisitorInterface; +use Irstea\PlantUmlBundle\Model\NodeInterface; +use ReflectionClass; + +/** + * Description of RelationDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class AssociationDecorator extends AbstractDoctrineDecorator +{ + protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor) + { + $associations = $metadata->getAssociationMappings(); + if(empty($associations)) { + return; + } + + foreach($associations as $association) { + $this->visitAssociation($node, $visitor, $association); + } + } + + protected function visitAssociation(NodeInterface $node, ClassVisitorInterface $visitor, array $association) + { + if (!$association['isOwningSide']) { + return; + } + + $target = $visitor->visitClass($association['targetEntity']); + if ($target === false) { + return; + } + + $link = "-->"; + if ($association["isCascadeRemove"]) { + $link = "o".$link; + } + + $leftLabel = ""; + $rightLabel = ""; + switch($association["type"]) { + case ClassMetadata::ONE_TO_ONE: + $leftLabel = '1'; + $rightLabel = '1'; + break; + case ClassMetadata::ONE_TO_MANY: + $leftLabel = '1'; + $rightLabel = '*'; + break; + case ClassMetadata::MANY_TO_MANY: + $leftLabel = '*'; + $rightLabel = '*'; + break; + case ClassMetadata::MANY_TO_ONE: + $leftLabel = '*'; + $rightLabel = '1'; + break; + } + $link = sprintf('"%s" %s "%s"', $leftLabel, $link, $rightLabel); + + $node->addArrow( + new BaseArrow($node, $target, $link, $association["fieldName"]." >") + ); + } +} diff --git a/Doctrine/EntityDecorator.php b/Doctrine/EntityDecorator.php new file mode 100644 index 0000000..64d6522 --- /dev/null +++ b/Doctrine/EntityDecorator.php @@ -0,0 +1,32 @@ +<?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 EntityDecorator + * + * @author Guillaume Perréal <guillaume.perreal@irstea.fr> + */ +class EntityDecorator extends AbstractDoctrineDecorator +{ + protected function decorateEntity(ClassMetadata $metadata, NodeInterface $node, ClassVisitorInterface $visitor) + { + if ($metadata->isMappedSuperclass) { + $node->addStereotype('mappedSuperClass'); + } elseif($metadata->isEmbeddedClass) { + $node->addStereotype('embedded'); + } else { + $node->addStereotype('entity'); + } + } +} diff --git a/Model/Node/BaseNode.php b/Model/Node/BaseNode.php index ced0607..1b19d52 100644 --- a/Model/Node/BaseNode.php +++ b/Model/Node/BaseNode.php @@ -59,9 +59,9 @@ class BaseNode implements NodeInterface */ function __construct(NamespaceInterface $namespace, $name, $nodeType, array $classifiers = [], array $stereotypes = []) { - $this->namespace = $namespace; + $this->namespace = $namespace; - $pos = strrpos($name, '\\'); + $pos = strrpos($name, '\\'); $this->name = substr($name, $pos + 1); $this->alias = str_replace('\\', '.', $name)."_node"; @@ -70,6 +70,18 @@ class BaseNode implements NodeInterface $this->stereotypes = $stereotypes; } + public function addClassifier($classifier) + { + $this->classifiers[] = $classifier; + return $this; + } + + public function addStereotype($stereotype) + { + $this->stereotypes[] = $stereotype; + return $this; + } + public function outputTo(WriterInterface $writer) { $this diff --git a/Model/NodeInterface.php b/Model/NodeInterface.php index bf2ba6e..7a27509 100644 --- a/Model/NodeInterface.php +++ b/Model/NodeInterface.php @@ -21,4 +21,16 @@ interface NodeInterface extends WritableNodeInterface * @return self */ public function addArrow(ArrowInterface $arrow); + + /** + * @param string $classifier + * @return string + */ + public function addClassifier($classifier); + + /** + * @param string $stereotype + * @return string + */ + public function addStereotype($stereotype); } -- GitLab