Completed
Push — master ( 905306...b5ba41 )
by Philip
08:53
created

Service::__construct()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

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

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
    protected function initLocales(Translator $translator)
62
    {
63
        $locales   = $this->getLocales();
64
        $localeDir = __DIR__.'/../locales';
65
        $translator->addLoader('yaml', new YamlFileLoader());
66
        foreach ($locales as $locale) {
67
            $translator->addResource('yaml', $localeDir.'/'.$locale.'.yml', $locale);
68
        }
69
        return $locales;
70
    }
71
72
    /**
73
     * Initializes the children of the data entries.
74
     */
75
    protected function initChildren()
76
    {
77
        foreach ($this->datas as $name => $data) {
78
            $fields = $data->getDefinition()->getFieldNames();
79
            foreach ($fields as $field) {
80
                if ($data->getDefinition()->getType($field) == 'reference') {
81
                    $this->datas[$data->getDefinition()->getSubTypeField($field, 'reference', 'entity')]->getDefinition()->addChild($data->getDefinition()->getTable(), $field, $name);
82
                }
83
            }
84
        }
85
    }
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
    protected function getLocaleLabels(array $locales, array $crud)
99
    {
100
        $localeLabels = [];
101
        foreach ($locales as $locale) {
102
            if (array_key_exists('label_'.$locale, $crud)) {
103
                $localeLabels[$locale] = $crud['label_'.$locale];
104
            }
105
        }
106
        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
    protected function configureDefinition(EntityDefinition $definition, array $crud)
119
    {
120
        $toConfigure = [
121
            'deleteCascade',
122
            'listFields',
123
            'filter',
124
            'childrenLabelFields',
125
            'pageSize',
126
            'initialSortField',
127
            'initialSortAscending',
128
            'navBarGroup',
129
            'optimisticLocking',
130
            'hardDeletion',
131
        ];
132
        foreach ($toConfigure as $field) {
133
            if (array_key_exists($field, $crud)) {
134
                $function = 'set'.ucfirst($field);
135
                $definition->$function($crud[$field]);
136
            }
137
        }
138
    }
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
    protected function createDefinition(Translator $translator, EntityDefinitionFactoryInterface $entityDefinitionFactory, array $locales, array $crud, $name)
158
    {
159
        $label               = array_key_exists('label', $crud) ? $crud['label'] : $name;
160
        $localeLabels        = $this->getLocaleLabels($locales, $crud);
161
        $standardFieldLabels = [
162
            'id' => $translator->trans('crudlex.label.id'),
163
            'created_at' => $translator->trans('crudlex.label.created_at'),
164
            'updated_at' => $translator->trans('crudlex.label.updated_at')
165
        ];
166
167
        $definition = $entityDefinitionFactory->createEntityDefinition(
168
            $crud['table'],
169
            $crud['fields'],
170
            $label,
171
            $localeLabels,
172
            $standardFieldLabels,
173
            $this
174
        );
175
        $this->configureDefinition($definition, $crud);
176
        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 EntityDefinitionFactory $entityDefinitionFactory
0 ignored issues
show
Documentation introduced by
Should the type for parameter $entityDefinitionFactory not be EntityDefinitionFactoryInterface?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
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
    public function __construct($crudFile, $crudFileCachingDirectory, UrlGenerator $urlGenerator, Translator $translator, DataFactoryInterface $dataFactory, EntityDefinitionFactoryInterface $entityDefinitionFactory, FilesystemInterface $filesystem, ?EntityDefinitionValidatorInterface $validator)
200
    {
201
202
        $this->urlGenerator = $urlGenerator;
203
204
        $reader     = new YamlReader($crudFileCachingDirectory);
205
        $parsedYaml = $reader->read($crudFile);
206
207
        if ($validator !== null) {
208
            $validator->validate($parsedYaml);
209
        }
210
211
        $locales     = $this->initLocales($translator);
212
        $this->datas = [];
213
        foreach ($parsedYaml as $name => $crud) {
214
            $definition         = $this->createDefinition($translator, $entityDefinitionFactory, $locales, $crud, $name);
215
            $this->datas[$name] = $dataFactory->createData($definition, $filesystem);
216
        }
217
218
        $this->initChildren();
219
220
    }
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
    public function getData($name)
232
    {
233
        if (!array_key_exists($name, $this->datas)) {
234
            return null;
235
        }
236
        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
    public function getEntities()
246
    {
247
        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
    public function getEntitiesNavBar()
257
    {
258
        $result = [];
259
        foreach ($this->datas as $entity => $data) {
260
            $navBarGroup = $data->getDefinition()->getNavBarGroup();
261
            if ($navBarGroup !== 'main') {
262
                $result[$navBarGroup][] = $entity;
263
            } else {
264
                $result[$entity] = 'main';
265
            }
266
        }
267
        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
    public function setTemplate($key, $template)
282
    {
283
        $this->templates[$key] = $template;
284
    }
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
    public function getTemplate($section, $action, $entity)
307
    {
308
        $sectionAction = $section.'.'.$action;
309
310
        $offsets = [
311
            $sectionAction.'.'.$entity,
312
            $section.'.'.$entity,
313
            $sectionAction,
314
            $section
315
        ];
316
        foreach ($offsets as $offset) {
317
            if (array_key_exists($offset, $this->templates)) {
318
                return $this->templates[$offset];
319
            }
320
        }
321
322
        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
    public function setLocale($locale)
332
    {
333
        foreach ($this->datas as $data) {
334
            $data->getDefinition()->setLocale($locale);
335
        }
336
    }
337
338
    /**
339
     * Gets the available locales.
340
     *
341
     * @return array
342
     * the available locales
343
     */
344
    public function getLocales()
345
    {
346
        $localeDir     = __DIR__.'/../locales';
347
        $languageFiles = scandir($localeDir);
348
        $locales       = [];
349
        foreach ($languageFiles as $languageFile) {
350
            if (in_array($languageFile, ['.', '..'])) {
351
                continue;
352
            }
353
            $extensionPos = strpos($languageFile, '.yml');
354
            if ($extensionPos !== false) {
355
                $locale    = substr($languageFile, 0, $extensionPos);
356
                $locales[] = $locale;
357
            }
358
        }
359
        sort($locales);
360
        return $locales;
361
    }
362
363
    /**
364
     * Gets whether CRUDlex manages the i18n.
365
     * @return bool
366
     * true if so
367
     */
368
    public function isManageI18n()
369
    {
370
        return $this->manageI18n;
371
    }
372
373
    /**
374
     * Sets whether CRUDlex manages the i18n.
375
     * @param bool $manageI18n
376
     * true if so
377
     */
378
    public function setManageI18n($manageI18n)
379
    {
380
        $this->manageI18n = $manageI18n;
381
    }
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
    public function generateURL($name, $parameters)
393
    {
394
        return $this->urlGenerator->generate($name, $parameters);
395
    }
396
397
}
398