Issues (16)

DependencyInjection/Configuration.php (3 issues)

Labels
Severity
1
<?php
2
3
/*
4
 * This file is part of the XiideaEasyAuditBundle package.
5
 *
6
 * (c) Xiidea <http://www.xiidea.net>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Xiidea\EasyAuditBundle\DependencyInjection;
13
14
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
15
use Symfony\Component\Config\Definition\Builder\TreeBuilder;
16
use Symfony\Component\Config\Definition\ConfigurationInterface;
17
use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException;
18
19
/**
20
 * This is the class that validates and merges configuration from your app/config files.
21
 *
22
 * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html#cookbook-bundles-extension-config-class}
23
 */
24
class Configuration implements ConfigurationInterface
25
{
26
    const ROOT_NODE_NAME = 'xiidea_easy_audit';
27
28
    /**
29
     * {@inheritdoc}
30
     */
31
    #[\Override]
32
    public function getConfigTreeBuilder(): TreeBuilder
33
    {
34
        $treeBuilder = new TreeBuilder(self::ROOT_NODE_NAME);
35
36
        $rootNode = $treeBuilder->getRootNode();
37
38
        $this->addRequiredConfigs($rootNode);
39
        $this->addDefaultServices($rootNode);
40
        $this->addOptionalConfigs($rootNode);
41
        $this->addChannelHandlers($rootNode);
42
43
        return $treeBuilder;
44
    }
45
46
    /**
47
     * @param ArrayNodeDefinition $rootNode
48
     */
49
    private function addRequiredConfigs(ArrayNodeDefinition $rootNode)
50
    {
51
        $rootNode
52
            ->children()
53
                ->scalarNode('user_property')->isRequired()->end()
54
                ->scalarNode('audit_log_class')->cannotBeOverwritten()->isRequired()->cannotBeEmpty()->end()
0 ignored issues
show
The method scalarNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

54
                ->/** @scrutinizer ignore-call */ scalarNode('audit_log_class')->cannotBeOverwritten()->isRequired()->cannotBeEmpty()->end()
Loading history...
55
            ->end();
56
    }
57
58
    /**
59
     * @param ArrayNodeDefinition $rootNode
60
     */
61
    private function addDefaultServices(ArrayNodeDefinition $rootNode)
62
    {
63
        $rootNode
64
            ->children()
65
                ->scalarNode('resolver')->defaultValue('xiidea.easy_audit.default_event_resolver')->end()
66
                ->scalarNode('doctrine_event_resolver')
67
                    ->defaultValue(null)
68
                ->end()
69
                ->booleanNode('default_logger')->defaultValue(true)->end()
70
            ->end();
71
    }
72
73
    /**
74
     * @param ArrayNodeDefinition $rootNode
75
     */
76
    private function addOptionalConfigs(ArrayNodeDefinition $rootNode)
77
    {
78
        $rootNode
79
            ->children()
80
                ->variableNode('doctrine_objects')
81
                    ->defaultValue(array())
82
                ->end()
83
                ->variableNode('events')->defaultValue(array())->end()
0 ignored issues
show
The method variableNode() does not exist on Symfony\Component\Config...der\NodeParentInterface. It seems like you code against a sub-type of Symfony\Component\Config...der\NodeParentInterface such as Symfony\Component\Config...ion\Builder\NodeBuilder. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

83
                ->/** @scrutinizer ignore-call */ variableNode('events')->defaultValue(array())->end()
Loading history...
84
                ->variableNode('custom_resolvers')->defaultValue(array())->end()
85
            ->end();
86
    }
87
88
    /**
89
     * @param ArrayNodeDefinition $rootNode
90
     */
91
    private function addChannelHandlers(ArrayNodeDefinition $rootNode)
92
    {
93
        $rootNode
94
            ->fixXmlConfig('loggerChannel')
95
            ->children()
96
                ->arrayNode('logger_channel')
97
                    ->canBeUnset()
98
                    ->useAttributeAsKey('name')
99
                    ->prototype('array')
100
                    ->fixXmlConfig('channel', 'elements')
0 ignored issues
show
The method fixXmlConfig() does not exist on Symfony\Component\Config...\Builder\NodeDefinition. It seems like you code against a sub-type of Symfony\Component\Config...\Builder\NodeDefinition such as Symfony\Component\Config...der\ArrayNodeDefinition. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

100
                    ->/** @scrutinizer ignore-call */ fixXmlConfig('channel', 'elements')
Loading history...
101
                        ->canBeUnset()
102
                        ->beforeNormalization()->ifString()->then($this->changeToArrayFromString())->end()
103
                        ->beforeNormalization()->ifTrue($this->isIndexedArray())->then($this->changeToAssoc())->end()
104
                        ->validate()->ifTrue($this->isEmpty())->thenUnset()->end()
105
                        ->validate()->always($this->getChannelTypeValidator())->end()
106
                        ->children()
107
                            ->scalarNode('type')->validate()
108
                                ->ifNotInArray(array('inclusive', 'exclusive'))
109
                                ->thenInvalid('The type of channels has to be inclusive or exclusive')->end()->end()
110
                            ->arrayNode('elements')->prototype('scalar')->end()->end()->end()
111
                        ->end()
112
                    ->end()
113
                ->end()
114
            ->end();
115
    }
116
117
    /**
118
     * @return \Closure
119
     */
120
    private function getChannelTypeValidator()
121
    {
122
        return function ($v) {
123
            $isExclusiveList = isset($v['type']) ? 'exclusive' === $v['type'] : null;
124
            $elements = array();
125
126
            foreach ($v['elements'] as $element) {
127
                Configuration::appendChannelTypes($element, $isExclusiveList, $elements);
128
            }
129
130
            return array('type' => $isExclusiveList ? 'exclusive' : 'inclusive', 'elements' => $elements);
131
        };
132
    }
133
134
    /**
135
     * @param bool $invalid
136
     *
137
     * @throws InvalidConfigurationException
138
     */
139
    public static function throwExceptionOnInvalid($invalid)
140
    {
141
        if (!$invalid) {
142
            return;
143
        }
144
145
        throw new InvalidConfigurationException(
146
            'Cannot combine exclusive/inclusive definitions in channels list'
147
        );
148
    }
149
150
    public static function appendChannelTypes($element, &$isExclusiveList, &$elements = array())
151
    {
152
        $isExclusiveItem = str_starts_with($element, '!');
153
154
        self::throwExceptionOnInvalid(!$isExclusiveItem === $isExclusiveList);
155
156
        $elements[] = $isExclusiveItem ? substr($element, 1) : $element;
157
        $isExclusiveList = $isExclusiveItem;
158
    }
159
160
    /**
161
     * @return \Closure
162
     */
163
    private function isIndexedArray()
164
    {
165
        return function ($v) {
166
            return is_array($v) && is_numeric(key($v));
167
        };
168
    }
169
170
    /**
171
     * @return \Closure
172
     */
173
    private function changeToAssoc()
174
    {
175
        return function ($v) {
176
            return array('elements' => $v);
177
        };
178
    }
179
180
    /**
181
     * @return \Closure
182
     */
183
    private function changeToArrayFromString()
184
    {
185
        return function ($v) {
186
            return array('elements' => array($v));
187
        };
188
    }
189
190
    /**
191
     * @return \Closure
192
     */
193
    private function isEmpty()
194
    {
195
        return function ($v) {
196
            return empty($v);
197
        };
198
    }
199
}
200