Completed
Push — master ( b77c5c...4fbeac )
by Jeroen
10s
created

YamlConfig   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 206
Duplicated Lines 2.43 %

Coupling/Cohesion

Components 1
Dependencies 3

Test Coverage

Coverage 72%

Importance

Changes 0
Metric Value
wmc 29
lcom 1
cbo 3
dl 5
loc 206
ccs 54
cts 75
cp 0.72
rs 10
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 11 2
A getConfig() 0 6 1
A getFile() 0 4 1
A process() 0 13 2
A load() 0 8 2
A compile() 0 11 2
B replaceParameters() 0 14 5
A expandTasksTargetGroups() 0 16 2
C expandTasksTargetGroupsForSection() 5 32 8
A flatten() 0 6 1
A setParameter() 0 14 3

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the Conveyor package.
5
 *
6
 * (c) Jeroen Fiege <[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 Webcreate\Conveyor\Config;
13
14
use Symfony\Component\Config\Definition\Processor;
15
use Symfony\Component\Yaml\Yaml;
16
use Webcreate\Conveyor\Config\Definition\DeployConfiguration;
17
use Webcreate\Conveyor\Factory\StrategyFactory;
18
use Webcreate\Conveyor\Factory\TaskFactory;
19
use Webcreate\Conveyor\Factory\TransporterFactory;
20
use Webcreate\Conveyor\Util\ArrayUtil;
21
22
/**
23
 * @todo refactor getConfig() method: might want to implement \ArrayAccess interface
24
 */
25
class YamlConfig
26
{
27
    protected $processedConfig;
28
    protected $loadedConfig;
29
    protected $compiledConfig;
30
    protected $parameters = array();
31
    protected $taskFactory;
32
    protected $transporterFactory;
33
    protected $strategyFactory;
34
    protected $file;
35
36
    /**
37
     * Constructor.
38
     *
39
     * @param  string                    $file
40
     * @param  TaskFactory               $taskFactory
41
     * @param  TransporterFactory        $transporterFactory
42
     * @param  StrategyFactory           $strategyFactory
43
     * @throws \InvalidArgumentException
44
     */
45 3
    public function __construct($file, TaskFactory $taskFactory, TransporterFactory $transporterFactory, StrategyFactory $strategyFactory)
46
    {
47 3
        if (!file_exists($file)) {
48 2
            throw new \InvalidArgumentException(sprintf('File %s does not exists', $file));
49
        }
50
51 1
        $this->file               = $file;
52 1
        $this->taskFactory        = $taskFactory;
53 1
        $this->transporterFactory = $transporterFactory;
54 1
        $this->strategyFactory    = $strategyFactory;
55 1
    }
56
57
    /**
58
     * @return array
59
     */
60 1
    public function getConfig()
61
    {
62 1
        $this->compile();
63
64 1
        return $this->compiledConfig;
65
    }
66
67
    /**
68
     * @return string
69
     */
70
    public function getFile()
71
    {
72
        return $this->file;
73
    }
74
75
    /**
76
     * @return array
77
     */
78 1
    protected function process()
79
    {
80 1
        if (null === $this->processedConfig) {
81 1
            $this->load();
82
83 1
            $configuration = new DeployConfiguration($this->taskFactory, $this->transporterFactory, $this->strategyFactory);
84 1
            $processor = new Processor();
85
86 1
            $this->processedConfig = $processor->processConfiguration($configuration, $this->loadedConfig);
0 ignored issues
show
Bug introduced by
It seems like $this->loadedConfig can also be of type string; however, Symfony\Component\Config...:processConfiguration() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
87
        }
88
89 1
        return $this->processedConfig;
90
    }
91
92
    /**
93
     * @return array
94
     */
95 1
    protected function load()
96
    {
97 1
        if (null === $this->loadedConfig) {
98 1
            $this->loadedConfig = Yaml::parse($this->file);
99
        }
100
101 1
        return $this->loadedConfig;
102
    }
103
104
    /**
105
     * @return mixed
106
     */
107 1
    protected function compile()
108
    {
109 1
        if (null === $this->compiledConfig) {
110 1
            $this->process();
111
112 1
            $this->compiledConfig = $this->replaceParameters($this->processedConfig, $this->parameters);
113 1
            $this->compiledConfig = $this->expandTasksTargetGroups($this->compiledConfig);
114
        }
115
116 1
        return $this->compiledConfig;
117
    }
118
119
    /**
120
     * @param  array $config
121
     * @param  array $parameters
122
     * @return array
123
     */
124 1
    protected function replaceParameters(array $config, array $parameters)
125
    {
126 1
        foreach ($config as &$value) {
127 1
            if (is_array($value)) {
128 1
                $value = $this->replaceParameters($value, $parameters);
129 1
            } elseif (is_string($value)) {
130 1
                foreach ($parameters as $key => $val) {
131 1
                    $value = str_replace(sprintf('{{%s}}', $key), $val, $value);
132
                }
133
            }
134
        }
135
136 1
        return $config;
137
    }
138
139
    /**
140
     * Expand target groups
141
     *
142
     * @param array $config
143
     * @return array
144
     */
145 1
    protected function expandTasksTargetGroups(array $config)
146
    {
147
        $sections = array(
148 1
            &$config['build']['tasks'],
149 1
            &$config['deploy']['before'],
150 1
            &$config['deploy']['after'],
151 1
            &$config['deploy']['final'],
152 1
            &$config['undeploy']['tasks'],
153
        );
154
155 1
        foreach ($sections as &$section) {
156 1
            $section = $this->expandTasksTargetGroupsForSection($config, $section);
157
        }
158
159 1
        return $config;
160
    }
161
162
    /**
163
     * Expand target groups for a certain section
164
     *
165
     * @param array $config
166
     * @param array $section
167
     * @return array
168
     */
169 1
    protected function expandTasksTargetGroupsForSection(array $config, array $section = null)
170
    {
171 1
        if (null === $section) {
172 1
            return $section;
173
        }
174
175 1
        $groups = array();
176 1 View Code Duplication
        foreach ($config['targets'] as $targetName => $targetConfig) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
177 1
            foreach ($targetConfig['groups'] as $group) {
178 1
                $groups[$group][] = $targetName;
179
            }
180
        }
181
182 1
        foreach ($section as &$taskConfig) {
183
            $targets = $taskConfig['targets'];
184
            $expandedTargets = array();
185
186
            foreach ($targets as $target) {
187
                if (isset($groups[$target])) {
188
                    foreach ($groups[$target] as $groupTarget) {
189
                        $expandedTargets[] = $groupTarget;
190
                    }
191
                } else {
192
                    $expandedTargets[] = $target;
193
                }
194
            }
195
196
            $taskConfig['targets'] = $expandedTargets;
197
        }
198
199 1
        return $section;
200
    }
201
202
    /**
203
     * @return array
204
     */
205
    public function flatten()
206
    {
207
        $util = new ArrayUtil();
208
209
        return $util->flatten($this->getConfig());
210
    }
211
212
    /**
213
     * @param string $name
214
     * @param mixed  $value
215
     */
216
    public function setParameter($name, $value)
217
    {
218
        $this->process();
219
220
        $this->parameters[$name] = $value;
221
222
        if ('target' === $name) {
223
            foreach ($this->processedConfig['targets'][$value]['parameters'] as $key => $value) {
224
                $this->setParameter('target.' . $key, $value);
225
            }
226
        }
227
228
        $this->compiledConfig = null;
229
    }
230
}
231