-
Guillaume Perréal authored85f81393
<?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);
}
}