Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Open sidebar
Pôle IS
Bundles Symfony 2
plantuml-bundle
Commits
de9253f1
Commit
de9253f1
authored
May 11, 2016
by
Guillaume Perréal
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactorisation de la création des graphs.
parent
7e3455bc
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
400 additions
and
282 deletions
+400
-282
Command/GenerateCommand.php
Command/GenerateCommand.php
+6
-276
DependencyInjection/IrsteaPlantUmlExtension.php
DependencyInjection/IrsteaPlantUmlExtension.php
+194
-2
Doctrine/AbstractDoctrineDecorator.php
Doctrine/AbstractDoctrineDecorator.php
+3
-2
Doctrine/DoctrineNamespace.php
Doctrine/DoctrineNamespace.php
+3
-1
Factory/FilterFactory.php
Factory/FilterFactory.php
+112
-0
Resources/config/services.yml
Resources/config/services.yml
+81
-0
composer.json
composer.json
+1
-1
No files found.
Command/GenerateCommand.php
View file @
de9253f1
...
...
@@ -6,48 +6,12 @@
*/
namespace
Irstea\PlantUmlBundle\Command
;
use
Doctrine\ORM\EntityManagerInterface
;
use
Irstea\PlantUmlBundle\Doctrine\AssociationDecorator
;
use
Irstea\PlantUmlBundle\Doctrine\DoctrineNamespace
;
use
Irstea\PlantUmlBundle\Doctrine\EntityDecorator
;
use
Irstea\PlantUmlBundle\Doctrine\EntityFinder
;
use
Irstea\PlantUmlBundle\Doctrine\FieldDecorator
;
use
Irstea\PlantUmlBundle\Finder\ClassFinder
;
use
Irstea\PlantUmlBundle\Finder\FilteringFinder
;
use
Irstea\PlantUmlBundle\Finder\FinderInterface
;
use
Irstea\PlantUmlBundle\Model\ClassFilterInterface
;
use
Irstea\PlantUmlBundle\Model\ClassVisitor
;
use
Irstea\PlantUmlBundle\Model\Decorator\AttributeDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\CompositeDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\FilteringDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\InheritanceDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\InterfaceDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\MethodDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\NullDecorator
;
use
Irstea\PlantUmlBundle\Model\Decorator\TraitDecorator
;
use
Irstea\PlantUmlBundle\Model\DecoratorInterface
;
use
Irstea\PlantUmlBundle\Model\Filter\AcceptAllFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\Composite\AllFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\NamespaceFilter
;
use
Irstea\PlantUmlBundle\Model\Graph
;
use
Irstea\PlantUmlBundle\Model\Namespace_\BundleNamespace
;
use
Irstea\PlantUmlBundle\Model\Namespace_\FlatNamespace
;
use
Irstea\PlantUmlBundle\Model\Namespace_\Php\RootNamespace
;
use
Irstea\PlantUmlBundle\Model\NamespaceInterface
;
use
Irstea\PlantUmlBundle\Writer\OutputWriter
;
use
ReflectionClass
;
use
Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand
;
use
Symfony\Component\Config\Definition\Exception\Exception
;
use
Symfony\Component\Console\Input\InputArgument
;
use
Symfony\Component\Console\Input\InputInterface
;
use
Symfony\Component\Console\Output\OutputInterface
;
use
Symfony\Component\Finder\Finder
;
use
Symfony\Component\Finder\SplFileInfo
;
use
Symfony\Component\HttpKernel\KernelInterface
;
use
Symfony\Component\Security\Core\Exception\InvalidArgumentException
;
use
Symfony\Component\Security\Core\Exception\RuntimeException
;
/**
* Description of ImportAffiliationCommand
...
...
@@ -56,21 +20,6 @@ use Symfony\Component\Security\Core\Exception\RuntimeException;
*/
class
GenerateCommand
extends
ContainerAwareCommand
{
/**
* @var string[]
*/
private
$bundles
;
/**
* @var KernelInterface
*/
private
$kernel
;
/**
* @var EntityManagerInterface
*/
private
$entityManager
;
protected
function
configure
()
{
$this
...
...
@@ -79,16 +28,6 @@ class GenerateCommand extends ContainerAwareCommand
->
addArgument
(
'graph'
,
InputArgument
::
REQUIRED
,
'Nom du graphe à générer'
);
}
protected
function
initialize
(
InputInterface
$input
,
OutputInterface
$output
)
{
parent
::
initialize
(
$input
,
$output
);
// @todo: DI
$this
->
bundles
=
$this
->
getContainer
()
->
getParameter
(
'kernel.bundles'
);
$this
->
kernel
=
$this
->
getContainer
()
->
get
(
'kernel'
);
$this
->
entityManager
=
$this
->
getContainer
()
->
get
(
'doctrine.orm.entity_manager'
);
}
/**
*
* @param InputInterface $input
...
...
@@ -99,224 +38,15 @@ class GenerateCommand extends ContainerAwareCommand
protected
function
execute
(
InputInterface
$input
,
OutputInterface
$output
)
{
$name
=
$input
->
getArgument
(
'graph'
);
$graphs
=
$this
->
getContainer
()
->
getParameter
(
'irstea_plant_uml.graphs'
);
if
(
!
isset
(
$graphs
[
$name
]))
{
$serviceId
=
"irstea_plant_uml.graph.
$name
"
;
if
(
!
$this
->
getContainer
()
->
has
(
$serviceId
))
{
throw
new
InvalidArgumentException
(
"Le graphe '
$name
' n'est pas défini."
);
}
$config
=
$graphs
[
$name
];
list
(
$finder
,
$filter
)
=
$this
->
buildFinder
(
$config
[
'sources'
]);
$graph
=
new
Graph
(
new
ClassVisitor
(
$this
->
buildDecorator
(
$config
[
'decoration'
],
$filter
),
$this
->
buildFilter
(
$config
[
'layout'
]),
$this
->
buildNamespace
(
$config
[
'layout'
][
'namespaces'
])
),
$finder
);
$graph
->
visitAll
();
$writer
=
new
OutputWriter
(
$output
);
$graph
=
$this
->
getContainer
()
->
get
(
$serviceId
);
$graph
->
visitAll
();
$graph
->
writeTo
(
$writer
);
}
/**
* @param array $config
* @return FinderInterface
*/
protected
function
buildFinder
(
array
$config
)
{
switch
(
$config
[
'type'
])
{
case
'entities'
:
$finder
=
$this
->
buildEntityFinder
(
$config
[
'entity_manager'
]);
break
;
case
'classes'
:
$finder
=
$this
->
buildClassFinder
(
$config
[
'directories'
]);
break
;
}
$filter
=
$this
->
buildFilter
(
$config
);
if
(
!
$filter
)
{
return
[
$finder
,
null
];
}
return
[
new
FilteringFinder
(
$finder
,
$filter
),
$filter
];
}
/**
* @param array $directories
* @return FinderInterface
*/
protected
function
buildClassFinder
(
array
$directories
)
{
return
new
ClassFinder
(
$this
->
parseDirectories
(
$directories
));
}
/**
* @param string $managerName
* @return FinderInterface
*/
protected
function
buildEntityFinder
(
$managerName
)
{
return
new
EntityFinder
(
$this
->
getContainer
()
->
get
(
'doctrine'
)
->
getManager
(
$managerName
)
);
}
/**
* @param array $config
* @return DecoratorInterface
* @throws RuntimeException
*/
protected
function
buildDecorator
(
array
$config
,
ClassFilterInterface
$defaultFilter
=
null
)
{
if
(
empty
(
$config
[
'decorators'
]))
{
return
NullDecorator
::
instance
();
}
$decorators
=
[];
foreach
(
$config
[
'decorators'
]
as
$type
)
{
$decorators
[]
=
$this
->
buildTypedDecorator
(
$type
);
}
if
(
count
(
$decorators
)
===
1
)
{
$decorator
=
$decorators
[
0
];
}
else
{
$decorator
=
new
CompositeDecorator
(
$decorators
);
}
$filter
=
$this
->
buildFilter
(
$config
)
?:
$defaultFilter
;
if
(
$filter
)
{
$decorator
=
new
FilteringDecorator
(
$decorator
,
$filter
);
}
return
$decorator
;
}
/**
* @param type $type
* @return DecoratorInterface
*/
protected
function
buildTypedDecorator
(
$type
)
{
switch
(
$type
)
{
case
'inheritance'
:
return
new
InheritanceDecorator
();
case
'interfaces'
:
return
new
InterfaceDecorator
();
case
'traits'
:
return
new
TraitDecorator
();
case
'attributes'
:
return
new
AttributeDecorator
();
case
'methods'
:
return
new
MethodDecorator
();
case
'entity'
:
return
new
EntityDecorator
(
$this
->
entityManager
->
getMetadataFactory
());
case
'associations'
:
return
new
AssociationDecorator
(
$this
->
entityManager
->
getMetadataFactory
());
case
'fields'
:
return
new
FieldDecorator
(
$this
->
entityManager
->
getMetadataFactory
());
default
:
return
NullDecorator
::
instance
();
}
}
/**
* @param string $config
* @return NamespaceInterface
*/
protected
function
buildNamespace
(
$config
)
{
switch
(
$config
)
{
case
'php'
:
return
new
RootNamespace
();
case
'flat'
:
return
new
FlatNamespace
();
case
'entities'
:
return
new
DoctrineNamespace
(
$this
->
entityManager
->
getConfiguration
()
->
getEntityNamespaces
());
case
'bundles'
:
return
new
BundleNamespace
(
$this
->
bundles
);
}
}
/**
* @param array $config
* @return ClassFilterInterface|null
*/
protected
function
buildFilter
(
array
$config
)
{
$filters
=
array_merge
(
isset
(
$config
[
'include'
])
?
$this
->
buildSubFilters
(
$config
[
'include'
],
false
)
:
[],
isset
(
$config
[
'exclude'
])
?
$this
->
buildSubFilters
(
$config
[
'exclude'
],
true
)
:
[]
);
switch
(
count
(
$filters
))
{
case
0
:
return
null
;
case
1
:
return
$filters
[
0
];
default
:
return
new
AllFilter
(
$filters
);
}
}
/**
* @param array $config
* @param boolean $notFound
* @return ClassFilterInterface|null
*/
protected
function
buildSubFilters
(
array
$config
,
$notFound
)
{
$filters
=
[];
if
(
!
empty
(
$config
[
'directories'
]))
{
$paths
=
$this
->
parseDirectories
(
$config
[
'directories'
]);
$filters
[]
=
new
DirectoryFilter
(
$paths
,
$notFound
);
}
if
(
!
empty
(
$config
[
'namespaces'
]))
{
$namespaces
=
$this
->
parseNamespaces
(
$config
[
'namespaces'
]);
$filters
[]
=
new
NamespaceFilter
(
$namespaces
,
$notFound
);
}
return
$filters
;
}
/**
* @param array $paths
* @return array
*/
protected
function
parseDirectories
(
array
$paths
)
{
$actualPaths
=
[];
foreach
(
$paths
as
$path
)
{
if
(
preg_match
(
'/^@(\w+)(.*)$/'
,
$path
,
$groups
))
{
$bundle
=
$this
->
kernel
->
getBundle
(
$groups
[
1
]);
$path
=
$bundle
->
getPath
()
.
$groups
[
2
];
}
$actualPaths
[]
=
realpath
(
$path
);
}
return
$actualPaths
;
}
/**
* @param array $paths
* @return array
*/
protected
function
parseNamespaces
(
array
$namespaces
)
{
$actualNamespaces
=
[];
foreach
(
$namespaces
as
$namespace
)
{
if
(
preg_match
(
'/^@(\w+)(.*)$/'
,
$namespace
,
$groups
))
{
$bundle
=
$this
->
kernel
->
getBundle
(
$groups
[
1
]);
$namespace
=
$bundle
->
getNamespace
()
.
$groups
[
2
];
}
$actualNamespaces
[]
=
$namespace
;
}
return
$actualNamespaces
;
}
}
\ No newline at end of file
}
DependencyInjection/IrsteaPlantUmlExtension.php
View file @
de9253f1
...
...
@@ -8,8 +8,18 @@
namespace
Irstea\PlantUmlBundle\DependencyInjection
;
use
Irstea\PlantUmlBundle\Doctrine\EntityFinder
;
use
Irstea\PlantUmlBundle\Finder\ClassFinder
;
use
Irstea\PlantUmlBundle\Finder\FilteringFinder
;
use
Irstea\PlantUmlBundle\Model\ClassVisitor
;
use
Irstea\PlantUmlBundle\Model\Graph
;
use
Symfony\Component\Config\FileLocator
;
use
Symfony\Component\DependencyInjection\ContainerBuilder
;
use
Symfony\Component\HttpKernel\DependencyInjection\Extension
;
use
Symfony\Component\DependencyInjection\Definition
;
use
Symfony\Component\DependencyInjection\DefinitionDecorator
;
use
Symfony\Component\DependencyInjection\Extension\Extension
;
use
Symfony\Component\DependencyInjection\Loader
;
use
Symfony\Component\DependencyInjection\Reference
;
/**
* Description of IrsteaPlantUmlExtension
...
...
@@ -20,10 +30,192 @@ class IrsteaPlantUmlExtension extends Extension
{
public
function
load
(
array
$configs
,
ContainerBuilder
$container
)
{
$loader
=
new
Loader\YamlFileLoader
(
$container
,
new
FileLocator
(
__DIR__
.
'/../Resources/config'
));
$loader
->
load
(
'services.yml'
);
$configuration
=
new
Configuration
();
$config
=
$this
->
processConfiguration
(
$configuration
,
$configs
);
$container
->
setParameter
(
'irstea_plant_uml.binaries'
,
$config
[
'binaries'
]);
$container
->
setParameter
(
'irstea_plant_uml.graphs'
,
$config
[
'graphs'
]);
foreach
(
$config
[
'graphs'
]
as
$key
=>
$graph
)
{
$this
->
loadGraph
(
$key
,
$graph
,
$container
);
}
}
public
function
loadGraph
(
$key
,
array
$config
,
ContainerBuilder
$container
)
{
$id
=
"irstea_plant_uml.graph.
$key
"
;
$emName
=
$config
[
'sources'
][
'entity_manager'
];
$em
=
new
Reference
(
"doctrine.orm.${emName}_entity_manager"
);
list
(
$source
,
$defaultFilter
)
=
$this
->
loadSources
(
$id
,
$em
,
$config
[
'sources'
],
$container
);
$visitor
=
$this
->
addService
(
$container
,
"
$id
.visitor"
,
ClassVisitor
::
class
,
[
$this
->
loadDecorator
(
$id
,
$em
,
$config
[
'decoration'
],
$defaultFilter
,
$container
),
$this
->
loadFilter
(
$id
,
$config
[
'layout'
],
$container
),
$this
->
loadNamespace
(
$id
,
$em
,
$config
[
'layout'
][
'namespaces'
],
$container
)
]
);
$container
->
setDefinition
(
$id
,
new
Definition
(
Graph
::
class
,
[
$visitor
,
$source
]))
->
setPublic
(
true
)
->
setLazy
(
true
);
}
/**
* @param string $id
* @param array $config
* @param ContainerBuilder $container
* @return Refernce[]
*/
protected
function
loadSources
(
$id
,
Reference
$em
,
array
$config
,
ContainerBuilder
$container
)
{
$finderId
=
"
$id
.finder"
;
$filter
=
$this
->
loadFilter
(
$finderId
,
$config
,
$container
);
if
(
$filter
)
{
$inner
=
$this
->
loadFinder
(
"
$finderId
.inner"
,
$em
,
$config
,
$container
);
$finder
=
$this
->
addService
(
$container
,
$finderId
,
FilteringFinder
::
class
,
[
$inner
,
$filter
]);
}
else
{
$finder
=
$this
->
loadFinder
(
$finderId
,
$em
,
$config
,
$container
);
}
return
[
$finder
,
$filter
];
}
/**
* @param string $id
* @param Reference $em
* @param array $config
* @param ContainerBuilder $container
* @return Reference
*/
protected
function
loadFinder
(
$id
,
Reference
$em
,
array
$config
,
ContainerBuilder
$container
)
{
switch
(
$config
[
'type'
])
{
case
'entities'
:
return
$this
->
addService
(
$container
,
$id
,
EntityFinder
::
class
,
[
$em
]);
case
'classes'
:
return
$this
->
addService
(
$container
,
$id
,
ClassFinder
::
class
,
[
$config
[
'directories'
]]);
}
}
/**
*
* @param string $id
* @param Reference $em
* @param array $config
* @param Reference $defaultFilter
* @param ContainerBuilder $container
* @return Reference
*/
protected
function
loadDecorator
(
$id
,
Reference
$em
,
array
$config
,
Reference
$defaultFilter
,
ContainerBuilder
$container
)
{
if
(
empty
(
$config
[
'decorators'
]))
{
return
new
Reference
(
'irstea.plant_uml.decorator.null'
);
}
$decoratorId
=
"
$id
.decorator"
;
$decorators
=
[];
foreach
(
$config
[
'decorators'
]
as
$i
=>
$type
)
{
$decorators
[]
=
$this
->
loadTypedDecorator
(
"
$decoratorId
.
$i
"
,
$em
,
$type
,
$container
);
}
if
(
count
(
$decorators
)
===
1
)
{
$container
->
setAlias
(
$decoratorId
,
"
$decoratorId
.0"
);
}
else
{
$container
->
setDefinition
(
$decoratorId
,
new
DefinitionDecorator
(
'irstea.plant_uml.decorator.composite.template'
))
->
replaceArgument
(
0
,
$decorators
);
}
$filter
=
$this
->
loadFilter
(
$decoratorId
,
$config
,
$container
)
?:
$defaultFilter
;
if
(
$filter
)
{
$container
->
setDefinition
(
"
$decoratorId
.decorator"
,
new
DefinitionDecorator
(
'irstea.plant_uml.decorator.filtered.template'
))
->
setDecoratedService
(
$decoratorId
,
"inner_decorator"
)
->
setArguments
([
new
Reference
(
"inner_decorator"
),
$filter
]);
}
return
new
Reference
(
$decoratorId
);
}
/**
* @param string $id
* @param Reference $em
* @param string $type
* @param ContainerBuilder $container
* @return Reference
*/
protected
function
loadTypedDecorator
(
$id
,
Reference
$em
,
$type
,
ContainerBuilder
$container
)
{
if
(
in_array
(
$type
,
[
'entity'
,
'associations'
,
'fields'
]))
{
$container
->
setDefinition
(
$id
,
new
DefinitionDecorator
(
"irstea.plant_uml.decorator.
$type
.template"
))
->
replaceArgument
(
0
,
$em
);
return
new
Reference
(
$id
);
}
return
new
Reference
(
"irstea.plant_uml.decorator.
$type
"
);
}
/**
* @param string $id
* @param Reference $em
* @param string $type
* @param ContainerBuilder $container
* @return Reference
*/
protected
function
loadNamespace
(
$id
,
Reference
$em
,
$type
,
ContainerBuilder
$container
)
{
if
(
$type
===
"entities"
)
{
$namespaceId
=
"
$id
.namespace"
;
$container
->
setDefinition
(
$namespaceId
,
new
DefinitionDecorator
(
'irstea.plant_uml.namespaces.entities.template'
))
->
replaceArgument
(
0
,
$em
);
return
new
Reference
(
$namespaceId
);
}
return
new
Reference
(
"irstea.plant_uml.namespaces.
$type
"
);
}
/**
* @param string $id
* @param array $config
* @param ContainerBuilder $container
* @return Reference
*/
protected
function
loadFilter
(
$id
,
array
$config
,
ContainerBuilder
$container
)
{
$filterId
=
"
$id
.filter"
;
$container
->
setDefinition
(
$filterId
,
new
DefinitionDecorator
(
"irstea.plant_uml.filter.template"
))
->
setArguments
([
isset
(
$config
[
'include'
])
?
$config
[
'include'
]
:
[],
isset
(
$config
[
'exclude'
])
?
$config
[
'exclude'
]
:
[],
]);
return
new
Reference
(
$filterId
);
}
/**
*
* @param ContainerBuilder $container
* @param string $id
* @param Definition $def
* @return Reference
*/
protected
function
addService
(
ContainerBuilder
$container
,
$id
,
$class
,
array
$arguments
=
[])
{
$container
->
setDefinition
(
$id
,
new
Definition
(
$class
,
$arguments
))
->
setPublic
(
false
);
return
new
Reference
(
$id
);
}
}
Doctrine/AbstractDoctrineDecorator.php
View file @
de9253f1
...
...
@@ -8,6 +8,7 @@
namespace
Irstea\PlantUmlBundle\Doctrine
;
use
Doctrine\ORM\EntityManagerInterface
;
use
Doctrine\ORM\Mapping\ClassMetadata
;
use
Doctrine\ORM\Mapping\ClassMetadataFactory
;
use
Irstea\PlantUmlBundle\Model\ClassVisitorInterface
;
...
...
@@ -27,9 +28,9 @@ abstract class AbstractDoctrineDecorator implements DecoratorInterface
*/
protected
$metadataFactory
;
public
function
__construct
(
ClassMetadataFactory
$metadataFactory
)
public
function
__construct
(
EntityManagerInterface
$manager
)
{
$this
->
metadataFactory
=
$metadataFactory
;
$this
->
metadataFactory
=
$m
anager
->
getM
etadataFactory
()
;
}
public
function
decorate
(
ReflectionClass
$class
,
NodeInterface
$node
,
ClassVisitorInterface
$visitor
)
...
...
Doctrine/DoctrineNamespace.php
View file @
de9253f1
...
...
@@ -17,8 +17,10 @@ class DoctrineNamespace extends \Irstea\PlantUmlBundle\Model\Namespace_\MappedNa
{
const
SEPARATOR
=
'::'
;
public
function
__construct
(
array
$entityNamespaces
)
public
function
__construct
(
\
Doctrine\ORM\EntityManagerInterface
$em
)
{
$entityNamespaces
=
$em
->
getConfiguration
()
->
getEntityNamespaces
();
$mapping
=
[];
foreach
(
$entityNamespaces
as
$alias
=>
$namespace
)
{
$mapping
[
$namespace
.
'\\'
]
=
$alias
.
'::'
;
...
...
Factory/FilterFactory.php
0 → 100644
View file @
de9253f1
<?php
/*
* © 2016 IRSTEA
* Guillaume Perréal <guillaume.perreal@irstea.fr>
* Tous droits réservés.
*/
namespace
Irstea\PlantUmlBundle\Factory
;
use
Irstea\PlantUmlBundle\Model\ClassFilterInterface
;
use
Irstea\PlantUmlBundle\Model\Filter\AcceptAllFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\Composite\AllFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\DirectoryFilter
;
use
Irstea\PlantUmlBundle\Model\Filter\NamespaceFilter
;
use
Symfony\Component\HttpKernel\KernelInterface
;
/**
* Description of FilterFactory
*
* @author Guillaume Perréal <guillaume.perreal@irstea.fr>
*/
class
FilterFactory
{
/**
* @var KernelInterface
*/
private
$kernel
;
public
function
__construct
(
KernelInterface
$kernel
)
{
$this
->
kernel
=
$kernel
;
}
/**
* @param array $include
* @param array $exclude
* @return ClassFilterInterface
*/
public
function
create
(
$include
=
[],
$exclude
=
[])
{
$filters
=
[];
if
(
!
empty
(
$include
))
{
$filters
[]
=
$this
->
createSubFilters
(
$include
,
false
);
}
if
(
!
empty
(
$exclude
))
{
$filters
[]
=
$this
->
createSubFilters
(
$exclude
,
true
);
}
$filters
=
array_merge
(
$filters
);