Passed
Push — master ( 8bd912...d93388 )
by Alan
06:58 queued 02:20
created

src/Metadata/Extractor/YamlExtractor.php (1 issue)

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
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Metadata\Extractor;
15
16
use ApiPlatform\Core\Exception\InvalidArgumentException;
17
use Symfony\Component\Yaml\Exception\ParseException;
18
use Symfony\Component\Yaml\Yaml;
19
20
/**
21
 * Extracts an array of metadata from a list of YAML files.
22
 *
23
 * @author Antoine Bluchet <[email protected]>
24
 * @author Baptiste Meyer <[email protected]>
25
 * @author Kévin Dunglas <[email protected]>
26
 */
27
final class YamlExtractor extends AbstractExtractor
28
{
29
    /**
30
     * {@inheritdoc}
31
     */
32
    protected function extractPath(string $path)
33
    {
34
        try {
35
            $resourcesYaml = Yaml::parse((string) file_get_contents($path), Yaml::PARSE_CONSTANT);
36
        } catch (ParseException $e) {
37
            $e->setParsedFile($path);
38
39
            throw new InvalidArgumentException($e->getMessage(), $e->getCode(), $e);
40
        }
41
42
        if (null === $resourcesYaml = $resourcesYaml['resources'] ?? $resourcesYaml) {
43
            return;
44
        }
45
46
        if (!\is_array($resourcesYaml)) {
47
            throw new InvalidArgumentException(sprintf('"resources" setting is expected to be null or an array, %s given in "%s".', \gettype($resourcesYaml), $path));
48
        }
49
50
        $this->extractResources($resourcesYaml, $path);
51
    }
52
53
    private function extractResources(array $resourcesYaml, string $path): void
54
    {
55
        foreach ($resourcesYaml as $resourceName => $resourceYaml) {
56
            $resourceName = $this->resolve($resourceName);
57
58
            if (null === $resourceYaml) {
59
                $resourceYaml = [];
60
            }
61
62
            if (!\is_array($resourceYaml)) {
63
                throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $resourceName, \gettype($resourceYaml), $path));
0 ignored issues
show
It seems like $resourceName can also be of type array and array; however, parameter $args of sprintf() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

63
                throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', /** @scrutinizer ignore-type */ $resourceName, \gettype($resourceYaml), $path));
Loading history...
64
            }
65
66
            $this->resources[$resourceName] = [
67
                'shortName' => $this->phpize($resourceYaml, 'shortName', 'string'),
68
                'description' => $this->phpize($resourceYaml, 'description', 'string'),
69
                'iri' => $this->phpize($resourceYaml, 'iri', 'string'),
70
                'itemOperations' => $resourceYaml['itemOperations'] ?? null,
71
                'collectionOperations' => $resourceYaml['collectionOperations'] ?? null,
72
                'subresourceOperations' => $resourceYaml['subresourceOperations'] ?? null,
73
                'graphql' => $resourceYaml['graphql'] ?? null,
74
                'attributes' => $resourceYaml['attributes'] ?? null,
75
            ];
76
77
            if (!isset($resourceYaml['properties'])) {
78
                $this->resources[$resourceName]['properties'] = null;
79
80
                continue;
81
            }
82
83
            if (!\is_array($resourceYaml['properties'])) {
84
                throw new InvalidArgumentException(sprintf('"properties" setting is expected to be null or an array, %s given in "%s".', \gettype($resourceYaml['properties']), $path));
85
            }
86
87
            $this->extractProperties($resourceYaml, $resourceName, $path);
88
        }
89
    }
90
91
    private function extractProperties(array $resourceYaml, string $resourceName, string $path): void
92
    {
93
        foreach ($resourceYaml['properties'] as $propertyName => $propertyValues) {
94
            if (null === $propertyValues) {
95
                $this->resources[$resourceName]['properties'][$propertyName] = null;
96
97
                continue;
98
            }
99
100
            if (!\is_array($propertyValues)) {
101
                throw new InvalidArgumentException(sprintf('"%s" setting is expected to be null or an array, %s given in "%s".', $propertyName, \gettype($propertyValues), $path));
102
            }
103
104
            $this->resources[$resourceName]['properties'][$propertyName] = [
105
                'description' => $this->phpize($propertyValues, 'description', 'string'),
106
                'readable' => $this->phpize($propertyValues, 'readable', 'bool'),
107
                'writable' => $this->phpize($propertyValues, 'writable', 'bool'),
108
                'readableLink' => $this->phpize($propertyValues, 'readableLink', 'bool'),
109
                'writableLink' => $this->phpize($propertyValues, 'writableLink', 'bool'),
110
                'required' => $this->phpize($propertyValues, 'required', 'bool'),
111
                'identifier' => $this->phpize($propertyValues, 'identifier', 'bool'),
112
                'iri' => $this->phpize($propertyValues, 'iri', 'string'),
113
                'attributes' => $propertyValues['attributes'] ?? [],
114
                'subresource' => $propertyValues['subresource'] ?? null,
115
            ];
116
        }
117
    }
118
119
    /**
120
     * Transforms a YAML attribute's value in PHP value.
121
     *
122
     * @throws InvalidArgumentException
123
     *
124
     * @return bool|string|null
125
     */
126
    private function phpize(array $array, string $key, string $type)
127
    {
128
        if (!isset($array[$key])) {
129
            return null;
130
        }
131
132
        switch ($type) {
133
            case 'bool':
134
                if (\is_bool($array[$key])) {
135
                    return $array[$key];
136
                }
137
                break;
138
            case 'string':
139
                if (\is_string($array[$key])) {
140
                    return $array[$key];
141
                }
142
                break;
143
        }
144
145
        throw new InvalidArgumentException(sprintf('The property "%s" must be a "%s", "%s" given.', $key, $type, \gettype($array[$key])));
146
    }
147
}
148