Completed
Push — master ( aa0624...f17611 )
by Nikola
03:22
created

Configuration::getCurrencyCodeTypeDefinition()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 15
Code Lines 11

Duplication

Lines 15
Ratio 100 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 15
loc 15
ccs 0
cts 10
cp 0
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 11
nc 1
nop 0
crap 2
1
<?php
2
/*
3
 * This file is part of the Exchange Rate Bundle, an RunOpenCode project.
4
 *
5
 * (c) 2017 RunOpenCode
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace RunOpenCode\Bundle\ExchangeRate\DependencyInjection;
11
12
use RunOpenCode\Bundle\ExchangeRate\Role;
13
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
14
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
15
use Symfony\Component\Config\Definition\ConfigurationInterface;
16
17
/**
18
 * Class Configuration
19
 *
20
 * Configuration tree.
21
 *
22
 * @package RunOpenCode\Bundle\ExchangeRate\DependencyInjection
23
 */
24
class Configuration implements ConfigurationInterface
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29 1
    public function getConfigTreeBuilder()
30
    {
31 1
        $treeBuilder = new TreeBuilder();
32
33 1
        $rootNode = $treeBuilder->root('run_open_code_exchange_rate');
34
35
        $rootNode
36 1
            ->children()
37 1
                ->scalarNode('base_currency')
38 1
                    ->isRequired()
39 1
                    ->info('Set base currency in which you are doing your business activities.')
40 1
                ->end()
41 1
                ->scalarNode('repository')
42 1
                    ->defaultValue('file')
43 1
                    ->info('Service ID which is in charge for rates persistence.')
44 1
                ->end()
45 1
                ->append($this->getRatesDefinition())
46 1
                ->append($this->getFileRepositoryDefinition())
47 1
                ->append($this->getSourcesDefinition())
48 1
                ->append($this->getAccessRolesDefinition())
49
                ->append($this->getNotificationDefinition())
50
                ->arrayNode('form_types')
51
                    ->addDefaultsIfNotSet()
52
                    ->children()
53
                        ->append($this->getSourceTypeDefinition())
54
                        ->append($this->getRateTypeTypeDefinition())
55
                        ->append($this->getCurrencyCodeTypeDefinition())
56
                        ->append($this->getRateTypeDefinition())
57
                    ->end()
58
                ->end()
59
            ->end()
60
        ->end();
61
62
        return $treeBuilder;
63
    }
64
65
    /**
66
     * Build configuration tree for rates.
67
     *
68
     * @return ArrayNodeDefinition
69
     */
70 1
    protected function getRatesDefinition()
71
    {
72 1
        $node = new ArrayNodeDefinition('rates');
73
        $node
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition: Symfony\Component\Config...der\ArrayNodeDefinition. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
74 1
            ->info('Configuration of each individual rate with which you intend to work with.')
75 1
            ->requiresAtLeastOneElement()
76 1
                ->prototype('array')
77 1
                    ->children()
78 1
                        ->scalarNode('currency_code')->isRequired()->end()
79 1
                        ->scalarNode('rate_type')->isRequired()->end()
80 1
                        ->scalarNode('source')->isRequired()->end()
81 1
                        ->arrayNode('extra')->end()
82 1
                    ->end()
83 1
                ->end()
84 1
            ->end();
85
86 1
        return $node;
87
    }
88
89
    /**
90
     * Build configuration tree for repository.
91
     *
92
     * @return ArrayNodeDefinition
93
     */
94 1
    protected function getFileRepositoryDefinition()
95
    {
96 1
        $node = new ArrayNodeDefinition('file_repository');
97
98
        $node
99 1
            ->info('Configuration for file repository (if used).')
100 1
            ->addDefaultsIfNotSet()
101 1
            ->children()
102 1
                ->scalarNode('path')
103 1
                ->info('Absolute path to file where database file will be stored.')
104 1
                ->defaultValue('%kernel.root_dir%/db/exchange_rates.dat')
105 1
                ->end()
106 1
            ->end()
107 1
        ->end();
108
109 1
        return $node;
110
    }
111
112
    /**
113
     * Build configuration tree for simple sources.
114
     *
115
     * @return ArrayNodeDefinition
116
     */
117 1
    protected function getSourcesDefinition()
118
    {
119 1
        $node = new ArrayNodeDefinition('sources');
120
121
        $node
122 1
            ->info('Add sources to sources registry without registering them into service container.')
123 1
            ->useAttributeAsKey('name')
124 1
            ->prototype('scalar')->end()
125 1
        ->end();
126
127 1
        return $node;
128
    }
129
130
    /**
131
     * Build configuration tree for access roles.
132
     *
133
     * @return ArrayNodeDefinition
134
     */
135 1
    protected function getAccessRolesDefinition()
136
    {
137 1
        $node = new ArrayNodeDefinition('access_roles');
138
139
        $node
140 1
            ->info('Configuration of controller access roles.')
141 1
            ->addDefaultsIfNotSet()
142 1
            ->children()
143 1
                ->arrayNode('list')
144 1
                    ->defaultValue(array(Role::MANAGE_RATE, Role::VIEW_RATE))
145
                    ->prototype('scalar')->end()
146
                ->end()
147
                ->arrayNode('create')
148
                    ->defaultValue(array(Role::MANAGE_RATE, Role::VIEW_RATE))
149
                    ->prototype('scalar')->end()
150
                ->end()
151
                ->arrayNode('edit')
152
                    ->defaultValue(array(Role::MANAGE_RATE, Role::DELETE_RATE))
153
                    ->prototype('scalar')->end()
154
                ->end()
155
                ->arrayNode('delete')
156
                    ->defaultValue(array(Role::MANAGE_RATE, Role::DELETE_RATE))
157
                    ->prototype('scalar')->end()
158
                ->end()
159
            ->end()
160
        ->end();
161
162
163
        return $node;
164
    }
165
166
    /**
167
     * Build configuration tree for notifications.
168
     *
169
     * @return ArrayNodeDefinition
170
     */
171
    protected function getNotificationDefinition()
172
    {
173
        $node = new ArrayNodeDefinition('notifications');
174
175
        $node
176
            ->info('Notification settings.')
177
            ->addDefaultsIfNotSet()
178
            ->children()
179
                ->arrayNode('fetch')
180
                    ->children()
181
                        ->booleanNode('enabled')
182
                            ->info('Send e-mail report about fetch result and fetched rates.')
183
                            ->defaultTrue()
184
                        ->end()
185
                        ->scalarNode('from')
186
                            ->info('Mail sender address.')
187
                            ->defaultNull()
188
                        ->end()
189
                        ->arrayNode('to')
190
                            ->info('Recipients e-mail addresses.')
191
                            ->prototype('scalar')->end()
192
                        ->end()
193
                        ->arrayNode('cc')
194
                            ->info('Recipients e-mail addresses.')
195
                            ->prototype('scalar')->end()
196
                        ->end()
197
                        ->arrayNode('bcc')
198
                            ->info('Blank carbon copy recipients e-mail addresses.')
199
                            ->prototype('scalar')->end()
200
                        ->end()
201
                        ->arrayNode('templates')
202
                            ->addDefaultsIfNotSet()
203
                            ->info('Enable/disable individual mail notifications.')
204
                            ->children()
205
                                ->arrayNode('success')
206
                                    ->addDefaultsIfNotSet()
207
                                    ->children()
208
                                        ->booleanNode('enabled')
209
                                            ->info('Enable/disable success notification.')
210
                                            ->defaultTrue()
211
                                        ->end()
212
                                        ->scalarNode('subject')
213
                                            ->info('Mail notification subject.')
214
                                            ->defaultValue('System notification: exchange rates successfully fetched.')
215
                                        ->end()
216
                                        ->scalarNode('template')
217
                                            ->info('Mail body template.')
218
                                            ->defaultValue('@ExchangeRate/mail/success.html.twig')
219
                                        ->end()
220
                                    ->end()
221
                                ->end()
222
                                ->arrayNode('error')
223
                                    ->addDefaultsIfNotSet()
224
                                    ->children()
225
                                        ->booleanNode('enabled')
226
                                            ->info('Enable/disable success notification.')
227
                                            ->defaultTrue()
228
                                        ->end()
229
                                        ->scalarNode('subject')
230
                                            ->info('Mail notification subject.')
231
                                            ->defaultValue('Error notification: exchange rates are not fetched.')
232
                                        ->end()
233
                                        ->scalarNode('template')
234
                                            ->info('Mail body template.')
235
                                            ->defaultValue('@ExchangeRate/mail/error.html.twig')
236
                                        ->end()
237
                                    ->end()
238
                                ->end()
239
                            ->end()
240
                        ->end()
241
                    ->end()
242
                ->end()
243
            ->end()
244
        ->end();
245
246
        return $node;
247
    }
248
249
    /**
250
     * Build configuration tree for "RunOpenCode\Bundle\ExchangeRate\Form\Type\SourceType" default settings.
251
     *
252
     * @return ArrayNodeDefinition
253
     */
254 View Code Duplication
    protected function getSourceTypeDefinition()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
255
    {
256
        $node = new ArrayNodeDefinition('source_type');
257
258
        $node
259
            ->info('Modify default "RunOpenCode\\Bundle\\ExchangeRate\\Form\\Type\\SourceType" settings.')
260
            ->addDefaultsIfNotSet()
261
            ->children()
262
                ->scalarNode('choice_translation_domain')->defaultValue('roc_exchange_rate')->end()
263
                ->arrayNode('preferred_choices')->end()
264
            ->end()
265
        ->end();
266
267
        return $node;
268
    }
269
270
    /**
271
     * Build configuration tree for "RunOpenCode\Bundle\ExchangeRate\Form\Type\RateTypeType" default settings.
272
     *
273
     * @return ArrayNodeDefinition
274
     */
275 View Code Duplication
    protected function getRateTypeTypeDefinition()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
276
    {
277
        $node = new ArrayNodeDefinition('rate_type_type');
278
279
        $node
280
            ->info('Modify default "RunOpenCode\\Bundle\\ExchangeRate\\Form\\Type\\RateTypeType" settings.')
281
            ->addDefaultsIfNotSet()
282
            ->children()
283
                ->scalarNode('choice_translation_domain')->defaultValue('roc_exchange_rate')->end()
284
                ->arrayNode('preferred_choices')->end()
285
            ->end()
286
        ->end();
287
288
        return $node;
289
    }
290
291
    /**
292
     * Build configuration tree for "RunOpenCode\Bundle\ExchangeRate\Form\Type\CurrencyCodeType" default settings.
293
     *
294
     * @return ArrayNodeDefinition
295
     */
296 View Code Duplication
    protected function getCurrencyCodeTypeDefinition()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297
    {
298
        $node = new ArrayNodeDefinition('currency_code_type');
299
300
        $node
301
            ->info('Modify default "RunOpenCode\\Bundle\\ExchangeRate\\Form\\Type\\CurrencyCodeType" settings.')
302
            ->addDefaultsIfNotSet()
303
            ->children()
304
                ->scalarNode('choice_translation_domain')->defaultValue('roc_exchange_rate')->end()
305
                ->arrayNode('preferred_choices')->end()
306
            ->end()
307
        ->end();
308
309
        return $node;
310
    }
311
312
    /**
313
     * Build configuration tree for "RunOpenCode\Bundle\ExchangeRate\Form\Type\RateType" default settings.
314
     *
315
     * @return ArrayNodeDefinition
316
     */
317
    protected function getRateTypeDefinition()
318
    {
319
        $node = new ArrayNodeDefinition('rate_type');
320
321
        $node
322
            ->info('Modify default "RunOpenCode\\Bundle\\ExchangeRate\\Form\\Type\\RateType" settings.')
323
            ->addDefaultsIfNotSet()
324
            ->children()
325
                ->scalarNode('choice_translation_domain')->defaultValue('roc_exchange_rate')->end()
326
                ->scalarNode('label_format')->defaultValue('{{currency-code}}, {{rate-type}} ({{source}})')->end()
327
                ->arrayNode('preferred_choices')->end()
328
            ->end()
329
        ->end();
330
331
        return $node;
332
    }
333
}
334