Completed
Push — master ( bb19ec...a4f748 )
by Philip
04:50
created

Service::__construct()   B

Complexity

Conditions 3
Paths 4

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 15
cts 15
cp 1
rs 8.8571
c 0
b 0
f 0
cc 3
eloc 14
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\UrlGeneratorInterface;
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\UrlGeneratorInterface
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 78
    protected function initLocales(Translator $translator)
62
    {
63 78
        $locales   = $this->getLocales();
64 78
        $localeDir = __DIR__.'/../locales';
65 78
        $translator->addLoader('yaml', new YamlFileLoader());
66 78
        foreach ($locales as $locale) {
67 78
            $translator->addResource('yaml', $localeDir.'/'.$locale.'.yml', $locale);
68
        }
69 78
        return $locales;
70
    }
71
72
    /**
73
     * Initializes the children of the data entries.
74
     */
75 78
    protected function initChildren()
76
    {
77 78
        foreach ($this->datas as $name => $data) {
78 78
            $fields = $data->getDefinition()->getFieldNames();
79 78
            foreach ($fields as $field) {
80 78
                if ($data->getDefinition()->getType($field) == 'reference') {
81 78
                    $this->datas[$data->getDefinition()->getSubTypeField($field, 'reference', 'entity')]->getDefinition()->addChild($data->getDefinition()->getTable(), $field, $name);
82
                }
83
            }
84
        }
85 78
    }
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 78
    protected function getLocaleLabels(array $locales, array $crud)
99
    {
100 78
        $localeLabels = [];
101 78
        foreach ($locales as $locale) {
102 78
            if (array_key_exists('label_'.$locale, $crud)) {
103 78
                $localeLabels[$locale] = $crud['label_'.$locale];
104
            }
105
        }
106 78
        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 78
    protected function configureDefinition(EntityDefinition $definition, array $crud)
119
    {
120
        $toConfigure = [
121 78
            'deleteCascade',
122
            'listFields',
123
            'filter',
124
            'childrenLabelFields',
125
            'pageSize',
126
            'initialSortField',
127
            'initialSortAscending',
128
            'navBarGroup',
129
            'optimisticLocking',
130
            'hardDeletion',
131
        ];
132 78
        foreach ($toConfigure as $field) {
133 78
            if (array_key_exists($field, $crud)) {
134 78
                $function = 'set'.ucfirst($field);
135 78
                $definition->$function($crud[$field]);
136
            }
137
        }
138 78
    }
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 78
    protected function createDefinition(Translator $translator, EntityDefinitionFactoryInterface $entityDefinitionFactory, array $locales, array $crud, $name)
158
    {
159 78
        $label               = array_key_exists('label', $crud) ? $crud['label'] : $name;
160 78
        $localeLabels        = $this->getLocaleLabels($locales, $crud);
161
        $standardFieldLabels = [
162 78
            'id' => $translator->trans('crudlex.label.id'),
163 78
            'created_at' => $translator->trans('crudlex.label.created_at'),
164 78
            'updated_at' => $translator->trans('crudlex.label.updated_at')
165
        ];
166
167 78
        $definition = $entityDefinitionFactory->createEntityDefinition(
168 78
            $crud['table'],
169 78
            $crud['fields'],
170 78
            $label,
171 78
            $localeLabels,
172 78
            $standardFieldLabels,
173 78
            $this
174
        );
175 78
        $this->configureDefinition($definition, $crud);
176 78
        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 UrlGeneratorInterface $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 79
    public function __construct($crudFile, $crudFileCachingDirectory, UrlGeneratorInterface $urlGenerator, Translator $translator, DataFactoryInterface $dataFactory, EntityDefinitionFactoryInterface $entityDefinitionFactory, FilesystemInterface $filesystem, ?EntityDefinitionValidatorInterface $validator)
200
    {
201
202 79
        $this->urlGenerator = $urlGenerator;
203
204 79
        $this->templates = [];
205 79
        $this->setTemplate('layout', '@crud/layout.twig');
206
207 79
        $reader     = new YamlReader($crudFileCachingDirectory);
208 79
        $parsedYaml = $reader->read($crudFile);
209
210 78
        if ($validator !== null) {
211 78
            $validator->validate($parsedYaml);
212
        }
213
214 78
        $locales     = $this->initLocales($translator);
215 78
        $this->datas = [];
216 78
        foreach ($parsedYaml as $name => $crud) {
217 78
            $definition         = $this->createDefinition($translator, $entityDefinitionFactory, $locales, $crud, $name);
218 78
            $this->datas[$name] = $dataFactory->createData($definition, $filesystem);
219
        }
220
221 78
        $this->initChildren();
222
223 78
    }
224
225
    /**
226
     * Getter for the AbstractData instances.
227
     *
228
     * @param string $name
229
     * the entity name of the desired Data instance
230
     *
231
     * @return AbstractData
232
     * the AbstractData instance or null on invalid name
233
     */
234 70
    public function getData($name)
235
    {
236 70
        if (!array_key_exists($name, $this->datas)) {
237 3
            return null;
238
        }
239 70
        return $this->datas[$name];
240
    }
241
242
    /**
243
     * Getter for all available entity names.
244
     *
245
     * @return string[]
246
     * a list of all available entity names
247
     */
248 5
    public function getEntities()
249
    {
250 5
        return array_keys($this->datas);
251
    }
252
253
    /**
254
     * Getter for the entities for the navigation bar.
255
     *
256
     * @return string[]
257
     * a list of all available entity names with their group
258
     */
259 11
    public function getEntitiesNavBar()
260
    {
261 11
        $result = [];
262 11
        foreach ($this->datas as $entity => $data) {
263 11
            $navBarGroup = $data->getDefinition()->getNavBarGroup();
264 11
            if ($navBarGroup !== 'main') {
265 11
                $result[$navBarGroup][] = $entity;
266
            } else {
267 11
                $result[$entity] = 'main';
268
            }
269
        }
270 11
        return $result;
271
    }
272
273
    /**
274
     * Sets a template to use instead of the build in ones.
275
     *
276
     * @param string $key
277
     * the template key to use in this format:
278
     * $section.$action.$entity
279
     * $section.$action
280
     * $section
281
     * @param string $template
282
     * the template to use for this key
283
     */
284 79
    public function setTemplate($key, $template)
285
    {
286 79
        $this->templates[$key] = $template;
287 79
    }
288
289
    /**
290
     * Determines the Twig template to use for the given parameters depending on
291
     * the existance of certain template keys set in this order:
292
     *
293
     * $section.$action.$entity
294
     * $section.$action
295
     * $section
296
     *
297
     * If nothing exists, this string is returned: "@crud/<action>.twig"
298
     *
299
     * @param string $section
300
     * the section of the template, either "layout" or "template"
301
     * @param string $action
302
     * the current calling action like "create" or "show"
303
     * @param string $entity
304
     * the current calling entity
305
     *
306
     * @return string
307
     * the best fitting template
308
     */
309 11
    public function getTemplate($section, $action, $entity)
310
    {
311 11
        $sectionAction = $section.'.'.$action;
312
313
        $offsets = [
314 11
            $sectionAction.'.'.$entity,
315 11
            $section.'.'.$entity,
316 11
            $sectionAction,
317 11
            $section
318
        ];
319 11
        foreach ($offsets as $offset) {
320 11
            if (array_key_exists($offset, $this->templates)) {
321 11
                return $this->templates[$offset];
322
            }
323
        }
324
325 11
        return '@crud/'.$action.'.twig';
326
    }
327
328
    /**
329
     * Sets the locale to be used.
330
     *
331
     * @param string $locale
332
     * the locale to be used.
333
     */
334 3
    public function setLocale($locale)
335
    {
336 3
        foreach ($this->datas as $data) {
337 3
            $data->getDefinition()->setLocale($locale);
338
        }
339 3
    }
340
341
    /**
342
     * Gets the available locales.
343
     *
344
     * @return array
345
     * the available locales
346
     */
347 78
    public function getLocales()
348
    {
349 78
        $localeDir     = __DIR__.'/../locales';
350 78
        $languageFiles = scandir($localeDir);
351 78
        $locales       = [];
352 78
        foreach ($languageFiles as $languageFile) {
353 78
            if (in_array($languageFile, ['.', '..'])) {
354 78
                continue;
355
            }
356 78
            $extensionPos = strpos($languageFile, '.yml');
357 78
            if ($extensionPos !== false) {
358 78
                $locale    = substr($languageFile, 0, $extensionPos);
359 78
                $locales[] = $locale;
360
            }
361
        }
362 78
        sort($locales);
363 78
        return $locales;
364
    }
365
366
    /**
367
     * Gets whether CRUDlex manages the i18n.
368
     * @return bool
369
     * true if so
370
     */
371 11
    public function isManageI18n()
372
    {
373 11
        return $this->manageI18n;
374
    }
375
376
    /**
377
     * Sets whether CRUDlex manages the i18n.
378
     * @param bool $manageI18n
379
     * true if so
380
     */
381 1
    public function setManageI18n($manageI18n)
382
    {
383 1
        $this->manageI18n = $manageI18n;
384 1
    }
385
386
    /**
387
     * Generates an URL.
388
     * @param string $name
389
     * the name of the route
390
     * @param mixed $parameters
391
     * an array of parameters
392
     * @return null|string
393
     * the generated URL
394
     */
395 11
    public function generateURL($name, $parameters)
396
    {
397 11
        return $this->urlGenerator->generate($name, $parameters);
398
    }
399
400
}
401