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
ng-model-generator-bundle
Commits
f3ee1892
Commit
f3ee1892
authored
Sep 14, 2018
by
Guillaume Perréal
Browse files
Amélioration de la vérification des ressources et des IRI.
parent
846f449e
Changes
14
Hide whitespace changes
Inline
Side-by-side
src/Metadata/MetadataFactory.php
View file @
f3ee1892
...
...
@@ -138,6 +138,12 @@ final class MetadataFactory implements MetadataFactoryInterface
$metadata
->
getShortName
(),
$metadata
->
getDescription
(),
$classMeta
->
isAbstract
(),
$this
->
getOperationSerialization
(
null
,
$class
,
true
,
$metadata
->
getAttribute
(
'normalization_context'
,
[])[
'groups'
]
??
[]
),
$this
->
getOperations
(
$class
)
);
}
...
...
@@ -298,16 +304,21 @@ final class MetadataFactory implements MetadataFactoryInterface
/**
* @parma string $operationName
*
* @param PHPClass $class
* @param bool $normalization
* @param string[] $groups
* @param OperationDef|null $opDef
* @param PHPClass $class
* @param bool $normalization
* @param string[] $groups
*
* @throws \ApiPlatform\Core\Exception\PropertyNotFoundException
* @throws \ApiPlatform\Core\Exception\ResourceClassNotFoundException
* @throws \ReflectionException
*
* @return SerializationMetadata
*/
private
function
getOperationSerialization
(
OperationDef
$opDef
,
PHPClass
$class
,
bool
$normalization
,
array
$groups
):
SerializationMetadata
private
function
getOperationSerialization
(
?
OperationDef
$opDef
,
PHPClass
$class
,
bool
$normalization
,
array
$groups
):
SerializationMetadata
{
sort
(
$groups
);
$key
=
sprintf
(
'%s:%d:%s:%s'
,
$class
->
getFullName
(),
$normalization
,
$opDef
->
getName
(),
implode
(
'+'
,
$groups
));
$key
=
sprintf
(
'%s:%d:%s:%s'
,
$class
->
getFullName
(),
$normalization
,
$opDef
?
$opDef
->
getName
()
:
'_Default_'
,
implode
(
'+'
,
$groups
));
if
(
!
isset
(
$this
->
serializations
[
$key
]))
{
$this
->
serializations
[
$key
]
=
$this
->
doGetSerialization
(
$class
,
$normalization
,
$opDef
,
$groups
);
}
...
...
@@ -327,9 +338,9 @@ final class MetadataFactory implements MetadataFactoryInterface
*
* @return SerializationMetadata
*/
private
function
doGetSerialization
(
PHPClass
$class
,
bool
$normalization
,
OperationDef
$opDef
,
array
$groups
):
SerializationMetadata
private
function
doGetSerialization
(
PHPClass
$class
,
bool
$normalization
,
?
OperationDef
$opDef
,
array
$groups
):
SerializationMetadata
{
$selfNamePrefix
=
Inflector
::
classify
(
$opDef
->
getName
());
$selfNamePrefix
=
$opDef
?
Inflector
::
classify
(
$opDef
->
getName
())
:
implode
(
''
,
$groups
)
;
$otherNamePrefix
=
$selfNamePrefix
.
$class
->
getBaseName
();
if
(
$normalization
)
{
...
...
@@ -340,9 +351,9 @@ final class MetadataFactory implements MetadataFactoryInterface
$selfNamePrefix
=
''
;
}
$propFilter
=
'filterGetProperty'
;
}
elseif
(
$opDef
->
isCreateItem
())
{
}
elseif
(
$opDef
&&
$opDef
->
isCreateItem
())
{
$propFilter
=
'filterCreateProperty'
;
}
elseif
(
$opDef
->
isUpdateItem
())
{
}
elseif
(
$opDef
&&
$opDef
->
isUpdateItem
())
{
$propFilter
=
'filterUpdateProperty'
;
}
else
{
$propFilter
=
'filterAnyProperty'
;
...
...
src/Metadata/PropertyMetadata.php
View file @
f3ee1892
...
...
@@ -35,7 +35,8 @@ class PropertyMetadata implements \JsonSerializable
/** @var Type */
private
$type
;
/** @var bool */
private
$identifier
;
/** @var bool */
private
$identifier
;
/** @var bool */
private
$readable
;
...
...
@@ -201,13 +202,26 @@ class PropertyMetadata implements \JsonSerializable
*/
private
function
serializeType
(
?Type
$type
)
{
return
$type
?
[
'builtin_type'
=>
$type
->
getBuiltinType
(),
'class_name'
=>
$type
->
getClassName
(),
'nullable'
=>
$type
->
isNullable
(),
'collection'
=>
$type
->
isCollection
(),
'collection_key_type'
=>
$this
->
serializeType
(
$type
->
getCollectionKeyType
()),
'collection_value_type'
=>
$this
->
serializeType
(
$type
->
getCollectionValueType
()),
]
:
null
;
if
(
!
$type
)
{
return
null
;
}
if
(
$type
->
getCollectionValueType
())
{
return
[
'key_type'
=>
$this
->
serializeType
(
$type
->
getCollectionKeyType
()),
'value_type'
=>
$this
->
serializeType
(
$type
->
getCollectionValueType
()),
'nullable'
=>
$type
->
isNullable
(),
];
}
if
(
$type
->
getClassName
())
{
return
[
'class_name'
=>
$type
->
getClassName
(),
'nullable'
=>
$type
->
isNullable
(),
];
}
return
[
'builtin_type'
=>
$type
->
getBuiltinType
(),
'nullable'
=>
$type
->
isNullable
(),
];
}
}
src/Metadata/ResourceMetadata.php
View file @
f3ee1892
...
...
@@ -41,15 +41,21 @@ class ResourceMetadata implements \JsonSerializable
/** @var OperationMetadata[] */
private
$operations
=
[];
/**
* @var SerializationMetadata
*/
private
$defaultNormalization
;
/**
* ResourceMetadata constructor.
*
* @param PHPClass $class
* @param PHPClass|null $parentClass
* @param string $shortName
* @param string $description
* @param bool $abstract
* @param OperationMetadata[] $operations
* @param PHPClass $class
* @param PHPClass|null $parentClass
* @param string $shortName
* @param string $description
* @param bool $abstract
* @param SerializationMetadata $defaultNormalization
* @param OperationMetadata[] $operations
*/
public
function
__construct
(
PHPClass
$class
,
...
...
@@ -57,12 +63,14 @@ class ResourceMetadata implements \JsonSerializable
string
$shortName
,
string
$description
,
bool
$abstract
,
SerializationMetadata
$defaultNormalization
,
array
$operations
)
{
$this
->
class
=
$class
;
$this
->
parentClass
=
$parentClass
;
$this
->
abstract
=
$abstract
;
$this
->
description
=
$description
;
$this
->
defaultNormalization
=
$defaultNormalization
;
foreach
(
$operations
as
$operation
)
{
$this
->
operations
[
$operation
->
getName
()
.
$operation
->
getType
()]
=
$operation
->
withResource
(
$this
);
...
...
@@ -130,6 +138,16 @@ class ResourceMetadata implements \JsonSerializable
return
$this
->
abstract
;
}
/**
* Get class.
*
* @return PHPClass
*/
public
function
getClass
():
PHPClass
{
return
$this
->
class
;
}
/**
* Get operations.
*
...
...
@@ -140,6 +158,16 @@ class ResourceMetadata implements \JsonSerializable
return
$this
->
operations
;
}
/**
* Get defaultNormalization.
*
* @return SerializationMetadata
*/
public
function
getDefaultNormalization
():
SerializationMetadata
{
return
$this
->
defaultNormalization
;
}
/**
* {@inheritdoc}
*/
...
...
src/Metadata/SerializationMetadata.php
View file @
f3ee1892
...
...
@@ -138,6 +138,22 @@ final class SerializationMetadata implements \JsonSerializable
return
$this
->
normalization
;
}
/**
* @return PHPClass[]
*/
public
function
getRootSubClasses
():
array
{
$subclasses
=
[];
$rootClassName
=
$this
->
getRoot
()
->
getFullName
();
foreach
(
$this
->
representations
as
$className
=>
$meta
)
{
if
(
\
is_subclass_of
(
$className
,
$rootClassName
,
true
))
{
$subclasses
[
$className
]
=
PHPClass
::
get
(
$className
);
}
}
return
$subclasses
;
}
/**
* {@inheritdoc}
*/
...
...
src/ModelGenerator.php
View file @
f3ee1892
...
...
@@ -33,6 +33,7 @@ use Irstea\NgModelGeneratorBundle\Models\Types\BuiltinType;
use
Irstea\NgModelGeneratorBundle\Models\Types\Objects\InterfaceType
;
use
Irstea\NgModelGeneratorBundle\Models\Types\Objects\Property
;
use
Irstea\NgModelGeneratorBundle\Models\Types\Objects\Repository
;
use
Irstea\NgModelGeneratorBundle\Models\Types\Reference
;
use
Irstea\NgModelGeneratorBundle\Models\Types\Resources\UUID
;
use
Irstea\NgModelGeneratorBundle\Models\Types\Type
;
use
Symfony\Component\PropertyInfo\Type
as
PHPType
;
...
...
@@ -103,9 +104,9 @@ final class ModelGenerator
{
$this
->
typeFactory
=
$this
->
createTypeFactory
();
[
$repos
itories
,
$iriPatterns
]
=
$this
->
extractRepositories
();
$repos
=
$this
->
extractRepositories
();
$declarations
=
$this
->
extractDeclarations
(
$repos
itories
);
$declarations
=
$this
->
extractDeclarations
(
$repos
);
return
$this
->
twigEnv
->
render
(
'@NgModelGenerator/typescript_models.ts.twig'
,
...
...
@@ -113,10 +114,13 @@ final class ModelGenerator
'title'
=>
$this
->
documentation
->
getTitle
(),
'version'
=>
$this
->
documentation
->
getVersion
(),
'description'
=>
$this
->
documentation
->
getDescription
()
?:
''
,
'resources'
=>
array_keys
(
$iriPatterns
),
'repositories'
=>
$repositories
,
'repositories'
=>
array_filter
(
$declarations
,
function
(
Declaration
$d
)
{
return
$d
instanceof
Repository
;
}
),
'declarations'
=>
$declarations
,
'iriPatterns'
=>
$iriPatterns
,
]
);
}
...
...
@@ -204,50 +208,65 @@ final class ModelGenerator
}
/**
* @return
array
* @return
Repository[]
*/
private
function
extractRepositories
():
array
{
$repositories
=
[];
$iriPatterns
=
[];
/**
* @var PHPClass
* @var ResourceMetadata $resourceMeta
*/
foreach
(
$this
->
getResourceMetadata
()
as
$class
=>
$resourceMeta
)
{
// printf("\n\n===================================\n\n%s\n", \json_encode($resourceMeta, \JSON_PRETTY_PRINT));
// continue;
$repoName
=
$resourceMeta
->
getShortName
()
.
'Repository'
;
$repositories
[
$repoName
]
=
$this
->
typeFactory
->
getOrCreate
(
$repoName
,
function
()
use
(
$resourceMeta
):
Type
{
return
$this
->
buildRepositories
(
$resourceMeta
);
}
);
}
function
()
use
(
$resourceMeta
,
&
$iriPatterns
):
Type
{
$operations
=
[];
ksort
(
$repositories
);
foreach
(
$resourceMeta
->
getOperations
()
as
$operation
)
{
$mapper
=
new
OperationMapper
(
$this
->
typeFactory
,
$operation
);
$operations
[]
=
$operation
=
$mapper
();
return
$repositories
;
}
if
(
$operation
->
getName
()
===
'get'
)
{
$iriPatterns
[
$resourceMeta
->
getShortName
()]
=
$operation
->
getPath
();
}
}
/**
* @param ResourceMetadata $resourceMeta
*
* @return Repository
*/
private
function
buildRepositories
(
ResourceMetadata
$resourceMeta
):
Repository
{
$operations
=
[];
$iri
=
null
;
return
new
Repository
(
$resourceMeta
->
getShortName
(),
$operations
);
}
);
foreach
(
$resourceMeta
->
getOperations
()
as
$operation
)
{
$mapper
=
new
OperationMapper
(
$this
->
typeFactory
,
$operation
);
$operations
[]
=
$op
=
$mapper
();
if
(
$operation
->
getOpDef
()
->
isGetItem
())
{
$iri
=
$op
->
getPath
();
}
}
ksort
(
$repositories
);
ksort
(
$iriPatterns
);
$resourceRepr
=
$resourceMeta
->
getDefaultNormalization
()
->
getRepresentationOf
(
$resourceMeta
->
getClass
());
return
[
$repositories
,
$iriPatterns
];
/** @var InterfaceType $resourceType */
$resourceType
=
Reference
::
resolveAs
(
$this
->
typeFactory
->
get
(
$resourceRepr
->
getName
()),
InterfaceType
::
class
);
return
new
Repository
(
$resourceMeta
->
getClass
(),
$operations
,
$resourceType
,
$iri
);
}
/**
...
...
src/Models/ClassInfo.php
0 → 100644
View file @
f3ee1892
<?php
declare
(
strict_types
=
1
);
/*
* irstea/ng-model-generator-bundle generates Typescript interfaces for Angular using api-platform metadata.
* Copyright (C) 2018 IRSTEA
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License and the GNU
* Lesser General Public License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
namespace
Irstea\NgModelGeneratorBundle\Models
;
use
Irstea\NgModelGeneratorBundle\Metadata\PropertyMetadata
;
/**
* Class ClassInfo.
*/
final
class
ClassInfo
implements
\
JsonSerializable
{
public
const
UNDEFINED
=
'UNDEFINED'
;
public
const
EMBEDDED
=
'EMBEDDED'
;
public
const
IRI
=
'IRI'
;
public
const
UNION
=
'UNION'
;
public
const
INTERFACE
=
'INTERFACE'
;
/** @var PHPClass */
private
$resource
;
/** @var ClassInfo|null */
private
$parent
;
/** @var PropertyMetadata[] */
private
$properties
;
/** @var ClassInfo[] */
private
$children
=
[];
/** @var int */
private
$refCount
=
0
;
/** @var string */
private
$type
=
self
::
UNDEFINED
;
/**
* ClassInfo constructor.
*
* @param PHPClass $resource
* @param PropertyMetadata[] $properties
*/
public
function
__construct
(
PHPClass
$resource
,
array
$properties
=
[]
)
{
$this
->
resource
=
$resource
;
$this
->
properties
=
$properties
;
}
public
function
destroy
():
void
{
$this
->
setType
(
self
::
UNDEFINED
);
}
/**
* Get resource.
*
* @return PHPClass
*/
public
function
getResource
():
PHPClass
{
return
$this
->
resource
;
}
/**
* Get properties.
*
* @return PropertyMetadata[]
*/
public
function
getProperties
():
array
{
return
$this
->
properties
;
}
/**
* Get parent.
*
* @return ClassInfo|null
*/
public
function
getParent
():
?ClassInfo
{
return
$this
->
parent
;
}
/**
* Set parent.
*
* @param ClassInfo|null $parent
*/
public
function
setParent
(
?ClassInfo
$parent
):
void
{
if
(
$parent
===
$this
->
parent
)
{
return
;
}
$oldParent
=
$this
->
parent
;
$this
->
parent
=
$parent
;
if
(
$oldParent
)
{
$oldParent
->
removeChild
(
$this
);
}
if
(
$parent
)
{
$parent
->
addChild
(
$this
);
}
}
/**
* Get children.
*
* @return ClassInfo[]
*/
public
function
getChildren
():
array
{
return
$this
->
children
;
}
/**
* @param ClassInfo $child
*/
public
function
addChild
(
ClassInfo
$child
):
void
{
if
(
\
in_array
(
$child
,
$this
->
children
,
true
))
{
return
;
}
$this
->
children
[]
=
$child
;
$child
->
setParent
(
$this
);
}
/**
* @param ClassInfo $child
*/
public
function
removeChild
(
ClassInfo
$child
):
void
{
$key
=
\
array_search
(
$child
,
$this
->
children
,
true
);
if
(
$key
===
false
)
{
return
;
}
unset
(
$this
->
children
[
$key
]);
$child
->
setParent
(
null
);
}
/**
* @param int $amount
*/
public
function
incRefCount
(
int
$amount
=
1
):
void
{
$this
->
refCount
+=
$amount
;
foreach
(
$this
->
children
as
$child
)
{
$child
->
incRefCount
(
$amount
);
}
}
/**
* @param int $threshold
*
* @return bool
*/
public
function
isRefCountAbove
(
int
$threshold
):
bool
{
return
$this
->
refCount
>
$threshold
;
}
/**
* Test type.
*
* @param string $type
*/
public
function
isType
(
string
$type
):
bool
{
return
$this
->
type
===
$type
;
}
/**
* Set type.
*
* @param string $type
*/
public
function
setType
(
string
$type
):
void
{
$this
->
type
=
$type
;
if
(
$type
!==
self
::
INTERFACE
&&
$type
!==
self
::
UNION
)
{
foreach
(
$this
->
children
as
$child
)
{
$child
->
setParent
(
$this
->
parent
);
}
}
if
(
$type
!==
self
::
INTERFACE
)
{
if
(
$this
->
parent
)
{
$this
->
setParent
(
null
);
}
}
}
/**
* @return bool
*/
public
function
isInterface
():
bool
{
return
$this
->
isType
(
self
::
INTERFACE
);
}
/**
* @return bool
*/
public
function
isUnion
():
bool
{
return
$this
->
isType
(
self
::
UNION
);
}
/**
* @return bool
*/
public
function
isEmbedded
():
bool
{
return
$this
->
isType
(
self
::
EMBEDDED
);
}
/**
* @return bool
*/
public
function
isUndefined
():
bool
{
return
$this
->
isType
(
self
::
UNDEFINED
);
}
/**
* @return bool
*/
public
function
isIRI
():
bool
{
return
$this
->
isType
(
self
::
IRI
);
}
/**
* @return \Generator
*/
public
function
iterateDescendants
(
?string
$typeFilter
):
\
Generator
{
foreach
(
$this
->
children
as
$child
)
{
if
(
!
$typeFilter
||
$child
->
isType
(
$typeFilter
))
{
yield
$child
->
getResource
()
=>
$child
;
}
yield
from
$child
->
iterateDescendants
(
$typeFilter
);
}
}
/**
* {@inheritdoc}
*/
public
function
jsonSerialize
()
{
return
[
'resource'
=>
$this
->
resource
,
'refCount'
=>
$this
->
refCount
,
'type'
=>
$this
->
type
,
'parent'
=>
$this
->
parent
?
$this
->
parent
->
getResource
()
:
null
,
'children'
=>
array_map
(
function
(
ClassInfo
$ci
)
{
return
$ci
->
getResource
();
},
$this
->
children
),
'properties'
=>
$this
->
properties
,
];
}
}
src/Models/Types/Objects/InterfaceType.php
View file @
f3ee1892
...
...
@@ -43,10 +43,15 @@ class InterfaceType extends AbstractHierarchicalObject
/** @var Property $property */
foreach
(
$this
->
getProperties
()
as
$property
)
{
if
(
!
$property
->
isNullable
())
{
$tests
[]
=
sprintf
(
'%s in %s'
,
TypescriptHelper
::
quoteString
(
$property
->
getName
()),
$expr
);
$tests
[]
=
sprintf
(
'(%s in %s && %s)'
,
TypescriptHelper
::
quoteString
(
$property
->
getName
()),
$expr
,
$property
->
getType
()
->
checkType
(
$property
->
getUsage
(
$expr
))
);