Completed
Push — master ( 5e7f91...e0cb69 )
by Philip
08:11 queued 05:45
created

Service::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 13
cts 13
cp 1
rs 9.2
c 0
b 0
f 0
cc 3
eloc 12
nc 4
nop 8
crap 3

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
/*
4
 * This file is part of the CRUDlex package.
5
 *
6
 * (c) Philip Lehmann-Böhm <[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
namespace CRUDlex;
13
14
use League\Flysystem\FilesystemInterface;
15
use Symfony\Component\Routing\Generator\UrlGenerator;
16
use Symfony\Component\Translation\Loader\YamlFileLoader;
17
use Symfony\Component\Translation\Translator;
18
19
/**
20
 * The Service setups and initializes the whole CRUD system and is initialized via the framework
21
 * specific implementation, the Silex one for example.
22
 * It offers access to AbstractData instances, one for each defined entity off the CRUD YAML file
23
 * and various other helper functions.
24
 */
25
class Service
26
{
27
28
    /**
29
     * Holds the data instances.
30
     * @var array
31
     */
32
    protected $datas;
33
34
    /**
35
     * Holds the map for overriding templates.
36
     * @var array
37
     */
38
    protected $templates = [];
39
40
    /**
41
     * Holds whether CRUDlex manages i18n.
42
     * @var bool
43
     */
44
    protected $manageI18n = true;
45
46
    /**
47
     * Holds the URL generator.
48
     * @var \Symfony\Component\Routing\Generator\UrlGenerator
49
     */
50
    protected $urlGenerator;
51
52
    /**
53
     * Initializes the available locales.
54
     *
55
     * @param Translator $translator
56
     * the translator
57
     *
58
     * @return array
59
     * the available locales
60
     */
61 79
    protected function initLocales(Translator $translator)
62
    {
63 79
        $locales   = $this->getLocales();
64 79
        $localeDir = __DIR__.'/../locales';
65 79
        $translator->addLoader('yaml', new YamlFileLoader());
66 79
        foreach ($locales as $locale) {
67 79
            $translator->addResource('yaml', $localeDir.'/'.$locale.'.yml', $locale);
68
        }
69 79
        return $locales;
70
    }
71
72
    /**
73
     * Initializes the children of the data entries.
74
     */
75 79
    protected function initChildren()
76
    {
77 79
        foreach ($this->datas as $name => $data) {
78 79
            $fields = $data->getDefinition()->getFieldNames();
79 79
            foreach ($fields as $field) {
80 79
                if ($data->getDefinition()->getType($field) == 'reference') {
81 79
                    $this->datas[$data->getDefinition()->getSubTypeField($field, 'reference', 'entity')]->getDefinition()->addChild($data->getDefinition()->getTable(), $field, $name);
82
                }
83
            }
84
        }
85 79
    }
86
87
    /**
88
     * Gets a map with localized entity labels from the CRUD YML.
89
     *
90
     * @param array $locales
91
     * the available locales
92
     * @param array $crud
93
     * the CRUD entity map
94
     *
95
     * @return array
96
     * the map with localized entity labels
97
     */
98 79
    protected function getLocaleLabels(array $locales, array $crud)
99
    {
100 79
        $localeLabels = [];
101 79
        foreach ($locales as $locale) {
102 79
            if (array_key_exists('label_'.$locale, $crud)) {
103 79
                $localeLabels[$locale] = $crud['label_'.$locale];
104
            }
105
        }
106 79
        return $localeLabels;
107
    }
108
109
    /**
110
     * Configures the EntityDefinition according to the given
111
     * CRUD entity map.
112
     *
113
     * @param EntityDefinition $definition
114
     * the definition to configure
115
     * @param array $crud
116
     * the CRUD entity map
117
     */
118 79
    protected function configureDefinition(EntityDefinition $definition, array $crud)
119
    {
120
        $toConfigure = [
121 79
            'deleteCascade',
122
            'listFields',
123
            'filter',
124
            'childrenLabelFields',
125
            'pageSize',
126
            'initialSortField',
127
            'initialSortAscending',
128
            'navBarGroup',
129
            'optimisticLocking',
130
            'hardDeletion',
131
        ];
132 79
        foreach ($toConfigure as $field) {
133 79
            if (array_key_exists($field, $crud)) {
134 79
                $function = 'set'.ucfirst($field);
135 79
                $definition->$function($crud[$field]);
136
            }
137
        }
138 79
    }
139
140
    /**
141
     * Creates and setups an EntityDefinition instance.
142
     *
143
     * @param Translator $translator
144
     * the Translator to use for some standard field labels
145
     * @param EntityDefinitionFactoryInterface $entityDefinitionFactory
146
     * the EntityDefinitionFactory to use
147
     * @param array $locales
148
     * the available locales
149
     * @param array $crud
150
     * the parsed YAML of a CRUD entity
151
     * @param string $name
152
     * the name of the entity
153
     *
154
     * @return EntityDefinition
155
     * the EntityDefinition good to go
156
     */
157 79
    protected function createDefinition(Translator $translator, EntityDefinitionFactoryInterface $entityDefinitionFactory, array $locales, array $crud, $name)
158
    {
159 79
        $label               = array_key_exists('label', $crud) ? $crud['label'] : $name;
160 79
        $localeLabels        = $this->getLocaleLabels($locales, $crud);
161
        $standardFieldLabels = [
162 79
            'id' => $translator->trans('crudlex.label.id'),
163 79
            'created_at' => $translator->trans('crudlex.label.created_at'),
164 79
            'updated_at' => $translator->trans('crudlex.label.updated_at')
165
        ];
166
167 79
        $definition = $entityDefinitionFactory->createEntityDefinition(
168 79
            $crud['table'],
169 79
            $crud['fields'],
170 79
            $label,
171 79
            $localeLabels,
172 79
            $standardFieldLabels,
173 79
            $this
174
        );
175 79
        $this->configureDefinition($definition, $crud);
176 79
        return $definition;
177
    }
178
179
    /**
180
     * Initializes the instance.
181
     *
182
     * @param string $crudFile
183
     * the CRUD YAML file
184
     * @param string|null $crudFileCachingDirectory
185
     * the writable directory to store the CRUD YAML file cache
186
     * @param UrlGenerator $urlGenerator
187
     * the URL generator to use
188
     * @param Translator $translator
189
     * the translator to use
190
     * @param DataFactoryInterface $dataFactory
191
     * the data factory to use
192
     * @param EntityDefinitionFactoryInterface $entityDefinitionFactory
193
     * the EntityDefinitionFactory to use
194
     * @param FilesystemInterface $filesystem
195
     * the filesystem to use
196
     * @param EntityDefinitionValidatorInterface|null $validator
197
     * the validator to use, null if no validation required
198
     */
199 81
    public function __construct($crudFile, $crudFileCachingDirectory, UrlGenerator $urlGenerator, Translator $translator, DataFactoryInterface $dataFactory, EntityDefinitionFactoryInterface $entityDefinitionFactory, FilesystemInterface $filesystem, ?EntityDefinitionValidatorInterface $validator)
200
    {
201
202 81
        $this->urlGenerator = $urlGenerator;
203
204 81
        $reader     = new YamlReader($crudFileCachingDirectory);
205 81
        $parsedYaml = $reader->read($crudFile);
206
207 79
        if ($validator !== null) {
208 79
            $validator->validate($parsedYaml);
209
        }
210
211 79
        $locales     = $this->initLocales($translator);
212 79
        $this->datas = [];
213 79
        foreach ($parsedYaml as $name => $crud) {
214 79
            $definition         = $this->createDefinition($translator, $entityDefinitionFactory, $locales, $crud, $name);
215 79
            $this->datas[$name] = $dataFactory->createData($definition, $filesystem);
216
        }
217
218 79
        $this->initChildren();
219
220 79
    }
221
222
    /**
223
     * Getter for the AbstractData instances.
224
     *
225
     * @param string $name
226
     * the entity name of the desired Data instance
227
     *
228
     * @return AbstractData
229
     * the AbstractData instance or null on invalid name
230
     */
231 70
    public function getData($name)
232
    {
233 70
        if (!array_key_exists($name, $this->datas)) {
234 8
            return null;
235
        }
236 70
        return $this->datas[$name];
237
    }
238
239
    /**
240
     * Getter for all available entity names.
241
     *
242
     * @return string[]
243
     * a list of all available entity names
244
     */
245 7
    public function getEntities()
246
    {
247 7
        return array_keys($this->datas);
248
    }
249
250
    /**
251
     * Getter for the entities for the navigation bar.
252
     *
253
     * @return string[]
254
     * a list of all available entity names with their group
255
     */
256 10
    public function getEntitiesNavBar()
257
    {
258 10
        $result = [];
259 10
        foreach ($this->datas as $entity => $data) {
260 10
            $navBarGroup = $data->getDefinition()->getNavBarGroup();
261 10
            if ($navBarGroup !== 'main') {
262 10
                $result[$navBarGroup][] = $entity;
263
            } else {
264 10
                $result[$entity] = 'main';
265
            }
266
        }
267 10
        return $result;
268
    }
269
270
    /**
271
     * Sets a template to use instead of the build in ones.
272
     *
273
     * @param string $key
274
     * the template key to use in this format:
275
     * $section.$action.$entity
276
     * $section.$action
277
     * $section
278
     * @param string $template
279
     * the template to use for this key
280
     */
281 12
    public function setTemplate($key, $template)
282
    {
283 12
        $this->templates[$key] = $template;
284 12
    }
285
286
    /**
287
     * Determines the Twig template to use for the given parameters depending on
288
     * the existance of certain template keys set in this order:
289
     *
290
     * $section.$action.$entity
291
     * $section.$action
292
     * $section
293
     *
294
     * If nothing exists, this string is returned: "@crud/<action>.twig"
295
     *
296
     * @param string $section
297
     * the section of the template, either "layout" or "template"
298
     * @param string $action
299
     * the current calling action like "create" or "show"
300
     * @param string $entity
301
     * the current calling entity
302
     *
303
     * @return string
304
     * the best fitting template
305
     */
306 11
    public function getTemplate($section, $action, $entity)
307
    {
308 11
        $sectionAction = $section.'.'.$action;
309
310
        $offsets = [
311 11
            $sectionAction.'.'.$entity,
312 11
            $section.'.'.$entity,
313 11
            $sectionAction,
314 11
            $section
315
        ];
316 11
        foreach ($offsets as $offset) {
317 11
            if (array_key_exists($offset, $this->templates)) {
318 11
                return $this->templates[$offset];
319
            }
320
        }
321
322 11
        return '@crud/'.$action.'.twig';
323
    }
324
325
    /**
326
     * Sets the locale to be used.
327
     *
328
     * @param string $locale
329
     * the locale to be used.
330
     */
331 10
    public function setLocale($locale)
332
    {
333 10
        foreach ($this->datas as $data) {
334 10
            $data->getDefinition()->setLocale($locale);
335
        }
336 10
    }
337
338
    /**
339
     * Gets the available locales.
340
     *
341
     * @return array
342
     * the available locales
343
     */
344 79
    public function getLocales()
345
    {
346 79
        $localeDir     = __DIR__.'/../locales';
347 79
        $languageFiles = scandir($localeDir);
348 79
        $locales       = [];
349 79
        foreach ($languageFiles as $languageFile) {
350 79
            if (in_array($languageFile, ['.', '..'])) {
351 79
                continue;
352
            }
353 79
            $extensionPos = strpos($languageFile, '.yml');
354 79
            if ($extensionPos !== false) {
355 79
                $locale    = substr($languageFile, 0, $extensionPos);
356 79
                $locales[] = $locale;
357
            }
358
        }
359 79
        sort($locales);
360 79
        return $locales;
361
    }
362
363
    /**
364
     * Gets whether CRUDlex manages the i18n.
365
     * @return bool
366
     * true if so
367
     */
368 11
    public function isManageI18n()
369
    {
370 11
        return $this->manageI18n;
371
    }
372
373
    /**
374
     * Sets whether CRUDlex manages the i18n.
375
     * @param bool $manageI18n
376
     * true if so
377
     */
378 1
    public function setManageI18n($manageI18n)
379
    {
380 1
        $this->manageI18n = $manageI18n;
381 1
    }
382
383
    /**
384
     * Generates an URL.
385
     * @param string $name
386
     * the name of the route
387
     * @param mixed $parameters
388
     * an array of parameters
389
     * @return null|string
390
     * the generated URL
391
     */
392 11
    public function generateURL($name, $parameters)
393
    {
394 11
        return $this->urlGenerator->generate($name, $parameters);
395
    }
396
397
}
398