Utils   F
last analyzed

Complexity

Total Complexity 80

Size/Duplication

Total Lines 230
Duplicated Lines 0 %

Test Coverage

Coverage 99.18%

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 117
c 1
b 0
f 1
dl 0
loc 230
ccs 121
cts 122
cp 0.9918
rs 2
wmc 80

10 Methods

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

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 = is_countable($parts) ? count($parts) : 0;
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, (((is_countable($parts) ? count($parts) : 0) - 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 = is_countable($parts) ? count($parts) : 0;
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 16
        };
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 120
    public static function getValueWithinItsType($value, ?string $knownType = null)
105
    {
106 120
        if (is_int($value) || (!is_null($value) && in_array($knownType, [
107 120
            'int',
108 120
            'integer',
109 120
        ], true))) {
110 8
            return (int) $value;
111
        }
112 120
        if (is_float($value) || (!is_null($value) && in_array($knownType, [
113 120
            'float',
114 120
            'double',
115 120
            'decimal',
116 120
        ], true))) {
117 2
            return (float) $value;
118
        }
119 120
        if (is_bool($value) || (!is_null($value) && in_array($knownType, [
120 120
            'bool',
121 120
            'boolean',
122 120
        ], true))) {
123 6
            return 'true' === $value || true === $value || 1 === $value || '1' === $value;
124
        }
125
126 116
        return $value;
127
    }
128
129 70
    public static function resolveCompletePath(string $origin, string $destination): string
130
    {
131 70
        $resolvedPath = $destination;
132 70
        if (!empty($destination) && false === mb_strpos($destination, 'http://') && false === mb_strpos($destination, 'https://') && !empty($origin)) {
133 70
            if ('./' === mb_substr($destination, 0, 2)) {
134 4
                $destination = mb_substr($destination, 2);
135
            }
136 70
            $destinationParts = explode('/', $destination);
137 70
            $fileParts = pathinfo($origin);
138 70
            $fileBasename = (is_array($fileParts) && array_key_exists('basename', $fileParts)) ? $fileParts['basename'] : '';
139 70
            $parts = parse_url(str_replace('/'.$fileBasename, '', $origin));
140 70
            $scheme = (is_array($parts) && array_key_exists('scheme', $parts)) ? $parts['scheme'] : '';
141 70
            $host = (is_array($parts) && array_key_exists('host', $parts)) ? $parts['host'] : '';
142 70
            $path = (is_array($parts) && array_key_exists('path', $parts)) ? $parts['path'] : '';
143 70
            $path = str_replace('/'.$fileBasename, '', $path);
144 70
            $pathParts = explode('/', $path);
145 70
            $finalPath = implode('/', $pathParts);
146 70
            foreach ($destinationParts as $locationPart) {
147 70
                if ('..' === $locationPart) {
148 4
                    $finalPath = mb_substr($finalPath, 0, mb_strrpos($finalPath, '/', 0));
149
                } else {
150 70
                    $finalPath .= '/'.$locationPart;
151
                }
152
            }
153 70
            $port = (is_array($parts) && array_key_exists('port', $parts)) ? $parts['port'] : '';
154
            // Remote file
155 70
            if (!empty($scheme) && !empty($host)) {
156 2
                $resolvedPath = str_replace('urn', 'http', $scheme).'://'.$host.(!empty($port) ? ':'.$port : '').str_replace('//', '/', $finalPath);
157 68
            } elseif (empty($scheme) && empty($host) && count($pathParts)) {
158
                // Local file
159 68
                if (is_file($finalPath)) {
160 68
                    $resolvedPath = $finalPath;
161
                }
162
            }
163
        }
164
165 70
        return $resolvedPath;
166
    }
167
168 128
    public static function cleanComment($comment, string $glueSeparator = ',', bool $uniqueValues = true): string
169
    {
170 128
        if (!is_scalar($comment) && !is_array($comment)) {
171 2
            return '';
172
        }
173
174 126
        return trim(str_replace('*/', '*[:slash:]', is_scalar($comment) ? (string) $comment : implode($glueSeparator, $uniqueValues ? array_unique($comment) : $comment)));
175
    }
176
177
    /**
178
     * Clean a string to make it valid as PHP variable
179
     * See more about the used regular expression at {@link http://www.regular-expressions.info/unicode.html}:
180
     * - \p{L} for any valid letter
181
     * - \p{N} for any valid number
182
     * - /u for supporting unicode.
183
     *
184
     * @param string $string                  the string to clean
185
     * @param bool   $keepMultipleUnderscores optional, allows to keep the multiple consecutive underscores
186
     */
187 430
    public static function cleanString(string $string, bool $keepMultipleUnderscores = true): string
188
    {
189 430
        $cleanedString = preg_replace('/[^\p{L}\p{N}_]/u', '_', $string);
190 430
        if (!$keepMultipleUnderscores) {
191 126
            $cleanedString = preg_replace('/[_]+/', '_', $cleanedString);
192
        }
193
194 430
        return $cleanedString;
195
    }
196
197 156
    public static function removeNamespace(string $namespacedClassName): string
198
    {
199 156
        $elements = explode('\\', $namespacedClassName);
200
201 156
        return (string) array_pop($elements);
202
    }
203
204 180
    public static function createDirectory(string $directory, $permissions = 0775): bool
205
    {
206 180
        if (!is_dir($directory)) {
207 10
            mkdir($directory, $permissions, true);
208
        }
209
210 180
        return true;
211
    }
212
213
    /**
214
     * Save schemas to schemasFolder
215
     * Filename will be extracted from schemasUrl or default schema.wsdl will be used.
216
     */
217 4
    public static function saveSchemas(string $destinationFolder, string $schemasFolder, string $schemasUrl, string $content): string
218
    {
219 4
        if (is_null($schemasFolder) || empty($schemasFolder)) {
220
            // if null or empty schemas folder was provided
221
            // default schemas folder will be wsdl
222 2
            $schemasFolder = 'wsdl';
223
        }
224 4
        $schemasPath = rtrim($destinationFolder, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.rtrim($schemasFolder, DIRECTORY_SEPARATOR);
225
226
        // Here we must cover all possible variants
227 4
        if ((false !== mb_strpos(mb_strtolower($schemasUrl), '.wsdl')) || (false !== mb_strpos(mb_strtolower($schemasUrl), '.xsd')) || (false !== mb_strpos(mb_strtolower($schemasUrl), '.xml')) || (false === mb_strpos(mb_strtolower($schemasUrl), '?'))) {
228 4
            $filename = basename($schemasUrl).(false === mb_strpos(basename($schemasUrl), '.') ? '.xsd' : '');
229
        } else {
230
            // if $url is like http://example.com/index.php?WSDL default filename will be schema.wsdl
231 2
            $filename = 'schema.wsdl';
232
        }
233
234 4
        self::createDirectory($schemasPath);
235
236 4
        file_put_contents($schemasPath.DIRECTORY_SEPARATOR.$filename, $content);
237
238 4
        return $schemasPath.DIRECTORY_SEPARATOR.$filename;
239
    }
240
}
241