Passed
Push — develop ( da1ef5...333d24 )
by Mikaël
08:52
created

Utils   F

Complexity

Total Complexity 75

Size/Duplication

Total Lines 236
Duplicated Lines 0 %

Test Coverage

Coverage 99.1%

Importance

Changes 2
Bugs 0 Features 2
Metric Value
eloc 123
dl 0
loc 236
ccs 110
cts 111
cp 0.991
rs 2.4
c 2
b 0
f 2
wmc 75

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getContentFromUrl() 0 9 2
C getPart() 0 53 12
C getValueWithinItsType() 0 29 13
F resolveCompletePath() 0 37 25
A createDirectory() 0 7 2
A cleanComment() 0 7 5
A cleanString() 0 8 2
A removeNamespace() 0 5 1
B getStreamContextOptions() 0 22 7
A saveSchemas() 0 22 6

How to fix   Complexity   

Complex Class

Complex classes like Utils often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Utils, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare(strict_types=1);
4
5
namespace WsdlToPhp\PackageGenerator\Generator;
6
7
use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
8
9
final class Utils
10
{
11
    /**
12
     * Gets upper case word among a string from the end or from the beginning part.
13
     */
14 170
    public static function getPart(string $optionValue, string $string): string
15
    {
16 170
        $string = str_replace('_', '', $string);
17 170
        $string = preg_replace('/([0-9])/', '', $string);
18
19 170
        if (empty($string)) {
20 2
            return '';
21
        }
22
23 170
        $elementType = '';
24
25
        switch ($optionValue) {
26 170
            case GeneratorOptions::VALUE_END:
27 8
                $parts = preg_split('/[A-Z]/', ucfirst($string));
28 8
                $partsCount = count($parts);
29 8
                if (!empty($parts[$partsCount - 1])) {
30 6
                    $elementType = mb_substr($string, mb_strrpos($string, implode('', array_slice($parts, -1))) - 1);
31
                } else {
32 2
                    for ($i = $partsCount - 1; $i >= 0; --$i) {
33 2
                        $part = trim($parts[$i]);
34 2
                        if (!empty($part)) {
35
                            break;
36
                        }
37
                    }
38 2
                    $elementType = mb_substr($string, ((count($parts) - 2 - $i) + 1) * -1);
39
                }
40
41 8
                break;
42
43 162
            case GeneratorOptions::VALUE_START:
44 154
                $parts = preg_split('/[A-Z]/', ucfirst($string));
45 154
                $partsCount = count($parts);
46 154
                if (empty($parts[0]) && !empty($parts[1])) {
47 154
                    $elementType = mb_substr($string, 0, mb_strlen($parts[1]) + 1);
48
                } else {
49 6
                    for ($i = 0; $i < $partsCount; ++$i) {
50 6
                        $part = trim($parts[$i]);
51 6
                        if (!empty($part)) {
52 6
                            break;
53
                        }
54
                    }
55 6
                    $elementType = mb_substr($string, 0, $i);
56
                }
57
58 154
                break;
59
60 8
            case GeneratorOptions::VALUE_NONE:
61 8
                $elementType = $string;
62
63 8
                break;
64
        }
65
66 170
        return $elementType;
67
    }
68
69 4
    public static function getContentFromUrl(string $url, ?string $basicAuthLogin = null, ?string $basicAuthPassword = null, ?string $proxyHost = null, $proxyPort = null, ?string $proxyLogin = null, ?string $proxyPassword = null, array $contextOptions = []): string
70
    {
71 4
        $context = null;
72 4
        $options = self::getStreamContextOptions($basicAuthLogin, $basicAuthPassword, $proxyHost, $proxyPort, $proxyLogin, $proxyPassword, $contextOptions);
73 4
        if (!empty($options)) {
74 4
            $context = stream_context_create($options);
75
        }
76
77 4
        return file_get_contents($url, false, $context);
78
    }
79
80 16
    public static function getStreamContextOptions(?string $basicAuthLogin = null, ?string $basicAuthPassword = null, ?string $proxyHost = null, $proxyPort = null, ?string $proxyLogin = null, ?string $proxyPassword = null, array $contextOptions = []): array
81
    {
82 16
        $applyHttpHeader = function (array $contextOptions, string $header): array {
83 10
            if (!isset($contextOptions['http']['header']) || !in_array($header, $contextOptions['http']['header'])) {
84 8
                $contextOptions['http']['header'][] = $header;
85
            }
86
87 10
            return $contextOptions;
88
        };
89
90 16
        if (!empty($basicAuthLogin) && !empty($basicAuthPassword)) {
91 8
            $authorizationHeader = sprintf('Authorization: Basic %s', base64_encode(sprintf('%s:%s', $basicAuthLogin, $basicAuthPassword)));
92 8
            $contextOptions = $applyHttpHeader($contextOptions, $authorizationHeader);
93
        }
94
95 16
        if (!empty($proxyHost)) {
96 8
            $contextOptions['http']['proxy'] = sprintf('tcp://%s%s', $proxyHost, empty($proxyPort) ? '' : sprintf(':%s', $proxyPort));
97 8
            $proxyAuthorizationHeader = sprintf('Proxy-Authorization: Basic %s', base64_encode(sprintf('%s:%s', $proxyLogin, $proxyPassword)));
98 8
            $contextOptions = $applyHttpHeader($contextOptions, $proxyAuthorizationHeader);
99
        }
100
101 16
        return $contextOptions;
102
    }
103
104 106
    public static function getValueWithinItsType($value, ?string $knownType = null)
105
    {
106 106
        if (is_int($value) || (!is_null($value) && in_array($knownType, [
107
            'time',
108
            'positiveInteger',
109
            'unsignedLong',
110
            'unsignedInt',
111
            'short',
112
            'long',
113
            'int',
114
            'integer',
115
        ], true))) {
116 6
            return intval($value);
117
        }
118 106
        if (is_float($value) || (!is_null($value) && in_array($knownType, [
119
            'float',
120
            'double',
121
            'decimal',
122
        ], true))) {
123 2
            return floatval($value);
124
        }
125 106
        if (is_bool($value) || (!is_null($value) && in_array($knownType, [
126
            'bool',
127
            'boolean',
128
        ], true))) {
129 6
            return 'true' === $value || true === $value || 1 === $value || '1' === $value;
130
        }
131
132 102
        return $value;
133
    }
134
135 70
    public static function resolveCompletePath(string $origin, string $destination): string
136
    {
137 70
        $resolvedPath = $destination;
138 70
        if (!empty($destination) && false === mb_strpos($destination, 'http://') && false === mb_strpos($destination, 'https://') && !empty($origin)) {
139 70
            if ('./' === mb_substr($destination, 0, 2)) {
140 4
                $destination = mb_substr($destination, 2);
141
            }
142 70
            $destinationParts = explode('/', $destination);
143 70
            $fileParts = pathinfo($origin);
144 70
            $fileBasename = (is_array($fileParts) && array_key_exists('basename', $fileParts)) ? $fileParts['basename'] : '';
145 70
            $parts = parse_url(str_replace('/'.$fileBasename, '', $origin));
146 70
            $scheme = (is_array($parts) && array_key_exists('scheme', $parts)) ? $parts['scheme'] : '';
147 70
            $host = (is_array($parts) && array_key_exists('host', $parts)) ? $parts['host'] : '';
148 70
            $path = (is_array($parts) && array_key_exists('path', $parts)) ? $parts['path'] : '';
149 70
            $path = str_replace('/'.$fileBasename, '', $path);
150 70
            $pathParts = explode('/', $path);
151 70
            $finalPath = implode('/', $pathParts);
152 70
            foreach ($destinationParts as $locationPart) {
153 70
                if ('..' === $locationPart) {
154 4
                    $finalPath = mb_substr($finalPath, 0, mb_strrpos($finalPath, '/', 0));
155
                } else {
156 70
                    $finalPath .= '/'.$locationPart;
157
                }
158
            }
159 70
            $port = (is_array($parts) && array_key_exists('port', $parts)) ? $parts['port'] : '';
160
            // Remote file
161 70
            if (!empty($scheme) && !empty($host)) {
162 2
                $resolvedPath = str_replace('urn', 'http', $scheme).'://'.$host.(!empty($port) ? ':'.$port : '').str_replace('//', '/', $finalPath);
163 68
            } elseif (empty($scheme) && empty($host) && count($pathParts)) {
164
                // Local file
165 68
                if (is_file($finalPath)) {
166 68
                    $resolvedPath = $finalPath;
167
                }
168
            }
169
        }
170
171 70
        return $resolvedPath;
172
    }
173
174 120
    public static function cleanComment($comment, string $glueSeparator = ',', bool $uniqueValues = true): string
175
    {
176 120
        if (!is_scalar($comment) && !is_array($comment)) {
177 2
            return '';
178
        }
179
180 118
        return trim(str_replace('*/', '*[:slash:]', is_scalar($comment) ? (string) $comment : implode($glueSeparator, $uniqueValues ? array_unique($comment) : $comment)));
181
    }
182
183
    /**
184
     * Clean a string to make it valid as PHP variable
185
     * See more about the used regular expression at {@link http://www.regular-expressions.info/unicode.html}:
186
     * - \p{L} for any valid letter
187
     * - \p{N} for any valid number
188
     * - /u for supporting unicode.
189
     *
190
     * @param string $string                  the string to clean
191
     * @param bool   $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
192
     */
193 420
    public static function cleanString(string $string, bool $keepMultipleUnderscores = true): string
194
    {
195 420
        $cleanedString = preg_replace('/[^\p{L}\p{N}_]/u', '_', $string);
196 420
        if (!$keepMultipleUnderscores) {
197 118
            $cleanedString = preg_replace('/[_]+/', '_', $cleanedString);
198
        }
199
200 420
        return $cleanedString;
201
    }
202
203 146
    public static function removeNamespace(string $namespacedClassName): string
204
    {
205 146
        $elements = explode('\\', $namespacedClassName);
206
207 146
        return (string) array_pop($elements);
208
    }
209
210 170
    public static function createDirectory(string $directory, $permissions = 0775): bool
211
    {
212 170
        if (!is_dir($directory)) {
213 10
            mkdir($directory, $permissions, true);
214
        }
215
216 170
        return true;
217
    }
218
219
    /**
220
     * Save schemas to schemasFolder
221
     * Filename will be extracted from schemasUrl or default schema.wsdl will be used.
222
     */
223 4
    public static function saveSchemas(string $destinationFolder, string $schemasFolder, string $schemasUrl, string $content): string
224
    {
225 4
        if ((is_null($schemasFolder)) || empty($schemasFolder)) {
226
            // if null or empty schemas folder was provided
227
            // default schemas folder will be wsdl
228 2
            $schemasFolder = 'wsdl';
229
        }
230 4
        $schemasPath = rtrim($destinationFolder, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.rtrim($schemasFolder, DIRECTORY_SEPARATOR);
231
232
        // Here we must cover all possible variants
233 4
        if ((false !== mb_strpos(mb_strtolower($schemasUrl), '.wsdl')) || (false !== mb_strpos(mb_strtolower($schemasUrl), '.xsd')) || (false !== mb_strpos(mb_strtolower($schemasUrl), '.xml'))) {
234 4
            $filename = basename($schemasUrl);
235
        } else {
236
            // if $url is like http://example.com/index.php?WSDL default filename will be schema.wsdl
237 2
            $filename = 'schema.wsdl';
238
        }
239
240 4
        self::createDirectory($schemasPath);
241
242 4
        file_put_contents($schemasPath.DIRECTORY_SEPARATOR.$filename, $content);
243
244 4
        return $schemasPath.DIRECTORY_SEPARATOR.$filename;
245
    }
246
}
247