Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
99.08% covered (success)
99.08%
108 / 109
90.00% covered (success)
90.00%
9 / 10
CRAP
0.00% covered (danger)
0.00%
0 / 1
Utils
99.08% covered (success)
99.08%
108 / 109
90.00% covered (success)
90.00%
9 / 10
80
0.00% covered (danger)
0.00%
0 / 1
 getPart
96.43% covered (success)
96.43%
27 / 28
0.00% covered (danger)
0.00%
0 / 1
15
 getContentFromUrl
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getStreamContextOptions
100.00% covered (success)
100.00%
13 / 13
100.00% covered (success)
100.00%
1 / 1
7
 getValueWithinItsType
100.00% covered (success)
100.00%
17 / 17
100.00% covered (success)
100.00%
1 / 1
13
 resolveCompletePath
100.00% covered (success)
100.00%
25 / 25
100.00% covered (success)
100.00%
1 / 1
25
 cleanComment
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
5
 cleanString
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 removeNamespace
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 createDirectory
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 saveSchemas
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
8
1<?php
2
3declare(strict_types=1);
4
5namespace WsdlToPhp\PackageGenerator\Generator;
6
7use WsdlToPhp\PackageGenerator\ConfigurationReader\GeneratorOptions;
8
9final class Utils
10{
11    /**
12     * Gets upper case word among a string from the end or from the beginning part.
13     */
14    public static function getPart(string $optionValue, string $string): string
15    {
16        $string = str_replace('_', '', $string);
17        $string = preg_replace('/([0-9])/', '', $string);
18
19        if (empty($string)) {
20            return '';
21        }
22
23        $elementType = '';
24
25        switch ($optionValue) {
26            case GeneratorOptions::VALUE_END:
27                $parts = preg_split('/[A-Z]/', ucfirst($string));
28                $partsCount = is_countable($parts) ? count($parts) : 0;
29                if (!empty($parts[$partsCount - 1])) {
30                    $elementType = mb_substr($string, mb_strrpos($string, implode('', array_slice($parts, -1))) - 1);
31                } else {
32                    for ($i = $partsCount - 1; $i >= 0; --$i) {
33                        $part = trim($parts[$i]);
34                        if (!empty($part)) {
35                            break;
36                        }
37                    }
38                    $elementType = mb_substr($string, (((is_countable($parts) ? count($parts) : 0) - 2 - $i) + 1) * -1);
39                }
40
41                break;
42
43            case GeneratorOptions::VALUE_START:
44                $parts = preg_split('/[A-Z]/', ucfirst($string));
45                $partsCount = is_countable($parts) ? count($parts) : 0;
46                if (empty($parts[0]) && !empty($parts[1])) {
47                    $elementType = mb_substr($string, 0, mb_strlen($parts[1]) + 1);
48                } else {
49                    for ($i = 0; $i < $partsCount; ++$i) {
50                        $part = trim($parts[$i]);
51                        if (!empty($part)) {
52                            break;
53                        }
54                    }
55                    $elementType = mb_substr($string, 0, $i);
56                }
57
58                break;
59
60            case GeneratorOptions::VALUE_NONE:
61                $elementType = $string;
62
63                break;
64        }
65
66        return $elementType;
67    }
68
69    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        $context = null;
72        $options = self::getStreamContextOptions($basicAuthLogin, $basicAuthPassword, $proxyHost, $proxyPort, $proxyLogin, $proxyPassword, $contextOptions);
73        if (!empty($options)) {
74            $context = stream_context_create($options);
75        }
76
77        return file_get_contents($url, false, $context);
78    }
79
80    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        $applyHttpHeader = function (array $contextOptions, string $header): array {
83            if (!isset($contextOptions['http']['header']) || !in_array($header, $contextOptions['http']['header'])) {
84                $contextOptions['http']['header'][] = $header;
85            }
86
87            return $contextOptions;
88        };
89
90        if (!empty($basicAuthLogin) && !empty($basicAuthPassword)) {
91            $authorizationHeader = sprintf('Authorization: Basic %s', base64_encode(sprintf('%s:%s', $basicAuthLogin, $basicAuthPassword)));
92            $contextOptions = $applyHttpHeader($contextOptions, $authorizationHeader);
93        }
94
95        if (!empty($proxyHost)) {
96            $contextOptions['http']['proxy'] = sprintf('tcp://%s%s', $proxyHost, empty($proxyPort) ? '' : sprintf(':%s', $proxyPort));
97            $proxyAuthorizationHeader = sprintf('Proxy-Authorization: Basic %s', base64_encode(sprintf('%s:%s', $proxyLogin, $proxyPassword)));
98            $contextOptions = $applyHttpHeader($contextOptions, $proxyAuthorizationHeader);
99        }
100
101        return $contextOptions;
102    }
103
104    public static function getValueWithinItsType($value, ?string $knownType = null)
105    {
106        if (is_int($value) || (!is_null($value) && in_array($knownType, [
107            'int',
108            'integer',
109        ], true))) {
110            return (int) $value;
111        }
112        if (is_float($value) || (!is_null($value) && in_array($knownType, [
113            'float',
114            'double',
115            'decimal',
116        ], true))) {
117            return (float) $value;
118        }
119        if (is_bool($value) || (!is_null($value) && in_array($knownType, [
120            'bool',
121            'boolean',
122        ], true))) {
123            return 'true' === $value || true === $value || 1 === $value || '1' === $value;
124        }
125
126        return $value;
127    }
128
129    public static function resolveCompletePath(string $origin, string $destination): string
130    {
131        $resolvedPath = $destination;
132        if (!empty($destination) && false === mb_strpos($destination, 'http://') && false === mb_strpos($destination, 'https://') && !empty($origin)) {
133            if ('./' === mb_substr($destination, 0, 2)) {
134                $destination = mb_substr($destination, 2);
135            }
136            $destinationParts = explode('/', $destination);
137            $fileParts = pathinfo($origin);
138            $fileBasename = (is_array($fileParts) && array_key_exists('basename', $fileParts)) ? $fileParts['basename'] : '';
139            $parts = parse_url(str_replace('/'.$fileBasename, '', $origin));
140            $scheme = (is_array($parts) && array_key_exists('scheme', $parts)) ? $parts['scheme'] : '';
141            $host = (is_array($parts) && array_key_exists('host', $parts)) ? $parts['host'] : '';
142            $path = (is_array($parts) && array_key_exists('path', $parts)) ? $parts['path'] : '';
143            $path = str_replace('/'.$fileBasename, '', $path);
144            $pathParts = explode('/', $path);
145            $finalPath = implode('/', $pathParts);
146            foreach ($destinationParts as $locationPart) {
147                if ('..' === $locationPart) {
148                    $finalPath = mb_substr($finalPath, 0, mb_strrpos($finalPath, '/', 0));
149                } else {
150                    $finalPath .= '/'.$locationPart;
151                }
152            }
153            $port = (is_array($parts) && array_key_exists('port', $parts)) ? $parts['port'] : '';
154            // Remote file
155            if (!empty($scheme) && !empty($host)) {
156                $resolvedPath = str_replace('urn', 'http', $scheme).'://'.$host.(!empty($port) ? ':'.$port : '').str_replace('//', '/', $finalPath);
157            } elseif (empty($scheme) && empty($host) && count($pathParts)) {
158                // Local file
159                if (is_file($finalPath)) {
160                    $resolvedPath = $finalPath;
161                }
162            }
163        }
164
165        return $resolvedPath;
166    }
167
168    public static function cleanComment($comment, string $glueSeparator = ',', bool $uniqueValues = true): string
169    {
170        if (!is_scalar($comment) && !is_array($comment)) {
171            return '';
172        }
173
174        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    public static function cleanString(string $string, bool $keepMultipleUnderscores = true): string
188    {
189        $cleanedString = preg_replace('/[^\p{L}\p{N}_]/u', '_', $string);
190        if (!$keepMultipleUnderscores) {
191            $cleanedString = preg_replace('/[_]+/', '_', $cleanedString);
192        }
193
194        return $cleanedString;
195    }
196
197    public static function removeNamespace(string $namespacedClassName): string
198    {
199        $elements = explode('\\', $namespacedClassName);
200
201        return (string) array_pop($elements);
202    }
203
204    public static function createDirectory(string $directory, $permissions = 0775): bool
205    {
206        if (!is_dir($directory)) {
207            mkdir($directory, $permissions, true);
208        }
209
210        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    public static function saveSchemas(string $destinationFolder, string $schemasFolder, string $schemasUrl, string $content): string
218    {
219        if (is_null($schemasFolder) || empty($schemasFolder)) {
220            // if null or empty schemas folder was provided
221            // default schemas folder will be wsdl
222            $schemasFolder = 'wsdl';
223        }
224        $schemasPath = rtrim($destinationFolder, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.rtrim($schemasFolder, DIRECTORY_SEPARATOR);
225
226        // Here we must cover all possible variants
227        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            $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            $filename = 'schema.wsdl';
232        }
233
234        self::createDirectory($schemasPath);
235
236        file_put_contents($schemasPath.DIRECTORY_SEPARATOR.$filename, $content);
237
238        return $schemasPath.DIRECTORY_SEPARATOR.$filename;
239    }
240}