Completed
Push — master ( 0fb284...d1177b )
by Maximilian
14s
created

formatTranslatableViolationList()   D

Complexity

Conditions 13
Paths 9

Size

Total Lines 114
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 2
Metric Value
c 3
b 0
f 2
dl 0
loc 114
rs 4.9922
cc 13
eloc 60
nc 9
nop 5

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * This file is part of the Sententiaregum project.
5
 *
6
 * (c) Maximilian Bosch <[email protected]>
7
 * (c) Ben Bieler <[email protected]>
8
 *
9
 * For the full copyright and license information, please view the LICENSE
10
 * file that was distributed with this source code.
11
 */
12
13
namespace AppBundle\View;
14
15
use Symfony\Component\Translation\TranslatorInterface;
16
use Symfony\Component\Validator\ConstraintViolationListInterface;
17
18
/**
19
 * Concrete implementation of a formatter which transforms constraint violations into i18n
20
 * format that can be used in the HTTP response.
21
 *
22
 * It converts a violation list to the following format:
23
 *
24
 * [
25
 *   'de' => ['German translation'],
26
 *   'en' => ['English translation'],
27
 * ]
28
 *
29
 * Furthermore it is possible to sort all the violations by the property which caused the violation:
30
 *
31
 * [
32
 *   'property' => [
33
 *     [
34
 *       'de' => ['German translation'],
35
 *       'en' => ['English translation'],
36
 *     ]
37
 *   ],
38
 *   'another_property' => [
39
 *     [
40
 *       // ...
41
 *     ]
42
 *   ]
43
 * ]
44
 *
45
 * @author Maximilian Bosch <[email protected]>
46
 */
47
final class I18nResponseFormatBuilder implements I18nResponseFormatBuilderInterface
48
{
49
    /**
50
     * @var TranslatorInterface
51
     */
52
    private $translator;
53
54
    /**
55
     * Constructor.
56
     *
57
     * @param TranslatorInterface $translator
58
     */
59
    public function __construct(TranslatorInterface $translator)
60
    {
61
        $this->translator = $translator;
62
    }
63
64
    /**
65
     * {@inheritdoc}
66
     *
67
     * @throws \InvalidArgumentException If the target locales parameter is used improperly.
68
     */
69
    public function formatTranslatableViolationList(
70
        ConstraintViolationListInterface $violations,
71
        $sortProperties = true,
72
        $useAllLanguages = true,
73
        array $targetLocales = [],
74
        $domain = 'messages'
75
    ) {
76
        $hasLocales = count($targetLocales) > 0;
77
78
        if (!$useAllLanguages && $hasLocales) {
79
            throw new \InvalidArgumentException(
80
                'Wrong usage of $targetLocales: If the default locale is the only target, $targetLocales must not have any values!'
81
            );
82
        }
83
84
        if ($useAllLanguages && !$hasLocales) {
85
            throw new \InvalidArgumentException(
86
                'Wrong usage of $targetLocales: If the all locales should be rendered, $targetLocales must be given!'
87
            );
88
        }
89
90
        $fixtures = [];
91
        foreach ($violations as $violation) {
92
            // Every translation entry (whether sorted by properties in deeper levels or as top level)
93
            // should provide a basic structure.
94
            switch (true) {
95
                // If sorted by $targetLanguages, it may look like this:
96
                //
97
                // [
98
                //   'de' => ['Deutscher Text'],
99
                //   'en' => ['English text'],
100
                // ]
101
                //
102
                // When sorting by property, the structure will be merged recursively into the property list:
103
                //
104
                // [
105
                //   'property' => [
106
                //     // this is the structure merged into the property.
107
                //     'de' => ['Deutscher Text'],
108
                //     'en' => ['English text'],
109
                //   ]
110
                // ]
111
                case $useAllLanguages:
112
                    $structure = array_reduce(
113
                        $targetLocales,
114
                        function ($carry, $locale) use ($violation, $domain) {
115
                            if (!isset($carry[$locale])) {
116
                                $carry[$locale] = [];
117
                            }
118
119
                            if ($locale === $this->translator->getLocale()) {
120
                                $carry[$locale][] = $violation->getMessage();
121
                            } else {
122
                                $messageTemplate = $violation->getMessageTemplate();
123
                                $parameters      = $violation->getParameters();
124
125
                                if ($plural = $violation->getPlural()) {
126
                                    try {
127
                                        $message = $this->translator->transChoice(
128
                                            $messageTemplate,
129
                                            $plural,
130
                                            $parameters,
131
                                            $domain,
132
                                            $locale
133
                                        );
134
                                    } catch (\InvalidArgumentException $ex) {
135
                                        // we do nothing here.
136
                                        // If the pluralization fails, the default translation method will be used.
137
138
                                        $message = $this->translator->trans(
139
                                            $messageTemplate,
140
                                            $parameters,
141
                                            $domain,
142
                                            $locale
143
                                        );
144
                                    }
145
                                } else {
146
                                    $message = $this->translator->trans(
147
                                        $messageTemplate,
148
                                        $parameters,
149
                                        $domain,
150
                                        $locale
151
                                    );
152
                                }
153
154
                                $carry[$locale][] = $message;
155
                            }
156
157
                            return $carry;
158
                        },
159
                        []
160
                    );
161
                    break;
162
                default:
163
                    // If the default language is in use and nothing more, the structure looks like this:
164
                    //
165
                    // ['Message in the currently selected language']
166
                    $structure = [$violation->getMessage()];
167
            }
168
169
            if (!$sortProperties) {
170
                $fixtures = array_merge_recursive($fixtures, $structure);
171
            } else {
172
                $propertyPath = $violation->getPropertyPath();
173
                if (!isset($fixtures[$violation->getPropertyPath()])) {
174
                    $fixtures[$violation->getPropertyPath()] = [];
175
                }
176
177
                $fixtures[$propertyPath] = array_merge_recursive($fixtures[$propertyPath], $structure);
178
            }
179
        }
180
181
        return $fixtures;
182
    }
183
}
184