Completed
Pull Request — master (#6)
by Tomáš
07:30
created

Common::realpath()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 6
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 14
rs 9.4285
1
<?php
2
/**
3
 * Basic util functions.
4
 *
5
 * @author    Greg Sherwood <[email protected]>
6
 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
7
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8
 */
9
10
namespace PHP_CodeSniffer\Util;
11
12
use PHP_CodeSniffer\Config;
13
use PHP_CodeSniffer\Exceptions\RuntimeException;
14
15
class Common
16
{
17
18
    /**
19
     * An array of variable types for param/var we will check.
20
     *
21
     * @var string[]
22
     */
23
    public static $allowedTypes = array(
24
                                   'array',
25
                                   'boolean',
26
                                   'float',
27
                                   'integer',
28
                                   'mixed',
29
                                   'object',
30
                                   'string',
31
                                   'resource',
32
                                   'callable',
33
                                  );
34
35
36
    /**
37
     * CodeSniffer alternative for realpath.
38
     *
39
     * Allows for PHAR support.
40
     *
41
     * @param string $path The path to use.
42
     *
43
     * @return mixed
44
     */
45
    public static function realpath($path)
46
    {
47
        // Support the path replacement of ~ with the user's home directory.
48
        if (substr($path, 0, 2) === '~/') {
49
            $homeDir = getenv('HOME');
50
            if ($homeDir !== false) {
51
                $path = $homeDir.substr($path, 1);
52
            }
53
        }
54
55
        // No extra work needed if this is not a phar file.
56
        return realpath($path);
57
58
    }//end realpath()
59
60
61
    /**
62
     * Removes a base path from the front of a file path.
63
     *
64
     * @param string $path     The path of the file.
65
     * @param string $basepath The base path to remove. This should not end
66
     *                         with a directory separator.
67
     *
68
     * @return string
69
     */
70
    public static function stripBasepath($path, $basepath)
71
    {
72
        if (empty($basepath) === true) {
73
            return $path;
74
        }
75
76
        $basepathLen = strlen($basepath);
77
        if (substr($path, 0, $basepathLen) === $basepath) {
78
            $path = substr($path, $basepathLen);
79
        }
80
81
        $path = ltrim($path, DIRECTORY_SEPARATOR);
82
        if ($path === '') {
83
            $path = '.';
84
        }
85
86
        return $path;
87
88
    }//end stripBasepath()
89
90
91
    /**
92
     * Detects the EOL character being used in a string.
93
     *
94
     * @param string $contents The contents to check.
95
     *
96
     * @return string
97
     */
98
    public static function detectLineEndings($contents)
99
    {
100
        if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) {
101
            // Assume there are no newlines.
102
            $eolChar = "\n";
103
        } else {
104
            $eolChar = $matches[0];
105
        }
106
107
        return $eolChar;
108
109
    }//end detectLineEndings()
110
111
112
    /**
113
     * Prepares token content for output to screen.
114
     *
115
     * Replaces invisible characters so they are visible. On non-Windows
116
     * OSes it will also colour the invisible characters.
117
     *
118
     * @param string   $content The content to prepare.
119
     * @param string[] $exclude A list of characters to leave invisible.
120
     *                          Can contain \r, \n, \t and a space.
121
     *
122
     * @return string
123
     */
124
    public static function prepareForOutput($content, $exclude=array())
125
    {
126
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
127
            if (in_array("\r", $exclude) === false) {
128
                $content = str_replace("\r", '\r', $content);
129
            }
130
131
            if (in_array("\n", $exclude) === false) {
132
                $content = str_replace("\n", '\n', $content);
133
            }
134
135
            if (in_array("\t", $exclude) === false) {
136
                $content = str_replace("\t", '\t', $content);
137
            }
138
        } else {
139
            if (in_array("\r", $exclude) === false) {
140
                $content = str_replace("\r", "\033[30;1m\\r\033[0m", $content);
141
            }
142
143
            if (in_array("\n", $exclude) === false) {
144
                $content = str_replace("\n", "\033[30;1m\\n\033[0m", $content);
145
            }
146
147
            if (in_array("\t", $exclude) === false) {
148
                $content = str_replace("\t", "\033[30;1m\\t\033[0m", $content);
149
            }
150
151
            if (in_array(' ', $exclude) === false) {
152
                $content = str_replace(' ', "\033[30;1m·\033[0m", $content);
153
            }
154
        }//end if
155
156
        return $content;
157
158
    }//end prepareForOutput()
159
160
161
    /**
162
     * Returns true if the specified string is in the camel caps format.
163
     *
164
     * @param string  $string      The string the verify.
165
     * @param boolean $classFormat If true, check to see if the string is in the
166
     *                             class format. Class format strings must start
167
     *                             with a capital letter and contain no
168
     *                             underscores.
169
     * @param boolean $public      If true, the first character in the string
170
     *                             must be an a-z character. If false, the
171
     *                             character must be an underscore. This
172
     *                             argument is only applicable if $classFormat
173
     *                             is false.
174
     * @param boolean $strict      If true, the string must not have two capital
175
     *                             letters next to each other. If false, a
176
     *                             relaxed camel caps policy is used to allow
177
     *                             for acronyms.
178
     *
179
     * @return boolean
180
     */
181
    public static function isCamelCaps(
182
        $string,
183
        $classFormat=false,
184
        $public=true,
185
        $strict=true
186
    ) {
187
        // Check the first character first.
188
        if ($classFormat === false) {
189
            $legalFirstChar = '';
190
            if ($public === false) {
191
                $legalFirstChar = '[_]';
192
            }
193
194
            if ($strict === false) {
195
                // Can either start with a lowercase letter, or multiple uppercase
196
                // in a row, representing an acronym.
197
                $legalFirstChar .= '([A-Z]{2,}|[a-z])';
198
            } else {
199
                $legalFirstChar .= '[a-z]';
200
            }
201
        } else {
202
            $legalFirstChar = '[A-Z]';
203
        }
204
205
        if (preg_match("/^$legalFirstChar/", $string) === 0) {
206
            return false;
207
        }
208
209
        // Check that the name only contains legal characters.
210
        $legalChars = 'a-zA-Z0-9';
211
        if (preg_match("|[^$legalChars]|", substr($string, 1)) > 0) {
212
            return false;
213
        }
214
215
        if ($strict === true) {
216
            // Check that there are not two capital letters next to each other.
217
            $length          = strlen($string);
218
            $lastCharWasCaps = $classFormat;
219
220
            for ($i = 1; $i < $length; $i++) {
221
                $ascii = ord($string{$i});
222
                if ($ascii >= 48 && $ascii <= 57) {
223
                    // The character is a number, so it cant be a capital.
224
                    $isCaps = false;
225
                } else {
226
                    if (strtoupper($string{$i}) === $string{$i}) {
227
                        $isCaps = true;
228
                    } else {
229
                        $isCaps = false;
230
                    }
231
                }
232
233
                if ($isCaps === true && $lastCharWasCaps === true) {
234
                    return false;
235
                }
236
237
                $lastCharWasCaps = $isCaps;
238
            }
239
        }//end if
240
241
        return true;
242
243
    }//end isCamelCaps()
244
245
246
    /**
247
     * Returns true if the specified string is in the underscore caps format.
248
     *
249
     * @param string $string The string to verify.
250
     *
251
     * @return boolean
252
     */
253
    public static function isUnderscoreName($string)
254
    {
255
        // If there are space in the name, it can't be valid.
256
        if (strpos($string, ' ') !== false) {
257
            return false;
258
        }
259
260
        $validName = true;
261
        $nameBits  = explode('_', $string);
262
263
        if (preg_match('|^[A-Z]|', $string) === 0) {
264
            // Name does not begin with a capital letter.
265
            $validName = false;
266
        } else {
267
            foreach ($nameBits as $bit) {
268
                if ($bit === '') {
269
                    continue;
270
                }
271
272
                if ($bit{0} !== strtoupper($bit{0})) {
273
                    $validName = false;
274
                    break;
275
                }
276
            }
277
        }
278
279
        return $validName;
280
281
    }//end isUnderscoreName()
282
283
284
    /**
285
     * Returns a valid variable type for param/var tag.
286
     *
287
     * If type is not one of the standard type, it must be a custom type.
288
     * Returns the correct type name suggestion if type name is invalid.
289
     *
290
     * @param string $varType The variable type to process.
291
     *
292
     * @return string
293
     */
294
    public static function suggestType($varType)
295
    {
296
        if ($varType === '') {
297
            return '';
298
        }
299
300
        if (in_array($varType, self::$allowedTypes) === true) {
301
            return $varType;
302
        } else {
303
            $lowerVarType = strtolower($varType);
304
            switch ($lowerVarType) {
305
            case 'bool':
306
                return 'boolean';
307
            case 'double':
308
            case 'real':
309
                return 'float';
310
            case 'int':
311
                return 'integer';
312
            case 'array()':
313
                return 'array';
314
            }//end switch
315
316
            if (strpos($lowerVarType, 'array(') !== false) {
317
                // Valid array declaration:
318
                // array, array(type), array(type1 => type2).
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
319
                $matches = array();
320
                $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i';
321
                if (preg_match($pattern, $varType, $matches) !== 0) {
322
                    $type1 = '';
323
                    if (isset($matches[1]) === true) {
324
                        $type1 = $matches[1];
325
                    }
326
327
                    $type2 = '';
328
                    if (isset($matches[3]) === true) {
329
                        $type2 = $matches[3];
330
                    }
331
332
                    $type1 = self::suggestType($type1);
333
                    $type2 = self::suggestType($type2);
334
                    if ($type2 !== '') {
335
                        $type2 = ' => '.$type2;
336
                    }
337
338
                    return "array($type1$type2)";
339
                } else {
340
                    return 'array';
341
                }//end if
342
            } else if (in_array($lowerVarType, self::$allowedTypes) === true) {
343
                // A valid type, but not lower cased.
344
                return $lowerVarType;
345
            } else {
346
                // Must be a custom type name.
347
                return $varType;
348
            }//end if
349
        }//end if
350
351
    }//end suggestType()
352
353
354
    /**
355
     * Given a sniff class name, returns the code for the sniff.
356
     *
357
     * @param string $sniffClass The fully qualified sniff class name.
358
     *
359
     * @return string
360
     */
361
    public static function getSniffCode($sniffClass)
362
    {
363
        $parts = explode('\\', $sniffClass);
364
        $sniff = array_pop($parts);
365
366
        if (substr($sniff, -5) === 'Sniff') {
367
            // Sniff class name.
368
            $sniff = substr($sniff, 0, -5);
369
        } else {
370
            // Unit test class name.
371
            $sniff = substr($sniff, 0, -8);
372
        }
373
374
        $category = array_pop($parts);
375
        $sniffDir = array_pop($parts);
0 ignored issues
show
Unused Code introduced by
$sniffDir is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
376
        $standard = array_pop($parts);
377
        $code     = $standard.'.'.$category.'.'.$sniff;
378
        return $code;
379
380
    }//end getSniffCode()
381
382
383
}//end class
384