Skip to content

Commit ab1fbed

Browse files
authored
Merge pull request #835 from dunglas/remove_dup
Introduce AbstractFilePropertyMetadatFactory to remove duplicated code.
2 parents 08eef57 + d91899e commit ab1fbed

File tree

5 files changed

+150
-235
lines changed

5 files changed

+150
-235
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the API Platform project.
5+
*
6+
* (c) Kévin Dunglas <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace ApiPlatform\Core\Metadata\Property\Factory;
13+
14+
use ApiPlatform\Core\Exception\InvalidArgumentException;
15+
use ApiPlatform\Core\Exception\PropertyNotFoundException;
16+
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
17+
18+
/**
19+
* Common base class to load properties's metadata from files.
20+
*
21+
* @author Kévin Dunglas <[email protected]>
22+
*
23+
* @internal
24+
*/
25+
abstract class AbstractFilePropertyMetadataFactory implements PropertyMetadataFactoryInterface
26+
{
27+
protected $paths;
28+
protected $decorated;
29+
30+
/**
31+
* @param string[] $paths
32+
* @param PropertyMetadataFactoryInterface|null $decorated
33+
*/
34+
public function __construct(array $paths, PropertyMetadataFactoryInterface $decorated = null)
35+
{
36+
$this->paths = $paths;
37+
$this->decorated = $decorated;
38+
}
39+
40+
/**
41+
* {@inheritdoc}
42+
*/
43+
public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata
44+
{
45+
$parentPropertyMetadata = null;
46+
if ($this->decorated) {
47+
try {
48+
$parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options);
49+
} catch (PropertyNotFoundException $propertyNotFoundException) {
50+
// Ignore not found exception from decorated factories
51+
}
52+
}
53+
54+
if (
55+
!property_exists($resourceClass, $property) ||
56+
empty($propertyMetadata = $this->getMetadata($resourceClass, $property))
57+
) {
58+
return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property);
59+
}
60+
61+
if ($parentPropertyMetadata) {
62+
return $this->update($parentPropertyMetadata, $propertyMetadata);
63+
}
64+
65+
return new PropertyMetadata(
66+
null,
67+
$propertyMetadata['description'],
68+
$propertyMetadata['readable'],
69+
$propertyMetadata['writable'],
70+
$propertyMetadata['readableLink'],
71+
$propertyMetadata['writableLink'],
72+
$propertyMetadata['required'],
73+
$propertyMetadata['identifier'],
74+
$propertyMetadata['iri'],
75+
null,
76+
$propertyMetadata['attributes']
77+
);
78+
}
79+
80+
/**
81+
* Extracts metadata from the XML tree.
82+
*
83+
* @param string $resourceClass
84+
* @param string $propertyName
85+
*
86+
* @throws InvalidArgumentException
87+
*
88+
* @return array
89+
*/
90+
abstract protected function getMetadata(string $resourceClass, string $propertyName): array;
91+
92+
/**
93+
* Returns the metadata from the decorated factory if available or throws an exception.
94+
*
95+
* @param PropertyMetadata|null $parentPropertyMetadata
96+
* @param string $resourceClass
97+
* @param string $property
98+
*
99+
* @throws PropertyNotFoundException
100+
*
101+
* @return PropertyMetadata
102+
*/
103+
private function handleNotFound(PropertyMetadata $parentPropertyMetadata = null, string $resourceClass, string $property): PropertyMetadata
104+
{
105+
if ($parentPropertyMetadata) {
106+
return $parentPropertyMetadata;
107+
}
108+
109+
throw new PropertyNotFoundException(sprintf('Property "%s" of the resource class "%s" not found.', $property, $resourceClass));
110+
}
111+
112+
/**
113+
* Creates a new instance of metadata if the property is not already set.
114+
*
115+
* @param PropertyMetadata $propertyMetadata
116+
* @param array $metadata
117+
*
118+
* @return PropertyMetadata
119+
*/
120+
private function update(PropertyMetadata $propertyMetadata, array $metadata): PropertyMetadata
121+
{
122+
$metadataAccessors = [
123+
'description' => 'get',
124+
'readable' => 'is',
125+
'writable' => 'is',
126+
'writableLink' => 'is',
127+
'readableLink' => 'is',
128+
'required' => 'is',
129+
'identifier' => 'is',
130+
'iri' => 'get',
131+
'attributes' => 'get',
132+
];
133+
134+
foreach ($metadataAccessors as $metadataKey => $accessorPrefix) {
135+
if (null === $metadata[$metadataKey] || null !== $propertyMetadata->{$accessorPrefix.ucfirst($metadataKey)}()) {
136+
continue;
137+
}
138+
139+
$propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]);
140+
}
141+
142+
return $propertyMetadata;
143+
}
144+
}

src/Metadata/Property/Factory/XmlPropertyMetadataFactory.php

Lines changed: 2 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -12,103 +12,21 @@
1212
namespace ApiPlatform\Core\Metadata\Property\Factory;
1313

1414
use ApiPlatform\Core\Exception\InvalidArgumentException;
15-
use ApiPlatform\Core\Exception\PropertyNotFoundException;
16-
use ApiPlatform\Core\Metadata\Property\PropertyMetadata;
1715
use Symfony\Component\Config\Util\XmlUtils;
1816

1917
/**
2018
* Creates a property metadata from XML {@see Property} configuration.
2119
*
2220
* @author Baptiste Meyer <[email protected]>
2321
*/
24-
class XmlPropertyMetadataFactory implements PropertyMetadataFactoryInterface
22+
final class XmlPropertyMetadataFactory extends AbstractFilePropertyMetadataFactory
2523
{
2624
const RESOURCE_SCHEMA = __DIR__.'/../../schema/metadata.xsd';
2725

28-
private $paths;
29-
private $decorated;
30-
31-
/**
32-
* @param string[] $paths
33-
* @param PropertyMetadataFactoryInterface|null $decorated
34-
*/
35-
public function __construct(array $paths, PropertyMetadataFactoryInterface $decorated = null)
36-
{
37-
$this->paths = $paths;
38-
$this->decorated = $decorated;
39-
}
40-
4126
/**
4227
* {@inheritdoc}
4328
*/
44-
public function create(string $resourceClass, string $property, array $options = []): PropertyMetadata
45-
{
46-
$parentPropertyMetadata = null;
47-
if ($this->decorated) {
48-
try {
49-
$parentPropertyMetadata = $this->decorated->create($resourceClass, $property, $options);
50-
} catch (PropertyNotFoundException $propertyNotFoundException) {
51-
// Ignore not found exception from decorated factories
52-
}
53-
}
54-
55-
if (
56-
!property_exists($resourceClass, $property) ||
57-
empty($propertyMetadata = $this->getMetadata($resourceClass, $property))
58-
) {
59-
return $this->handleNotFound($parentPropertyMetadata, $resourceClass, $property);
60-
}
61-
62-
if ($parentPropertyMetadata) {
63-
return $this->update($parentPropertyMetadata, $propertyMetadata);
64-
}
65-
66-
return new PropertyMetadata(
67-
null,
68-
$propertyMetadata['description'],
69-
$propertyMetadata['readable'],
70-
$propertyMetadata['writable'],
71-
$propertyMetadata['readableLink'],
72-
$propertyMetadata['writableLink'],
73-
$propertyMetadata['required'],
74-
$propertyMetadata['identifier'],
75-
$propertyMetadata['iri'],
76-
null,
77-
$propertyMetadata['attributes']
78-
);
79-
}
80-
81-
/**
82-
* Returns the metadata from the decorated factory if available or throws an exception.
83-
*
84-
* @param PropertyMetadata|null $parentPropertyMetadata
85-
* @param string $resourceClass
86-
* @param string $property
87-
*
88-
* @throws PropertyNotFoundException
89-
*
90-
* @return PropertyMetadata
91-
*/
92-
private function handleNotFound(PropertyMetadata $parentPropertyMetadata = null, string $resourceClass, string $property): PropertyMetadata
93-
{
94-
if ($parentPropertyMetadata) {
95-
return $parentPropertyMetadata;
96-
}
97-
98-
throw new PropertyNotFoundException(sprintf('Property "%s" of the resource class "%s" not found.', $property, $resourceClass));
99-
}
100-
101-
/**
102-
* Extracts metadata from the XML tree.
103-
*
104-
* @param string $resourceClass
105-
* @param string $propertyName
106-
*
107-
* @throws InvalidArgumentException
108-
*
109-
* @return array
110-
*/
111-
private function getMetadata(string $resourceClass, string $propertyName): array
29+
protected function getMetadata(string $resourceClass, string $propertyName): array
11230
{
11331
foreach ($this->paths as $path) {
11432
try {
@@ -166,37 +84,4 @@ private function getAttributes(\SimpleXMLElement $element): array
16684

16785
return $attributes;
16886
}
169-
170-
/**
171-
* Creates a new instance of metadata if the property is not already set.
172-
*
173-
* @param PropertyMetadata $propertyMetadata
174-
* @param array $metadata
175-
*
176-
* @return PropertyMetadata
177-
*/
178-
private function update(PropertyMetadata $propertyMetadata, array $metadata): PropertyMetadata
179-
{
180-
$metadataAccessors = [
181-
'description' => 'get',
182-
'readable' => 'is',
183-
'writable' => 'is',
184-
'writableLink' => 'is',
185-
'readableLink' => 'is',
186-
'required' => 'is',
187-
'identifier' => 'is',
188-
'iri' => 'get',
189-
'attributes' => 'get',
190-
];
191-
192-
foreach ($metadataAccessors as $metadataKey => $accessorPrefix) {
193-
if (null === $metadata[$metadataKey] || null !== $propertyMetadata->{$accessorPrefix.ucfirst($metadataKey)}()) {
194-
continue;
195-
}
196-
197-
$propertyMetadata = $propertyMetadata->{'with'.ucfirst($metadataKey)}($metadata[$metadataKey]);
198-
}
199-
200-
return $propertyMetadata;
201-
}
20287
}

src/Metadata/Property/Factory/XmlPropertyNameCollectionFactory.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
*
2222
* @author Baptiste Meyer <[email protected]>
2323
*/
24-
class XmlPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface
24+
final class XmlPropertyNameCollectionFactory implements PropertyNameCollectionFactoryInterface
2525
{
2626
const RESOURCE_SCHEMA = __DIR__.'/../../schema/metadata.xsd';
2727

0 commit comments

Comments
 (0)