ConfigResolverParameterPass::process()   F
last analyzed

Complexity

Conditions 17
Paths 567

Size

Total Lines 91

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
nc 567
nop 1
dl 0
loc 91
rs 1.5174
c 0
b 0
f 0

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
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Compiler;
8
9
use eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\DynamicSettingParserInterface;
10
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
11
use Symfony\Component\DependencyInjection\ContainerBuilder;
12
use Symfony\Component\DependencyInjection\Reference;
13
use Symfony\Component\ExpressionLanguage\Expression;
14
15
/**
16
 * This compiler pass will resolve config resolver parameters, delimited by $ chars (e.g. $my_parameter$).
17
 * It will replace those parameters by fake services having the config resolver as factory.
18
 * The factory method will then return the right value, at runtime.
19
 *
20
 * Supported syntax for parameters: $<paramName>[;<namespace>[;<scope>]]$
21
 *
22
 * @see \eZ\Bundle\EzPublishCoreBundle\DependencyInjection\Configuration\SiteAccessAware\DynamicSettingParserInterface
23
 */
24
class ConfigResolverParameterPass implements CompilerPassInterface
25
{
26
    /** @var DynamicSettingParserInterface */
27
    private $dynamicSettingParser;
28
29
    public function __construct(DynamicSettingParserInterface $dynamicSettingParser)
30
    {
31
        $this->dynamicSettingParser = $dynamicSettingParser;
32
    }
33
34
    public function process(ContainerBuilder $container)
35
    {
36
        $dynamicSettingsServices = [];
37
        $resettableServices = [];
38
        $updateableServices = $container->getParameter('ezpublish.config_resolver.updateable_services');
39
        // Pass #1 Loop against all arguments of all service definitions to replace dynamic settings by the fake service.
40
        foreach ($container->getDefinitions() as $serviceId => $definition) {
41
            // Constructor injection
42
            $replaceArguments = [];
43
            foreach ($definition->getArguments() as $i => $arg) {
44
                if (!$this->dynamicSettingParser->isDynamicSetting($arg)) {
45
                    continue;
46
                }
47
48
                // Decorators use index_X for their key
49
                if (strpos($i, 'index') === 0) {
50
                    $i = (int)substr($i, strlen('index_'));
51
                }
52
53
                $replaceArguments[$i] = $this->createExpression($this->dynamicSettingParser->parseDynamicSetting($arg));
54
            }
55
56
            if (!empty($replaceArguments)) {
57
                $dynamicSettingsServices[$serviceId] = true;
58
                foreach ($replaceArguments as $i => $arg) {
59
                    $definition->replaceArgument($i, $arg);
60
                }
61
            }
62
63
            // Setter injection
64
            $methodCalls = $definition->getMethodCalls();
65
            foreach ($methodCalls as $i => &$call) {
66
                list($method, $callArgs) = $call;
67
                $callHasDynamicSetting = false;
68
                foreach ($callArgs as &$callArg) {
69
                    if (!$this->dynamicSettingParser->isDynamicSetting($callArg)) {
70
                        continue;
71
                    }
72
73
                    $callArg = $this->createExpression($this->dynamicSettingParser->parseDynamicSetting($callArg));
74
                    $callHasDynamicSetting = true;
75
                }
76
77
                $call = [$method, $callArgs];
78
                if ($callHasDynamicSetting) {
79
                    // We only support single dynamic setting injection for updatable services.
80
                    if (count($callArgs) == 1) {
81
                        $updateableServices[$serviceId][] = [$method, (string)$callArgs[0]];
82
                    } else {
83
                        // Method call has more than 1 argument, so we will reset it instead of updating it.
84
                        $dynamicSettingsServices[$serviceId] = true;
85
                        // Ensure current service is not registered as updatable service.
86
                        unset($updateableServices[$serviceId]);
87
                    }
88
                }
89
            }
90
91
            $definition->setMethodCalls($methodCalls);
92
        }
93
94
        // Pass #2 Loop again, to get all services depending on dynamic settings services.
95
        foreach ($container->getDefinitions() as $id => $definition) {
96
            $isDependent = false;
97
            foreach ($definition->getArguments() as $arg) {
98
                if (
99
                    !(
100
                        $arg instanceof Reference
101
                        && isset($dynamicSettingsServices[(string)$arg])
102
                    )
103
                ) {
104
                    continue;
105
                }
106
107
                $isDependent = true;
108
                break;
109
            }
110
111
            if ($isDependent) {
112
                $resettableServices[] = $id;
113
            }
114
        }
115
116
        $resettableServices = array_unique(
117
            array_merge(
118
                array_keys($dynamicSettingsServices),
119
                $resettableServices
120
            )
121
        );
122
        $container->setParameter('ezpublish.config_resolver.resettable_services', $resettableServices);
123
        $container->setParameter('ezpublish.config_resolver.updateable_services', $updateableServices);
124
    }
125
126
    /**
127
     * Returns the expression object corresponding to passed dynamic setting.
128
     *
129
     * @param array $dynamicSetting Parsed dynamic setting, as returned by DynamicSettingParser.
130
     *
131
     * @return Expression
132
     */
133 View Code Duplication
    private function createExpression(array $dynamicSetting)
134
    {
135
        $expression = sprintf(
136
            'service("ezpublish.config.resolver").getParameter("%s", %s, %s)',
137
            $dynamicSetting['param'],
138
            isset($dynamicSetting['namespace']) ? '"' . $dynamicSetting['namespace'] . '"' : 'null',
139
            isset($dynamicSetting['scope']) ? '"' . $dynamicSetting['scope'] . '"' : 'null'
140
        );
141
142
        return new Expression($expression);
143
    }
144
}
145