Passed
Push — master ( 65f41a...2c251c )
by Allan
02:57 queued 10s
created

BasePathComponent::normalize()   B

Complexity

Conditions 10
Paths 8

Size

Total Lines 84
Code Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 10
eloc 51
c 2
b 0
f 0
nc 8
nop 4
dl 0
loc 84
rs 7.2024

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
 * Copyright © Vaimo Group. All rights reserved.
4
 * See LICENSE_VAIMO.txt for license details.
5
 */
6
namespace Vaimo\ComposerPatches\Patch\Definition\NormalizerComponents;
7
8
use Vaimo\ComposerPatches\Patch\Definition as PatchDefinition;
9
use Vaimo\ComposerPatches\Config as PluginConfig;
10
use Vaimo\ComposerPatches\Composer\Constants as ComposerConstants;
11
12
class BasePathComponent implements \Vaimo\ComposerPatches\Interfaces\DefinitionNormalizerComponentInterface
13
{
14
    /**
15
     * @var \Vaimo\ComposerPatches\Utils\TemplateUtils
16
     */
17
    private $templateUtils;
18
19
    public function __construct()
20
    {
21
        $this->templateUtils = new \Vaimo\ComposerPatches\Utils\TemplateUtils();
22
    }
23
24
    public function normalize($target, $label, array $data, array $ownerConfig)
25
    {
26
        if (!isset($ownerConfig[PluginConfig::PATCHES_BASE])) {
27
            return array();
28
        }
29
30
        $source = $data[PatchDefinition::SOURCE];
31
32
        if (parse_url($source, PHP_URL_SCHEME)) {
33
            return array();
34
        }
35
36
        if (is_numeric($label) && isset($data[PatchDefinition::LABEL])) {
37
            $label = $data[PatchDefinition::LABEL];
38
        }
39
40
        if (strpos($data[PatchDefinition::PATH], DIRECTORY_SEPARATOR) === 0
41
            && file_exists($data[PatchDefinition::PATH])
42
        ) {
43
            return array(
44
                PatchDefinition::LABEL => $label,
45
                PatchDefinition::SOURCE => $source
46
            );
47
        }
48
49
        $template = $this->resolveTemplate($ownerConfig, $target);
50
        
51
        list ($sourcePath, $sourceTags) = $this->deconstructSource($source);
52
53
        $nameParts = explode(ComposerConstants::PACKAGE_SEPARATOR, $target);
54
55
        $pathVariables = array(
56
            'file' => $sourcePath,
57
            'vendor' => array_shift($nameParts),
58
            'package' => implode(ComposerConstants::PACKAGE_SEPARATOR, $nameParts),
59
            'label' => $label
60
        );
61
62
        $mutationNamesMap = array(
63
            'file' => 'file name',
64
            'vendor' => 'vendor name',
65
            'package' => 'module name',
66
            'label' => 'label value'
67
        );
68
        
69
        $extraVariables = array(
70
            'version' => preg_replace(
71
                '/[^A-Za-z0-9.-]/',
72
                '',
73
                strtok(reset($data[PatchDefinition::DEPENDS]) ?: '0.0.0', ' ')
74
            ),
75
            'file' => $sourcePath,
76
            'label' => $label
77
        );
78
79
        $variablePattern = '{{%s}}';
80
81
        $pathVariables = $this->expandPathVariables($pathVariables, $mutationNamesMap);
82
83
        $templateVariables = $this->prepareTemplateValues(
84
            $template,
85
            $variablePattern,
86
            array_replace($pathVariables, $extraVariables)
87
        );
88
89
        $sourcePath = $this->templateUtils->compose(
90
            $template . ($sourceTags ? ('#' . $sourceTags) : ''),
91
            $templateVariables,
92
            array_fill_keys(array($variablePattern), array())
93
        );
94
95
        $filename = basename($sourcePath);
96
97
        if (substr($label, -strlen($filename)) === $filename) {
98
            $label = str_replace(
99
                $filename,
100
                preg_replace('/\s{2,}/', ' ', preg_replace('/[^A-Za-z0-9]/', ' ', strtok($filename, '.'))),
101
                $label
102
            );
103
        }
104
105
        return array(
106
            PatchDefinition::LABEL => $label,
107
            PatchDefinition::SOURCE => $source
108
        );
109
    }
110
    
111
    private function deconstructSource($source)
112
    {
113
        $sourceTags = '';
114
115
        if (strpos($source, '#') !== false) {
116
            $sourceSegments = explode('#', $source);
117
118
            $sourceTags = array_pop($sourceSegments);
119
            $source = implode('#', $sourceSegments);
120
        }
121
        
122
        return array($source, $sourceTags);
123
    }
124
    
125
    private function prepareTemplateValues($template, $variablePattern, $variableValues)
126
    {
127
        $mutationRules = $this->templateUtils->collectValueMutationRules(
128
            $template,
129
            array($variablePattern)
130
        );
131
132
        return array_replace(
133
            $this->templateUtils->applyMutations(
134
                $variableValues,
135
                $mutationRules,
136
                ' :-_.'
137
            ),
138
            $variableValues
139
        );
140
    }
141
    
142
    private function expandPathVariables(array $pathVariables, array $mutationNamesMap)
143
    {
144
        $normalizedVariables = array_map(function ($part) {
145
            $part = strtolower(
146
                preg_replace(
147
                    array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'),
148
                    array('\\1_\\2', '\\1_\\2'),
149
                    str_replace('_', '.', $part)
150
                )
151
            );
152
153
            return preg_replace('/\s{2,}/', ' ', str_replace(array(' ', '_', '-', '.', '/', ':'), ' ', $part));
154
        }, $pathVariables);
155
156
        $mutationAppliers = $this->createMutationAppliers();
157
158
        $pathVariables = array();
159
160
        foreach ($normalizedVariables as $name => $value) {
161
            $variableName = $mutationNamesMap[$name];
162
163
            foreach ($mutationAppliers as $mutationApplier) {
164
                $mutationName = $mutationApplier($variableName);
165
                $pathVariables[$mutationName] = $mutationApplier($value);
166
            }
167
        }
168
        
169
        return $pathVariables;
170
    }
171
172
    private function resolveTemplate($ownerConfig, $packageName)
173
    {
174
        $templates = $ownerConfig[PluginConfig::PATCHES_BASE];
175
176
        $vendorName = strtok($packageName, ComposerConstants::PACKAGE_SEPARATOR);
177
178
        if (is_array($templates)) {
179
            if (isset($templates[$packageName])) {
180
                return $templates[$packageName];
181
            } elseif (isset($templates[$vendorName])) {
182
                return $templates[$vendorName];
183
            } elseif ($templates[PluginConfig::PATCHES_BASE_DEFAULT]) {
184
                return $templates[PluginConfig::PATCHES_BASE_DEFAULT];
185
            }
186
187
            return reset($templates);
188
        }
189
190
        return $templates;
191
    }
192
193
    private function createMutationAppliers()
194
    {
195
        return array(
196
            function ($value) {
197
                return str_replace(' ', '', $value);
198
            },
199
            function ($value) {
200
                return str_replace(' ', '', ucwords($value));
201
            },
202
            function ($value) {
203
                return str_replace(' ', '', ucfirst($value));
204
            },
205
            function ($value) {
206
                return str_replace(' ', '-', $value);
207
            },
208
            function ($value) {
209
                return str_replace(' ', '_', $value);
210
            },
211
        );
212
    }
213
}
214