Passed
Pull Request — master (#9)
by Pavel
05:20
created

Routing/Loader/YamlLoader.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Bankiru\Api\Rpc\Routing\Loader;
4
5
use Bankiru\Api\Rpc\Routing\MethodCollection;
6
use Bankiru\Api\Rpc\Routing\Route;
7
use Symfony\Component\Config\Resource\FileResource;
8
use Symfony\Component\Yaml\Exception\ParseException;
9
use Symfony\Component\Yaml\Parser;
10
11
class YamlLoader extends FileLoader
12
{
13
    private static $availableKeys = [
14
        'resource',
15
        'type',
16
        'prefix',
17
        'method',
18
        'controller',
19
        'context',
20
        'default_context',
21
        'inherit',
22
    ];
23
24
    /** @var  Parser */
25
    private $parser;
26
27
    /**
28
     * Loads a resource.
29
     *
30
     * @param mixed       $resource The resource
31
     * @param string|null $type     The resource type or null if unknown
32
     *
33
     * @return MethodCollection
34
     * @throws \Exception If something went wrong
35
     */
36 2
    public function load($resource, $type = null)
37
    {
38 2
        $path = $this->getLocator()->locate($resource);
39
40 2
        if (!stream_is_local($path)) {
41
            throw new \InvalidArgumentException(sprintf('This is not a local file "%s".', $path));
42
        }
43
44 2
        if (!file_exists($path)) {
45
            throw new \InvalidArgumentException(sprintf('File "%s" not found.', $path));
46
        }
47
48 2
        if (null === $this->parser) {
49 2
            $this->parser = new Parser();
50 2
        }
51
52
        try {
53 2
            $parsedConfig = $this->parser->parse(file_get_contents($path));
54 2
        } catch (ParseException $e) {
55
            throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e);
56
        }
57
58 2
        $collection = new MethodCollection();
59 2
        $collection->addResource(new FileResource($path));
60
61
        // empty file
62 2
        if (null === $parsedConfig) {
63
            return $collection;
64
        }
65
66
        // not an array
67 2
        if (!is_array($parsedConfig)) {
68
            throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path));
69
        }
70
71 2
        foreach ($parsedConfig as $name => $config) {
72 2
            $this->validate($config, $name, $path);
73
74 2
            if (isset($config['resource'])) {
75 2
                $this->parseImport($collection, $config, $path, $resource);
76 2
            } else {
77 2
                $this->parseRoute($collection, $name, $config, $path);
78
            }
79 2
        }
80
81 2
        return $collection;
82
    }
83
84
    /**
85
     * Returns whether this class supports the given resource.
86
     *
87
     * @param mixed       $resource A resource
88
     * @param string|null $type     The resource type or null if unknown
89
     *
90
     * @return bool True if this class supports the given resource, false otherwise
91
     */
92 2
    public function supports($resource, $type = null)
93
    {
94 2
        return is_string($resource) &&
95 2
               in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true) &&
96 2
               (!$type || 'yaml' === $type);
97
    }
98
99
    /**
100
     * Validates the route configuration.
101
     *
102
     * @param array  $config A resource config
103
     * @param string $name   The config key
104
     * @param string $path   The loaded file path
105
     *
106
     * @return array
107
     * @throws \InvalidArgumentException If one of the provided config keys is not supported,
108
     *                                   something is missing or the combination is nonsense
109
     */
110 2
    protected function validate($config, $name, $path)
111
    {
112 2
        if (!is_array($config)) {
113
            throw new \InvalidArgumentException(
114
                sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)
115
            );
116
        }
117 2
        if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) {
118
            throw new \InvalidArgumentException(
119
                sprintf(
120
                    'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".',
121
                    $path,
122
                    $name,
123
                    implode('", "', $extraKeys),
124
                    implode('", "', self::$availableKeys)
125
                )
126
            );
127
        }
128 2 View Code Duplication
        if (isset($config['resource']) && isset($config['method'])) {
129
            throw new \InvalidArgumentException(
130
                sprintf(
131
                    'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". ' .
132
                    'Choose between an import and a route definition.',
133
                    $path,
134
                    $name
135
                )
136
            );
137
        }
138 2 View Code Duplication
        if (!isset($config['resource']) && isset($config['type'])) {
139
            throw new \InvalidArgumentException(
140
                sprintf(
141
                    'The "type" key for the route definition "%s" in "%s" is unsupported. ' .
142
                    'It is only available for imports in combination with the "resource" key.',
143
                    $name,
144
                    $path
145
                )
146
            );
147
        }
148 2
    }
149
150
    /**
151
     * Parses an import and adds the routes in the resource to the RouteCollection.
152
     *
153
     * @param MethodCollection $collection A RouteCollection instance
154
     * @param array            $config     Route definition
155
     * @param string           $path       Full path of the YAML file being processed
156
     * @param string           $file       Loaded file name
157
     */
158 2
    protected function parseImport(MethodCollection $collection, array $config, $path, $file)
159
    {
160 2
        $type   = isset($config['type']) ? $config['type'] : null;
161 2
        $prefix = isset($config['prefix']) ? $config['prefix'] : '';
162 2
        $this->setCurrentDir(dirname($path));
163
164 2
        $subCollection = $this->import($config['resource'], $type, false, $file);
165
        /* @var $subCollection MethodCollection */
166 2
        $subCollection->addPrefix($prefix);
167
168 2
        if (array_key_exists('context', $config)) {
169 2
            foreach ((array)$config['context'] as $context) {
170 2
                $subCollection->addContext($context);
171 2
            }
172 2
        }
173
174 2
        $collection->addCollection($subCollection);
175 2
    }
176
177
    /**
178
     * Parses a route and adds it to the RouteCollection.
179
     *
180
     * @param MethodCollection $collection A RouteCollection instance
181
     * @param string           $name       Route name
182
     * @param array            $config     Route definition
183
     * @param string           $path       Full path of the YAML file being processed
184
     */
185 2
    protected function parseRoute(MethodCollection $collection, $name, array $config, $path)
0 ignored issues
show
The parameter $path is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
186
    {
187 2
        $context = array_key_exists('context', $config) ? (array)$config['context'] : [];
188 2
        $method  = array_key_exists('method', $config) ? $config['method'] : $name;
189 2
        $inherit = array_key_exists('inherit', $config) ? $config['inherit'] : true;
190 2
        $route   = new Route(
191 2
            $method,
192 2
            $config['controller'],
193 2
            $context,
194 2
            array_key_exists('default_context', $config) ? $config['default_context'] : true,
195
            $inherit
196 2
        );
197
198 2
        $collection->add($name, $route);
199 2
    }
200
}
201