Completed
Push — 1.0-symfony-3.3.13 ( 577127...a3487e )
by Kamil
50:10 queued 26:38
created

ResourceLoader   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 190
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 8

Importance

Changes 0
Metric Value
wmc 43
lcom 1
cbo 8
dl 0
loc 190
rs 8.3157
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A supports() 0 4 2
A getResolver() 0 4 1
A setResolver() 0 4 1
C load() 0 57 14
F createRoute() 0 58 22
A getRouteName() 0 6 2

How to fix   Complexity   

Complex Class

Complex classes like ResourceLoader 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 ResourceLoader, 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\Routing;
15
16
use Gedmo\Sluggable\Util\Urlizer;
17
use Sylius\Component\Resource\Metadata\MetadataInterface;
18
use Sylius\Component\Resource\Metadata\RegistryInterface;
19
use Symfony\Component\Config\Definition\Processor;
20
use Symfony\Component\Config\Loader\LoaderInterface;
21
use Symfony\Component\Config\Loader\LoaderResolverInterface;
22
use Symfony\Component\Routing\Route;
23
use Symfony\Component\Routing\RouteCollection;
24
use Symfony\Component\Yaml\Yaml;
25
26
final class ResourceLoader implements LoaderInterface
27
{
28
    /**
29
     * @var RegistryInterface
30
     */
31
    private $resourceRegistry;
32
33
    /**
34
     * @var RouteFactoryInterface
35
     */
36
    private $routeFactory;
37
38
    /**
39
     * @param RegistryInterface $resourceRegistry
40
     * @param RouteFactoryInterface $routeFactory
41
     */
42
    public function __construct(RegistryInterface $resourceRegistry, RouteFactoryInterface $routeFactory)
43
    {
44
        $this->resourceRegistry = $resourceRegistry;
45
        $this->routeFactory = $routeFactory;
46
    }
47
48
    /**
49
     * {@inheritdoc}
50
     */
51
    public function load($resource, $type = null): RouteCollection
52
    {
53
        $processor = new Processor();
54
        $configurationDefinition = new Configuration();
55
56
        $configuration = Yaml::parse($resource);
57
        $configuration = $processor->processConfiguration($configurationDefinition, ['routing' => $configuration]);
58
59
        if (!empty($configuration['only']) && !empty($configuration['except'])) {
60
            throw new \InvalidArgumentException('You can configure only one of "except" & "only" options.');
61
        }
62
63
        $routesToGenerate = ['show', 'index', 'create', 'update', 'delete'];
64
65
        if (!empty($configuration['only'])) {
66
            $routesToGenerate = $configuration['only'];
67
        }
68
        if (!empty($configuration['except'])) {
69
            $routesToGenerate = array_diff($routesToGenerate, $configuration['except']);
70
        }
71
72
        $isApi = $type === 'sylius.resource_api';
73
74
        /** @var MetadataInterface $metadata */
75
        $metadata = $this->resourceRegistry->get($configuration['alias']);
76
        $routes = $this->routeFactory->createRouteCollection();
77
78
        $rootPath = sprintf('/%s/', $configuration['path'] ?? Urlizer::urlize($metadata->getPluralName()));
79
        $identifier = sprintf('{%s}', $configuration['identifier']);
80
81
        if (in_array('index', $routesToGenerate, true)) {
82
            $indexRoute = $this->createRoute($metadata, $configuration, $rootPath, 'index', ['GET'], $isApi);
83
            $routes->add($this->getRouteName($metadata, $configuration, 'index'), $indexRoute);
84
        }
85
86
        if (in_array('create', $routesToGenerate, true)) {
87
            $createRoute = $this->createRoute($metadata, $configuration, $isApi ? $rootPath : $rootPath . 'new', 'create', $isApi ? ['POST'] : ['GET', 'POST'], $isApi);
88
            $routes->add($this->getRouteName($metadata, $configuration, 'create'), $createRoute);
89
        }
90
91
        if (in_array('update', $routesToGenerate, true)) {
92
            $updateRoute = $this->createRoute($metadata, $configuration, $isApi ? $rootPath . $identifier : $rootPath . $identifier . '/edit', 'update', $isApi ? ['PUT', 'PATCH'] : ['GET', 'PUT', 'PATCH'], $isApi);
93
            $routes->add($this->getRouteName($metadata, $configuration, 'update'), $updateRoute);
94
        }
95
96
        if (in_array('show', $routesToGenerate, true)) {
97
            $showRoute = $this->createRoute($metadata, $configuration, $rootPath . $identifier, 'show', ['GET'], $isApi);
98
            $routes->add($this->getRouteName($metadata, $configuration, 'show'), $showRoute);
99
        }
100
101
        if (in_array('delete', $routesToGenerate, true)) {
102
            $deleteRoute = $this->createRoute($metadata, $configuration, $rootPath . $identifier, 'delete', ['DELETE'], $isApi);
103
            $routes->add($this->getRouteName($metadata, $configuration, 'delete'), $deleteRoute);
104
        }
105
106
        return $routes;
107
    }
108
109
    /**
110
     * {@inheritdoc}
111
     */
112
    public function supports($resource, $type = null): bool
113
    {
114
        return 'sylius.resource' === $type || 'sylius.resource_api' === $type;
115
    }
116
117
    /**
118
     * {@inheritdoc}
119
     */
120
    public function getResolver(): void
121
    {
122
        // Intentionally left blank.
123
    }
124
125
    /**
126
     * {@inheritdoc}
127
     */
128
    public function setResolver(LoaderResolverInterface $resolver): void
129
    {
130
        // Intentionally left blank.
131
    }
132
133
    /**
134
     * @param MetadataInterface $metadata
135
     * @param array $configuration
136
     * @param string $path
137
     * @param string $actionName
138
     * @param array $methods
139
     * @param bool $isApi
140
     *
141
     * @return Route
142
     */
143
    private function createRoute(
144
        MetadataInterface $metadata,
145
        array $configuration,
146
        string $path,
147
        string $actionName,
148
        array $methods,
149
        bool $isApi = false
150
    ): Route {
151
        $defaults = [
152
            '_controller' => $metadata->getServiceId('controller') . sprintf(':%sAction', $actionName),
153
        ];
154
155
        if ($isApi && 'index' === $actionName) {
156
            $defaults['_sylius']['serialization_groups'] = ['Default'];
157
        }
158
        if ($isApi && in_array($actionName, ['show', 'create', 'update'], true)) {
159
            $defaults['_sylius']['serialization_groups'] = ['Default', 'Detailed'];
160
        }
161
        if ($isApi && 'delete' === $actionName) {
162
            $defaults['_sylius']['csrf_protection'] = false;
163
        }
164
        if (isset($configuration['grid']) && 'index' === $actionName) {
165
            $defaults['_sylius']['grid'] = $configuration['grid'];
166
        }
167
        if (isset($configuration['form']) && in_array($actionName, ['create', 'update'], true)) {
168
            $defaults['_sylius']['form'] = $configuration['form'];
169
        }
170
        if (isset($configuration['serialization_version'])) {
171
            $defaults['_sylius']['serialization_version'] = $configuration['serialization_version'];
172
        }
173
        if (isset($configuration['section'])) {
174
            $defaults['_sylius']['section'] = $configuration['section'];
175
        }
176
        if (!empty($configuration['criteria'])) {
177
            $defaults['_sylius']['criteria'] = $configuration['criteria'];
178
        }
179
        if (array_key_exists('filterable', $configuration)) {
180
            $defaults['_sylius']['filterable'] = $configuration['filterable'];
181
        }
182
        if (isset($configuration['templates']) && in_array($actionName, ['show', 'index', 'create', 'update'], true)) {
183
            $defaults['_sylius']['template'] = sprintf('%s:%s.html.twig', $configuration['templates'], $actionName);
184
        }
185
        if (isset($configuration['redirect']) && in_array($actionName, ['create', 'update'], true)) {
186
            $defaults['_sylius']['redirect'] = $this->getRouteName($metadata, $configuration, $configuration['redirect']);
187
        }
188
        if (isset($configuration['permission'])) {
189
            $defaults['_sylius']['permission'] = $configuration['permission'];
190
        }
191
        if (isset($configuration['vars']['all'])) {
192
            $defaults['_sylius']['vars'] = $configuration['vars']['all'];
193
        }
194
        if (isset($configuration['vars'][$actionName])) {
195
            $vars = $configuration['vars']['all'] ?? [];
196
            $defaults['_sylius']['vars'] = array_merge($vars, $configuration['vars'][$actionName]);
197
        }
198
199
        return $this->routeFactory->createRoute($path, $defaults, [], [], '', [], $methods);
200
    }
201
202
    /**
203
     * @param MetadataInterface $metadata
204
     * @param array $configuration
205
     * @param string $actionName
206
     *
207
     * @return string
208
     */
209
    private function getRouteName(MetadataInterface $metadata, array $configuration, string $actionName): string
210
    {
211
        $sectionPrefix = isset($configuration['section']) ? $configuration['section'] . '_' : '';
212
213
        return sprintf('%s_%s%s_%s', $metadata->getApplicationName(), $sectionPrefix, $metadata->getName(), $actionName);
214
    }
215
}
216