Completed
Push — 3.x ( d1adb1...66933d )
by Grégoire
03:32
created

RouteCollection::add()   B

Complexity

Conditions 7
Paths 20

Size

Total Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 37
rs 8.3946
c 0
b 0
f 0
cc 7
nc 20
nop 9

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Sonata Project package.
7
 *
8
 * (c) Thomas Rabaix <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Sonata\AdminBundle\Route;
15
16
use Symfony\Component\Routing\Route;
17
18
/**
19
 * @final since sonata-project/admin-bundle 3.52
20
 *
21
 * @author Thomas Rabaix <[email protected]>
22
 */
23
class RouteCollection
24
{
25
    /**
26
     * @var Route[]
27
     */
28
    protected $elements = [];
29
30
    /**
31
     * @var string
32
     */
33
    protected $baseCodeRoute;
34
35
    /**
36
     * @var string
37
     */
38
    protected $baseRouteName;
39
40
    /**
41
     * @var string
42
     */
43
    protected $baseControllerName;
44
45
    /**
46
     * @var string
47
     */
48
    protected $baseRoutePattern;
49
50
    /**
51
     * @var Route[]
52
     */
53
    private $cachedElements = [];
54
55
    /**
56
     * @param string $baseCodeRoute
57
     * @param string $baseRouteName
58
     * @param string $baseRoutePattern
59
     * @param string $baseControllerName
60
     */
61
    public function __construct($baseCodeRoute, $baseRouteName, $baseRoutePattern, $baseControllerName)
62
    {
63
        $this->baseCodeRoute = $baseCodeRoute;
64
        $this->baseRouteName = $baseRouteName;
65
        $this->baseRoutePattern = $baseRoutePattern;
66
        $this->baseControllerName = $baseControllerName;
67
    }
68
69
    /**
70
     * Add route.
71
     *
72
     * @param string $name
73
     * @param string $pattern   Pattern (will be automatically combined with @see $this->baseRoutePattern and $name
74
     * @param string $host
75
     * @param string $condition
76
     *
77
     * @return RouteCollection
78
     */
79
    public function add(
80
        $name,
81
        $pattern = null,
82
        array $defaults = [],
83
        array $requirements = [],
84
        array $options = [],
85
        $host = '',
86
        array $schemes = [],
87
        array $methods = [],
88
        $condition = ''
89
    ) {
90
        $pattern = $this->baseRoutePattern.'/'.($pattern ?: $name);
91
        $code = $this->getCode($name);
92
        $routeName = $this->baseRouteName.'_'.$name;
93
94
        if (!isset($defaults['_controller'])) {
95
            $actionJoiner = false === strpos($this->baseControllerName, '\\') ? ':' : '::';
96
            if (':' !== $actionJoiner && false !== strpos($this->baseControllerName, ':')) {
97
                $actionJoiner = ':';
98
            }
99
100
            $defaults['_controller'] = $this->baseControllerName.$actionJoiner.$this->actionify($code);
101
        }
102
103
        if (!isset($defaults['_sonata_admin'])) {
104
            $defaults['_sonata_admin'] = $this->baseCodeRoute;
105
        }
106
107
        $defaults['_sonata_name'] = $routeName;
108
109
        $element = static function () use ($pattern, $defaults, $requirements, $options, $host, $schemes, $methods, $condition) {
110
            return new Route($pattern, $defaults, $requirements, $options, $host, $schemes, $methods, $condition);
111
        };
112
        $this->addElement($code, $element);
113
114
        return $this;
115
    }
116
117
    /**
118
     * @param string $name
119
     *
120
     * @return string
121
     */
122
    public function getCode($name)
123
    {
124
        if (false !== strrpos($name, '.')) {
125
            return $name;
126
        }
127
128
        return $this->baseCodeRoute.'.'.$name;
129
    }
130
131
    /**
132
     * @return RouteCollection
133
     */
134
    public function addCollection(self $collection)
135
    {
136
        foreach ($collection->getElements() as $code => $element) {
137
            $this->addElement($code, $element);
138
        }
139
140
        return $this;
141
    }
142
143
    /**
144
     * @return Route[]
145
     */
146
    public function getElements()
147
    {
148
        foreach ($this->elements as $code => $element) {
149
            $this->resolveElement($code);
150
        }
151
152
        return $this->elements;
153
    }
154
155
    /**
156
     * @param string $name
157
     *
158
     * @return bool
159
     */
160
    public function has($name)
161
    {
162
        return \array_key_exists($this->getCode($name), $this->elements);
163
    }
164
165
    final public function hasCached(string $name): bool
166
    {
167
        return \array_key_exists($this->getCode($name), $this->cachedElements);
168
    }
169
170
    /**
171
     * @param string $name
172
     *
173
     * @throws \InvalidArgumentException
174
     *
175
     * @return Route
176
     */
177
    public function get($name)
178
    {
179
        if ($this->has($name)) {
180
            $code = $this->getCode($name);
181
            $this->resolveElement($code);
182
183
            return $this->elements[$code];
184
        }
185
186
        throw new \InvalidArgumentException(sprintf('Element "%s" does not exist.', $name));
187
    }
188
189
    /**
190
     * @param string $name
191
     *
192
     * @return RouteCollection
193
     */
194
    public function remove($name)
195
    {
196
        unset($this->elements[$this->getCode($name)]);
197
198
        return $this;
199
    }
200
201
    /**
202
     * @throws \InvalidArgumentException
203
     */
204
    final public function restore(string $name): self
205
    {
206
        if ($this->hasCached($name)) {
207
            $code = $this->getCode($name);
208
            $this->addElement($code, $this->cachedElements[$code]);
0 ignored issues
show
Documentation introduced by
$this->cachedElements[$code] is of type object<Symfony\Component\Routing\Route>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
209
210
            return $this;
211
        }
212
213
        throw new \InvalidArgumentException(sprintf('Element "%s" does not exist in cache.', $name));
214
    }
215
216
    /**
217
     * Remove all routes except routes in $routeList.
218
     *
219
     * @param string[]|string $routeList
220
     *
221
     * @return RouteCollection
222
     */
223
    public function clearExcept($routeList)
224
    {
225
        if (!\is_array($routeList)) {
226
            $routeList = [$routeList];
227
        }
228
229
        $routeCodeList = [];
230
        foreach ($routeList as $name) {
231
            $routeCodeList[] = $this->getCode($name);
232
        }
233
234
        $elements = $this->elements;
235
        foreach ($elements as $code => $element) {
236
            if (!\in_array($code, $routeCodeList, true)) {
237
                unset($this->elements[$code]);
238
            }
239
        }
240
241
        return $this;
242
    }
243
244
    /**
245
     * Remove all routes.
246
     *
247
     * @return RouteCollection
248
     */
249
    public function clear()
250
    {
251
        $this->elements = [];
252
253
        return $this;
254
    }
255
256
    /**
257
     * Convert a word in to the format for a symfony action action_name => actionName.
258
     *
259
     * @param string $action Word to actionify
260
     *
261
     * @return string Actionified word
262
     */
263
    public function actionify($action)
264
    {
265
        if (false !== ($pos = strrpos($action, '.'))) {
266
            $action = substr($action, $pos + 1);
267
        }
268
269
        // if this is a service rather than just a controller name, the suffix
270
        // Action is not automatically appended to the method name
271
        if (false === strpos($this->baseControllerName, ':')) {
272
            $action .= 'Action';
273
        }
274
275
        return lcfirst(str_replace(' ', '', ucwords(strtr($action, '_-', '  '))));
276
    }
277
278
    /**
279
     * @return string
280
     */
281
    public function getBaseCodeRoute()
282
    {
283
        return $this->baseCodeRoute;
284
    }
285
286
    /**
287
     * @return string
288
     */
289
    public function getBaseControllerName()
290
    {
291
        return $this->baseControllerName;
292
    }
293
294
    /**
295
     * @return string
296
     */
297
    public function getBaseRouteName()
298
    {
299
        return $this->baseRouteName;
300
    }
301
302
    /**
303
     * @return string
304
     */
305
    public function getBaseRoutePattern()
306
    {
307
        return $this->baseRoutePattern;
308
    }
309
310
    /**
311
     * @param Route|callable $element
312
     */
313
    final protected function addElement(string $code, $element): void
314
    {
315
        $this->elements[$code] = $element;
316
        $this->updateCachedElement($code);
317
    }
318
319
    final protected function updateCachedElement(string $code): void
320
    {
321
        $this->cachedElements[$code] = $this->elements[$code];
322
    }
323
324
    private function resolveElement(string $code): void
325
    {
326
        $element = $this->elements[$code];
327
328
        if (\is_callable($element)) {
329
            $this->elements[$code] = $element();
330
            $this->updateCachedElement($code);
331
        }
332
    }
333
}
334