Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Pôle IS
Bundles Symfony 2
plantuml-bundle
Commits
051af78f
Commit
051af78f
authored
Mar 09, 2016
by
Guillaume Perréal
Browse files
Mise en place d'un framework de décorateurs.
parent
709da3ad
Changes
10
Show whitespace changes
Inline
Side-by-side
Command/EntitySchemaCommand.php
View file @
051af78f
...
...
@@ -8,16 +8,18 @@ namespace Irstea\PlantUmlBundle\Command;
use
Doctrine\ORM\EntityManagerInterface
;
use
Doctrine\ORM\Mapping\ClassMetadata
;
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\Model\Namespace_
;
use
Irstea\PlantUmlBundle\Model\Orm\EntityVisitor
;
use
Irstea\PlantUmlBundle\Writer\OutputWriter
;
use
Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand
;
use
Symfony\Component\Console\Input\InputArgument
;
use
Symfony\Component\Console\Input\InputInterface
;
use
Symfony\Component\Console\Input\InputOption
;
use
Symfony\Component\Console\Output\OutputInterface
;
/**
* Description of ImportAffiliationCommand
*
...
...
@@ -52,7 +54,13 @@ class EntitySchemaCommand extends ContainerAwareCommand
$allMetadata
);
$visitor
=
new
EntityVisitor
(
$allMetadata
);
$decorator
=
new
FilteringDecorator
(
new
InheritanceDecorator
(),
new
Whitelist
(
$classes
)
);
$visitor
=
new
ClassVisitor
(
$decorator
);
array_walk
(
$classes
,
[
$visitor
,
'visitClass'
]);
$writer
=
new
OutputWriter
(
$output
);
...
...
Model/ClassVisitor.php
View file @
051af78f
...
...
@@ -35,10 +35,16 @@ class ClassVisitor implements ClassVisitorInterface, WritableInterface
*/
protected
$filter
;
public
function
__construct
(
ClassFilterInterface
$filter
=
null
)
/**
* @var DecoratorInterface
*/
protected
$decorator
;
public
function
__construct
(
DecoratorInterface
$decorator
=
null
,
ClassFilterInterface
$filter
=
null
)
{
$this
->
rootNamespace
=
new
RootNamespace
();
$this
->
filter
=
$filter
?:
AcceptAllFilter
::
instance
();
$this
->
decorator
=
$decorator
?:
NullDecorator
::
instance
();
}
/**
...
...
@@ -51,6 +57,16 @@ class ClassVisitor implements ClassVisitorInterface, WritableInterface
return
$this
;
}
/**
* @param DecoratorInterface $decorator
* @return self
*/
public
function
setDecorator
(
DecoratorInterface
$decorator
)
{
$this
->
decorator
=
$decorator
;
return
$this
;
}
public
function
visitClass
(
$className
)
{
assert
(
'is_string($className)'
,
$className
);
...
...
@@ -61,7 +77,7 @@ class ClassVisitor implements ClassVisitorInterface, WritableInterface
return
$this
->
nodes
[
$className
]
=
false
;
}
return
$this
->
doVisitClass
(
$className
);
return
$this
->
createNode
(
$className
);
}
/**
...
...
@@ -69,68 +85,27 @@ class ClassVisitor implements ClassVisitorInterface, WritableInterface
* @param string $className
* @return NodeInterface
*/
protected
function
doVisitClass
(
$className
)
{
$reflection
=
new
ReflectionClass
(
$className
);
return
$this
->
visitClassReflection
(
$reflection
);
}
/**
* @param ReflectionClass $class
* @return NodeInterface
*/
protected
function
visitClassReflection
(
ReflectionClass
$class
)
protected
function
createNode
(
$className
)
{
$class
=
new
ReflectionClass
(
$className
);
$namespace
=
$this
->
rootNamespace
->
getNamespace
(
$class
->
getNamespaceName
());
if
(
$class
->
isTrait
())
{
$node
=
new
Trait_
(
$namespace
,
$class
->
get
Name
()
);
$node
=
new
Trait_
(
$namespace
,
$className
);
}
elseif
(
$class
->
isInterface
())
{
$node
=
new
Interface_
(
$namespace
,
$class
->
get
Name
()
);
$node
=
new
Interface_
(
$namespace
,
$className
);
}
else
{
$node
=
new
Class_
(
$namespace
,
$class
->
get
Name
()
,
$class
->
isAbstract
(),
$class
->
isFinal
());
$node
=
new
Class_
(
$namespace
,
$className
,
$class
->
isAbstract
(),
$class
->
isFinal
());
}
$this
->
nodes
[
$class
->
getName
()]
=
$node
;
$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
,
[
$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'
);
$this
->
decorator
->
decorate
(
$className
,
$node
,
$this
);
return
$node
;
}
protected
function
visitRelations
(
NodeInterface
$source
,
array
$classNames
,
$relationClass
)
{
foreach
(
$classNames
as
$className
)
{
$target
=
$this
->
visitClass
(
$className
);
if
(
$target
)
{
$source
->
addArrow
(
new
$relationClass
(
$source
,
$target
));
}
}
}
public
function
outputTo
(
WriterInterface
$writer
)
{
return
$this
->
rootNamespace
->
outputTo
(
$writer
);
...
...
Model/Decorator/CompositeDecorator.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model\Decorator
;
use
Irstea\PlantUmlBundle\Model\ClassVisitorInterface
;
use
Irstea\PlantUmlBundle\Model\DecoratorInterface
;
use
Irstea\PlantUmlBundle\Model\NodeInterface
;
/**
* Description of CompositeDecorator
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
CompositeDecorator
implements
DecoratorInterface
{
/**
* @var DecoratorInterface[]
*/
private
$decorators
=
[];
public
function
__construct
(
array
$decorators
=
[])
{
$this
->
decorators
=
$decorators
;
}
public
function
addDecorator
(
DecoratorInterface
$decorator
)
{
$this
->
decorators
[]
=
$decorator
;
return
$this
;
}
public
function
decorate
(
$className
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
)
{
foreach
(
$this
->
decorators
as
$decorator
)
{
$decorator
->
decorate
(
$className
,
$node
,
$visitor
);
}
return
$this
;
}
}
Model/Decorator/FilteringDecorator.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model\Decorator
;
use
Irstea\PlantUmlBundle\Model\ClassFilterInterface
;
use
Irstea\PlantUmlBundle\Model\ClassVisitorInterface
;
use
Irstea\PlantUmlBundle\Model\DecoratorInterface
;
use
Irstea\PlantUmlBundle\Model\NodeInterface
;
/**
* Description of FilteringDecorator
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
FilteringDecorator
implements
DecoratorInterface
{
/**
* @var DecoratorInterface
*/
private
$next
;
/**
* @var ClassFilterInterface
*/
private
$filter
;
/**
* @param DecoratorInterface $next
* @param ClassFilterInterface $filter
*/
public
function
__construct
(
DecoratorInterface
$next
,
ClassFilterInterface
$filter
)
{
$this
->
next
=
$next
;
$this
->
filter
=
$filter
;
}
public
function
decorate
(
$className
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
)
{
if
(
$this
->
filter
->
accept
(
$className
))
{
$this
->
next
->
decorate
(
$className
,
$node
,
$visitor
);
}
return
$this
;
}
}
Model/Decorator/InheritanceDecorator.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model\Decorator
;
use
Irstea\PlantUmlBundle\Model\ClassVisitor
;
use
Irstea\PlantUmlBundle\Model\ClassVisitorInterface
;
use
Irstea\PlantUmlBundle\Model\DecoratorInterface
;
use
Irstea\PlantUmlBundle\Model\NodeInterface
;
use
ReflectionClass
;
/**
* Description of InheritanceDecorator
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
InheritanceDecorator
implements
DecoratorInterface
{
public
function
decorate
(
$className
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
)
{
$class
=
new
ReflectionClass
(
$className
);
$parent
=
$class
->
getParentClass
();
$traits
=
$class
->
getTraitNames
();
$interfaces
=
$class
->
getInterfaceNames
();
$indirectInterfaces
=
array_filter
(
array_map
(
function
(
$i
)
{
return
$i
->
getInterfaceNames
();
},
$class
->
getInterfaces
()
)
);
if
(
!
empty
(
$indirectInterfaces
))
{
$indirectInterfaces
=
call_user_func_array
(
'array_merge'
,
$indirectInterfaces
);
$interfaces
=
array_diff
(
$interfaces
,
$indirectInterfaces
);
}
if
(
$parent
)
{
$traits
=
array_diff
(
$traits
,
$parent
->
getTraitNames
());
$interfaces
=
array_diff
(
$interfaces
,
$parent
->
getInterfaceNames
());
$this
->
visitRelations
(
$node
,
[
$parent
->
getName
()],
'Irstea\PlantUmlBundle\Model\Arrow\ExtendsClass'
,
$visitor
);
}
$this
->
visitRelations
(
$node
,
$interfaces
,
'Irstea\PlantUmlBundle\Model\Arrow\ImplementsInterface'
,
$visitor
);
$this
->
visitRelations
(
$node
,
$traits
,
'Irstea\PlantUmlBundle\Model\Arrow\UsesTrait'
,
$visitor
);
return
$this
;
}
protected
function
visitRelations
(
NodeInterface
$source
,
array
$classNames
,
$relationClass
,
ClassVisitorInterface
$visitor
)
{
foreach
(
$classNames
as
$className
)
{
$target
=
$visitor
->
visitClass
(
$className
);
if
(
$target
)
{
$source
->
addArrow
(
new
$relationClass
(
$source
,
$target
));
}
}
}
}
Model/Decorator/NullDecorator.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model\Decorator
;
use
Irstea\PlantUmlBundle\Model\ClassVisitorInterface
;
use
Irstea\PlantUmlBundle\Model\DecoratorInterface
;
use
Irstea\PlantUmlBundle\Model\NodeInterface
;
/**
* Description of NullDecorator
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
NullDecorator
implements
DecoratorInterface
{
use
\
Irstea\PlantUmlBundle\Utils\Singleton
;
public
function
decorate
(
$className
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
)
{
return
$this
;
}
}
Model/DecoratorInterface.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model
;
/**
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
interface
DecoratorInterface
{
public
function
decorate
(
$className
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
);
}
Model/Filter/AcceptAllFilter.php
View file @
051af78f
...
...
@@ -17,24 +17,10 @@ use Irstea\PlantUmlBundle\Model\ClassFilterInterface;
*/
class
AcceptAllFilter
implements
ClassFilterInterface
{
use
\
Irstea\PlantUmlBundle\Utils\Singleton
;
public
function
accept
(
$className
)
{
return
true
;
}
/**
* @var self
*/
static
private
$instance
;
/**
* @return self
*/
static
public
function
instance
()
{
if
(
!
static
::
$instance
)
{
static
::
$instance
=
new
static
();
}
return
static
::
$instance
;
}
}
Model/Orm/EntityVisitor.php
deleted
100644 → 0
View file @
709da3ad
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Model\Orm
;
use
Doctrine\ORM\Mapping\ClassMetadata
;
use
Irstea\PlantUmlBundle\Model\ClassVisitor
;
/**
* Description of Visitor
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
EntityVisitor
extends
ClassVisitor
{
/**
* @var ClassMetadata[]
*/
protected
$metadata
=
[];
public
function
__construct
(
array
$metadata
,
\
Irstea\PlantUmlBundle\Model\ClassFilterInterface
$filter
=
null
)
{
parent
::
__construct
(
$filter
);
foreach
(
$metadata
as
$md
)
{
/* @var $md ClassMetadata */
$this
->
metadata
[
$md
->
getReflectionClass
()
->
getName
()]
=
$md
;
}
}
public
function
doVisitClass
(
$className
)
{
if
(
isset
(
$this
->
metadata
[
$className
]))
{
return
$this
->
visitClassMetadata
(
$this
->
metadata
[
$className
]);
}
return
parent
::
doVisitClass
(
$className
);
}
/**
* @param ClassMetadata $metadata
* @return AbstractNode
*/
protected
function
visitClassMetadata
(
ClassMetadata
$metadata
)
{
return
$this
->
visitClassReflection
(
$metadata
->
getReflectionClass
());
}
}
Utils/Singleton.php
0 → 100644
View file @
051af78f
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Utils
;
/**
* Description of Singleton
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
trait
Singleton
{
/**
* @var self
*/
static
private
$instance
;
/**
* @return self
*/
static
public
function
instance
()
{
if
(
!
static
::
$instance
)
{
static
::
$instance
=
new
static
();
}
return
static
::
$instance
;
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment