RequestConfiguration   F
last analyzed

Complexity

Total Complexity 96

Size/Duplication

Total Lines 621
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 2

Importance

Changes 0
Metric Value
wmc 96
lcom 1
cbo 2
dl 0
loc 621
rs 1.979
c 0
b 0
f 0

46 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getRequest() 0 4 1
A getMetadata() 0 4 1
A getParameters() 0 4 1
A getSection() 0 4 1
A isHtmlRequest() 0 4 1
A getDefaultTemplate() 0 10 3
A getTemplate() 0 10 2
A getFormType() 0 18 4
A getFormOptions() 0 9 2
A getRouteName() 0 6 2
A getRedirectRoute() 0 18 4
A getRedirectHash() 0 10 3
A getRedirectReferer() 0 15 4
A getRedirectParameters() 0 21 4
A addExtraRedirectParameters() 0 15 3
A isLimited() 0 4 1
A getLimit() 0 10 2
A isPaginated() 0 6 2
A getPaginationMaxPerPage() 0 4 1
A isFilterable() 0 4 1
A getCriteria() 0 10 2
A isSortable() 0 4 1
A getSorting() 0 17 4
A getRequestParameter() 0 7 1
A getRepositoryMethod() 0 10 3
A getRepositoryArguments() 0 14 4
A getFactoryMethod() 0 10 3
A getFactoryArguments() 0 14 4
A getFlashMessage() 0 4 1
A getSortablePosition() 0 4 1
A getSerializationGroups() 0 4 1
A getSerializationVersion() 0 4 1
A getEvent() 0 4 1
A hasPermission() 0 4 1
A getPermission() 0 14 3
A isHeaderRedirection() 0 14 4
A getVars() 0 4 1
B parseResourceValues() 0 20 6
A hasGrid() 0 4 1
A getGrid() 0 8 2
A hasStateMachine() 0 4 1
A getStateMachineGraph() 0 6 1
A getStateMachineTransition() 0 6 1
A isCsrfProtectionEnabled() 0 4 1
A areParametersIntentionallyEmptyArray() 0 4 3

How to fix   Complexity   

Complex Class

Complex classes like RequestConfiguration often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RequestConfiguration, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * This file is part of the Sylius package.
5
 *
6
 * (c) Paweł Jędrzejewski
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 Sylius\Bundle\ResourceBundle\Controller;
15
16
use Sylius\Component\Resource\Metadata\MetadataInterface;
17
use Symfony\Component\HttpFoundation\Request;
18
use Symfony\Component\PropertyAccess\PropertyAccess;
19
20
class RequestConfiguration
21
{
22
    /**
23
     * @var Request
24
     */
25
    private $request;
26
27
    /**
28
     * @var MetadataInterface
29
     */
30
    private $metadata;
31
32
    /**
33
     * @var Parameters
34
     */
35
    private $parameters;
36
37
    /**
38
     * @param MetadataInterface $metadata
39
     * @param Request $request
40
     * @param Parameters $parameters
41
     */
42
    public function __construct(MetadataInterface $metadata, Request $request, Parameters $parameters)
43
    {
44
        $this->metadata = $metadata;
45
        $this->request = $request;
46
        $this->parameters = $parameters;
47
    }
48
49
    /**
50
     * @return Request
51
     */
52
    public function getRequest()
53
    {
54
        return $this->request;
55
    }
56
57
    /**
58
     * @return MetadataInterface
59
     */
60
    public function getMetadata()
61
    {
62
        return $this->metadata;
63
    }
64
65
    /**
66
     * @return Parameters
67
     */
68
    public function getParameters()
69
    {
70
        return $this->parameters;
71
    }
72
73
    /**
74
     * @return string|null
75
     */
76
    public function getSection()
77
    {
78
        return $this->parameters->get('section');
79
    }
80
81
    /**
82
     * @return bool
83
     */
84
    public function isHtmlRequest()
85
    {
86
        return 'html' === $this->request->getRequestFormat();
87
    }
88
89
    /**
90
     * @param string $name
91
     *
92
     * @return string|null
93
     */
94
    public function getDefaultTemplate($name)
95
    {
96
        $templatesNamespace = (string) $this->metadata->getTemplatesNamespace();
97
98
        if (false !== strpos($templatesNamespace, ':')) {
99
            return sprintf('%s:%s.%s', $templatesNamespace ?: ':', $name, 'twig');
100
        }
101
102
        return sprintf('%s/%s.%s', $templatesNamespace, $name, 'twig');
103
    }
104
105
    /**
106
     * @param string $name
107
     *
108
     * @return mixed|null
109
     */
110
    public function getTemplate($name)
111
    {
112
        $template = $this->parameters->get('template', $this->getDefaultTemplate($name));
113
114
        if (null === $template) {
115
            throw new \RuntimeException(sprintf('Could not resolve template for resource "%s".', $this->metadata->getAlias()));
116
        }
117
118
        return $template;
119
    }
120
121
    /**
122
     * @return string|null
123
     */
124
    public function getFormType()
125
    {
126
        $form = $this->parameters->get('form');
127
        if (isset($form['type'])) {
128
            return $form['type'];
129
        }
130
131
        if (is_string($form)) {
132
            return $form;
133
        }
134
135
        $form = $this->metadata->getClass('form');
136
        if (is_string($form)) {
137
            return $form;
138
        }
139
140
        return sprintf('%s_%s', $this->metadata->getApplicationName(), $this->metadata->getName());
141
    }
142
143
    /**
144
     * @return array
145
     */
146
    public function getFormOptions()
147
    {
148
        $form = $this->parameters->get('form');
149
        if (isset($form['options'])) {
150
            return $form['options'];
151
        }
152
153
        return [];
154
    }
155
156
    /**
157
     * @param string $name
158
     *
159
     * @return string
160
     */
161
    public function getRouteName($name)
162
    {
163
        $sectionPrefix = $this->getSection() ? $this->getSection() . '_' : '';
164
165
        return sprintf('%s_%s%s_%s', $this->metadata->getApplicationName(), $sectionPrefix, $this->metadata->getName(), $name);
166
    }
167
168
    /**
169
     * @param string $name
170
     *
171
     * @return mixed|string|null
172
     */
173
    public function getRedirectRoute($name)
174
    {
175
        $redirect = $this->parameters->get('redirect');
176
177
        if (null === $redirect) {
178
            return $this->getRouteName($name);
179
        }
180
181
        if (is_array($redirect)) {
182
            if (!empty($redirect['referer'])) {
183
                return 'referer';
184
            }
185
186
            return $redirect['route'];
187
        }
188
189
        return $redirect;
190
    }
191
192
    /**
193
     * Get url hash fragment (#text) which is you configured.
194
     *
195
     * @return string
196
     */
197
    public function getRedirectHash()
198
    {
199
        $redirect = $this->parameters->get('redirect');
200
201
        if (!is_array($redirect) || empty($redirect['hash'])) {
202
            return '';
203
        }
204
205
        return '#' . $redirect['hash'];
206
    }
207
208
    /**
209
     * Get redirect referer, This will detected by configuration
210
     * If not exists, The `referrer` from headers will be used.
211
     *
212
     * @return string
213
     */
214
    public function getRedirectReferer()
215
    {
216
        $redirect = $this->parameters->get('redirect');
217
        $referer = $this->request->headers->get('referer');
218
219
        if (!is_array($redirect) || empty($redirect['referer'])) {
220
            return $referer;
221
        }
222
223
        if ($redirect['referer'] === true) {
224
            return $referer;
225
        }
226
227
        return $redirect['referer'];
228
    }
229
230
    /**
231
     * @param object|null $resource
232
     *
233
     * @return array
234
     */
235
    public function getRedirectParameters($resource = null)
236
    {
237
        $redirect = $this->parameters->get('redirect');
238
239
        if ($this->areParametersIntentionallyEmptyArray($redirect)) {
240
            return [];
241
        }
242
243
        if (!is_array($redirect)) {
244
            $redirect = ['parameters' => []];
245
        }
246
247
        $parameters = $redirect['parameters'] ?? [];
248
        $parameters = $this->addExtraRedirectParameters($parameters);
249
250
        if (null !== $resource) {
251
            $parameters = $this->parseResourceValues($parameters, $resource);
252
        }
253
254
        return $parameters;
255
    }
256
257
    /**
258
     * @param array $parameters
259
     *
260
     * @return array
261
     */
262
    private function addExtraRedirectParameters($parameters): array
263
    {
264
        $vars = $this->getVars();
265
        $accessor = PropertyAccess::createPropertyAccessor();
266
267
        if ($accessor->isReadable($vars, '[redirect][parameters]')) {
268
            $extraParameters = $accessor->getValue($vars, '[redirect][parameters]');
269
270
            if (is_array($extraParameters)) {
271
                $parameters = array_merge($parameters, $extraParameters);
272
            }
273
        }
274
275
        return $parameters;
276
    }
277
278
    /**
279
     * @return bool
280
     */
281
    public function isLimited()
282
    {
283
        return (bool) $this->parameters->get('limit', false);
284
    }
285
286
    /**
287
     * @return int|null
288
     */
289
    public function getLimit()
290
    {
291
        $limit = null;
292
293
        if ($this->isLimited()) {
294
            $limit = (int) $this->parameters->get('limit', 10);
295
        }
296
297
        return $limit;
298
    }
299
300
    /**
301
     * @return bool
302
     */
303
    public function isPaginated()
304
    {
305
        $pagination = $this->parameters->get('paginate', true);
306
307
        return $pagination !== false && $pagination !== null;
308
    }
309
310
    /**
311
     * @return int
312
     */
313
    public function getPaginationMaxPerPage()
314
    {
315
        return (int) $this->parameters->get('paginate', 10);
316
    }
317
318
    /**
319
     * @return bool
320
     */
321
    public function isFilterable()
322
    {
323
        return (bool) $this->parameters->get('filterable', false);
324
    }
325
326
    /**
327
     * @param array $criteria
328
     *
329
     * @return array
330
     */
331
    public function getCriteria(array $criteria = [])
332
    {
333
        $defaultCriteria = array_merge($this->parameters->get('criteria', []), $criteria);
334
335
        if ($this->isFilterable()) {
336
            return $this->getRequestParameter('criteria', $defaultCriteria);
337
        }
338
339
        return $defaultCriteria;
340
    }
341
342
    /**
343
     * @return bool
344
     */
345
    public function isSortable()
346
    {
347
        return (bool) $this->parameters->get('sortable', false);
348
    }
349
350
    /**
351
     * @param array $sorting
352
     *
353
     * @return array
354
     */
355
    public function getSorting(array $sorting = [])
356
    {
357
        $defaultSorting = array_merge($this->parameters->get('sorting', []), $sorting);
358
359
        if ($this->isSortable()) {
360
            $sorting = $this->getRequestParameter('sorting');
361
            foreach ($defaultSorting as $key => $value) {
362
                if (!isset($sorting[$key])) {
363
                    $sorting[$key] = $value;
364
                }
365
            }
366
367
            return $sorting;
368
        }
369
370
        return $defaultSorting;
371
    }
372
373
    /**
374
     * @param string $parameter
375
     * @param array $defaults
376
     *
377
     * @return array
378
     */
379
    public function getRequestParameter($parameter, $defaults = [])
380
    {
381
        return array_replace_recursive(
382
            $defaults,
383
            $this->request->get($parameter, [])
384
        );
385
    }
386
387
    /**
388
     * @return array|string|null
389
     */
390
    public function getRepositoryMethod()
391
    {
392
        if (!$this->parameters->has('repository')) {
393
            return null;
394
        }
395
396
        $repository = $this->parameters->get('repository');
397
398
        return is_array($repository) ? $repository['method'] : $repository;
399
    }
400
401
    /**
402
     * @return array
403
     */
404
    public function getRepositoryArguments()
405
    {
406
        if (!$this->parameters->has('repository')) {
407
            return [];
408
        }
409
410
        $repository = $this->parameters->get('repository');
411
412
        if (!isset($repository['arguments'])) {
413
            return [];
414
        }
415
416
        return is_array($repository['arguments']) ? $repository['arguments'] : [$repository['arguments']];
417
    }
418
419
    /**
420
     * @return array|string|null
421
     */
422
    public function getFactoryMethod()
423
    {
424
        if (!$this->parameters->has('factory')) {
425
            return null;
426
        }
427
428
        $factory = $this->parameters->get('factory');
429
430
        return is_array($factory) ? $factory['method'] : $factory;
431
    }
432
433
    /**
434
     * @return array
435
     */
436
    public function getFactoryArguments()
437
    {
438
        if (!$this->parameters->has('factory')) {
439
            return [];
440
        }
441
442
        $factory = $this->parameters->get('factory');
443
444
        if (!isset($factory['arguments'])) {
445
            return [];
446
        }
447
448
        return is_array($factory['arguments']) ? $factory['arguments'] : [$factory['arguments']];
449
    }
450
451
    /**
452
     * @param null $message
453
     *
454
     * @return mixed|null
455
     */
456
    public function getFlashMessage($message)
457
    {
458
        return $this->parameters->get('flash', sprintf('%s.%s.%s', $this->metadata->getApplicationName(), $this->metadata->getName(), $message));
459
    }
460
461
    /**
462
     * @return mixed|null
463
     */
464
    public function getSortablePosition()
465
    {
466
        return $this->parameters->get('sortable_position', 'position');
467
    }
468
469
    /**
470
     * @return mixed|null
471
     */
472
    public function getSerializationGroups()
473
    {
474
        return $this->parameters->get('serialization_groups', []);
475
    }
476
477
    /**
478
     * @return mixed|null
479
     */
480
    public function getSerializationVersion()
481
    {
482
        return $this->parameters->get('serialization_version');
483
    }
484
485
    /**
486
     * @return string|null
487
     */
488
    public function getEvent()
489
    {
490
        return $this->parameters->get('event');
491
    }
492
493
    /**
494
     * @return bool
495
     */
496
    public function hasPermission()
497
    {
498
        return false !== $this->parameters->get('permission', false);
499
    }
500
501
    /**
502
     * @param string $name
503
     *
504
     * @return string
505
     *
506
     * @throws \LogicException
507
     */
508
    public function getPermission($name)
509
    {
510
        $permission = $this->parameters->get('permission');
511
512
        if (null === $permission) {
513
            throw new \LogicException('Current action does not require any authorization.');
514
        }
515
516
        if (true === $permission) {
517
            return sprintf('%s.%s.%s', $this->metadata->getApplicationName(), $this->metadata->getName(), $name);
518
        }
519
520
        return $permission;
521
    }
522
523
    /**
524
     * @return bool
525
     */
526
    public function isHeaderRedirection()
527
    {
528
        $redirect = $this->parameters->get('redirect');
529
530
        if (!is_array($redirect) || !isset($redirect['header'])) {
531
            return false;
532
        }
533
534
        if ('xhr' === $redirect['header']) {
535
            return $this->getRequest()->isXmlHttpRequest();
536
        }
537
538
        return (bool) $redirect['header'];
539
    }
540
541
    public function getVars()
542
    {
543
        return $this->parameters->get('vars', []);
544
    }
545
546
    /**
547
     * @param array  $parameters
548
     * @param object $resource
549
     *
550
     * @return array
551
     */
552
    private function parseResourceValues(array $parameters, $resource): array
553
    {
554
        $accessor = PropertyAccess::createPropertyAccessor();
555
556
        if (empty($parameters)) {
557
            return ['id' => $accessor->getValue($resource, 'id')];
558
        }
559
560
        foreach ($parameters as $key => $value) {
561
            if (is_array($value)) {
562
                $parameters[$key] = $this->parseResourceValues($value, $resource);
563
            }
564
565
            if (is_string($value) && 0 === strpos($value, 'resource.')) {
566
                $parameters[$key] = $accessor->getValue($resource, substr($value, 9));
567
            }
568
        }
569
570
        return $parameters;
571
    }
572
573
    /**
574
     * @return bool
575
     */
576
    public function hasGrid()
577
    {
578
        return $this->parameters->has('grid');
579
    }
580
581
    /**
582
     * @return string
583
     *
584
     * @throws \LogicException
585
     */
586
    public function getGrid()
587
    {
588
        if (!$this->hasGrid()) {
589
            throw new \LogicException('Current action does not use grid.');
590
        }
591
592
        return $this->parameters->get('grid');
593
    }
594
595
    /**
596
     * @return bool
597
     */
598
    public function hasStateMachine()
599
    {
600
        return $this->parameters->has('state_machine');
601
    }
602
603
    /**
604
     * @return string
605
     */
606
    public function getStateMachineGraph()
607
    {
608
        $options = $this->parameters->get('state_machine');
609
610
        return $options['graph'] ?? null;
611
    }
612
613
    /**
614
     * @return string
615
     */
616
    public function getStateMachineTransition()
617
    {
618
        $options = $this->parameters->get('state_machine');
619
620
        return $options['transition'] ?? null;
621
    }
622
623
    /**
624
     * @return bool
625
     */
626
    public function isCsrfProtectionEnabled()
627
    {
628
        return $this->parameters->get('csrf_protection', true);
629
    }
630
631
    /**
632
     * @param mixed $redirect
633
     *
634
     * @return bool
635
     */
636
    private function areParametersIntentionallyEmptyArray($redirect): bool
637
    {
638
        return isset($redirect['parameters']) && is_array($redirect['parameters']) && empty($redirect['parameters']);
639
    }
640
}
641