ClassVisitor.php 3.43 KiB
<?php
/*
 * © 2016 IRSTEA
 * Guillaume Perréal <guillaume.perreal@irstea.fr>
 * Tous droits réservés.
 */
namespace Irstea\PlantUmlBundle\Model;
use Irstea\PlantUmlBundle\Model\Node\Class_;
use Irstea\PlantUmlBundle\Model\Node\Interface_;
use Irstea\PlantUmlBundle\Model\Node\Trait_;
use Irstea\PlantUmlBundle\Writer\WriterInterface;
use ReflectionClass;
/**
 * Description of Visitor
 * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
class ClassVisitor implements ClassVisitorInterface, UmlComponentInterface
    /**
     * @var RootNamespace
    protected $rootNamespace;
    public function __construct()
        $this->rootNamespace = new RootNamespace();
    public function visitClass($className)
        assert('is_string($className)', $className);
        if (isset($this->nodes[$className])) {
            return $this->nodes[$className];
        return $this->doVisitClass($className);
    /**
     * @param string $className
     * @return UmlNodeInterface
    protected function doVisitClass($className)
        $reflection = new ReflectionClass($className);
        return $this->visitClassReflection($reflection);
    /**
     * @param ReflectionClass $class
     * @return UmlNodeInterface
    protected function visitClassReflection(ReflectionClass $class)
        if ($class->isTrait()) {
            $node  = new Trait_($class->getName());
        } elseif ($class->isInterface()) {
            $node  = new Interface_($class->getName());
        } else {
            $node = new Class_($class->getName(), $class->isAbstract(), $class->isFinal());
        $this->nodes[$class->getName()] = $node;
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
$namespace = $this->rootNamespace->getNamespace($class->getNamespaceName()); $namespace->addNode($node); $parentClass = $class->getParentClass(); $traitNames = $class->getTraitNames(); $indirectInterfaces = array_filter( array_map( function ($i) { return $i->getInterfaceNames(); }, $class->getInterfaces() ) ); $interfaceNames = $class->getInterfaceNames(); if (!empty($indirectInterfaces)) { $indirectInterfaces = call_user_func_array('array_merge', $indirectInterfaces); $interfaceNames = array_diff($interfaceNames, $indirectInterfaces); } if ($parentClass) { $traitNames = array_diff($traitNames, $parentClass->getTraitNames()); $interfaceNames = array_diff($interfaceNames, $parentClass->getInterfaceNames()); $this->visitRelations($node, $namespace, [$parentClass->getName()], 'Irstea\PlantUmlBundle\Model\Arrow\ExtendsClass'); } $this->visitRelations($node, $namespace, $interfaceNames, 'Irstea\PlantUmlBundle\Model\Arrow\ImplementsInterface'); $this->visitRelations($node, $namespace, $traitNames, 'Irstea\PlantUmlBundle\Model\Arrow\UsesTrait'); return $node; } protected function visitRelations(UmlNodeInterface $source, NamespaceInterface $namespace, array $classNames, $relationClass) { foreach ($classNames as $className) { $target = $this->visitClass($className); $namespace->addArrow(new $relationClass($source, $target)); } } public function outputTo(WriterInterface $writer) { return $this->rootNamespace->outputTo($writer); } }