Passed
Push — master ( b12c89...119ef1 )
by Allan
02:13
created

BasePathComponent::normalize()   B

Complexity

Conditions 9
Paths 6

Size

Total Lines 74
Code Lines 45

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 45
nc 6
nop 4
dl 0
loc 74
rs 7.6444
c 2
b 0
f 0

How to fix   Long Method   

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
        return array(
96
            PatchDefinition::LABEL => $this->normalizeLabelForSourcePath($label, $sourcePath),
97
            PatchDefinition::SOURCE => $sourcePath
98
        );
99
    }
100
    
101
    private function normalizeLabelForSourcePath($label, $sourcePath)
102
    {
103
        $filename = basename($sourcePath);
104
105
        if (substr($label, -strlen($filename)) === $filename) {
106
            return str_replace(
107
                $filename,
108
                preg_replace('/\s{2,}/', ' ', preg_replace('/[^A-Za-z0-9]/', ' ', strtok($filename, '.'))),
109
                $label
110
            );
111
        }
112
        
113
        return $label;
114
    }
115
    
116
    private function deconstructSource($source)
117
    {
118
        $sourceTags = '';
119
120
        if (strpos($source, '#') !== false) {
121
            $sourceSegments = explode('#', $source);
122
123
            $sourceTags = array_pop($sourceSegments);
124
            $source = implode('#', $sourceSegments);
125
        }
126
        
127
        return array($source, $sourceTags);
128
    }
129
    
130
    private function prepareTemplateValues($template, $variablePattern, $variableValues)
131
    {
132
        $mutationRules = $this->templateUtils->collectValueMutationRules(
133
            $template,
134
            array($variablePattern)
135
        );
136
137
        return array_replace(
138
            $this->templateUtils->applyMutations(
139
                $variableValues,
140
                $mutationRules,
141
                ' :-_.'
142
            ),
143
            $variableValues
144
        );
145
    }
146
    
147
    private function expandPathVariables(array $pathVariables, array $mutationNamesMap)
148
    {
149
        $normalizedVariables = array_map(function ($part) {
150
            $part = strtolower(
151
                preg_replace(
152
                    array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'),
153
                    array('\\1_\\2', '\\1_\\2'),
154
                    str_replace('_', '.', $part)
155
                )
156
            );
157
158
            return preg_replace('/\s{2,}/', ' ', str_replace(array(' ', '_', '-', '.', '/', ':'), ' ', $part));
159
        }, $pathVariables);
160
161
        $mutationAppliers = $this->createMutationAppliers();
162
163
        $pathVariables = array();
164
165
        foreach ($normalizedVariables as $name => $value) {
166
            $variableName = $mutationNamesMap[$name];
167
168
            foreach ($mutationAppliers as $mutationApplier) {
169
                $mutationName = $mutationApplier($variableName);
170
                $pathVariables[$mutationName] = $mutationApplier($value);
171
            }
172
        }
173
        
174
        return $pathVariables;
175
    }
176
177
    private function resolveTemplate($ownerConfig, $packageName)
178
    {
179
        $templates = $ownerConfig[PluginConfig::PATCHES_BASE];
180
181
        $vendorName = strtok($packageName, ComposerConstants::PACKAGE_SEPARATOR);
182
183
        if (is_array($templates)) {
184
            if (isset($templates[$packageName])) {
185
                return $templates[$packageName];
186
            } elseif (isset($templates[$vendorName])) {
187
                return $templates[$vendorName];
188
            } elseif ($templates[PluginConfig::PATCHES_BASE_DEFAULT]) {
189
                return $templates[PluginConfig::PATCHES_BASE_DEFAULT];
190
            }
191
192
            return reset($templates);
193
        }
194
195
        return $templates;
196
    }
197
198
    private function createMutationAppliers()
199
    {
200
        return array(
201
            function ($value) {
202
                return str_replace(' ', '', $value);
203
            },
204
            function ($value) {
205
                return str_replace(' ', '', ucwords($value));
206
            },
207
            function ($value) {
208
                return str_replace(' ', '', ucfirst($value));
209
            },
210
            function ($value) {
211
                return str_replace(' ', '-', $value);
212
            },
213
            function ($value) {
214
                return str_replace(' ', '_', $value);
215
            },
216
        );
217
    }
218
}
219