An error occurred while loading the file. Please try again.
-
Guillaume Perréal authorede5959457
<?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 ReflectionClass;
/**
* Description of Visitor
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class ClassVisitor implements ClassVisitorInterface, UmlComponentInterface
{
/**
* @var UmlNodeInterface[]
*/
protected $nodes = [];
/**
* @var UmlComponentInterface[]
*/
protected $arrows = [];
/**
* @var string[]
*/
protected $namespaces = [];
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());
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
}
$this->nodes[$class->getName()] = $node;
$this->visitNamespace($class->getNamespaceName());
$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, [$parentClass->getName()], 'Irstea\PlantUmlBundle\Model\Arrow\ExtendsClass');
}
$this->visitRelations($node, $interfaceNames, 'Irstea\PlantUmlBundle\Model\Arrow\ImplementsInterface');
$this->visitRelations($node, $traitNames, 'Irstea\PlantUmlBundle\Model\Arrow\UsesTrait');
return $node;
}
protected function visitRelations(UmlNodeInterface $source, array $classNames, $relationClass)
{
foreach ($classNames as $className) {
$target = $this->visitClass($className);
$this->arrows[] = new $relationClass($source, $target);
}
}
protected function visitNamespace($namespaceName)
{
$current =& $this->namespaces;
foreach(explode('\\', $namespaceName) as $part) {
if (!isset($current[$part])) {
$current[$part] = [];
}
$current = &$current[$part];
}
}
public function outputTo($stream)
{
$this->outputNamespacesTo($stream, $this->namespaces);
foreach ($this->nodes as $node) {
$node->outputTo($stream);
}
foreach ($this->arrows as $arrow) {
$arrow->outputTo($stream);
}
}
protected function outputNamespacesTo($stream, $namespaces)
{
foreach($namespaces as $name => $children) {
fputs($stream, "namespace ");
/*while(count($children) == 1) {
fputs($stream, $name.'.');
list($name, $children) = each($children);
}*/
141142143144145146147
fputs($stream, "$name {\n");
$this->outputNamespacesTo($stream, $children);
fputs($stream, "}\n");
}
}
}