diff vendor/squizlabs/php_codesniffer/src/Util/Common.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents
children af1871eacc83
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vendor/squizlabs/php_codesniffer/src/Util/Common.php	Thu Feb 28 13:21:36 2019 +0000
@@ -0,0 +1,520 @@
+<?php
+/**
+ * Basic util functions.
+ *
+ * @author    Greg Sherwood <gsherwood@squiz.net>
+ * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
+ * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
+ */
+
+namespace PHP_CodeSniffer\Util;
+
+class Common
+{
+
+    /**
+     * An array of variable types for param/var we will check.
+     *
+     * @var string[]
+     */
+    public static $allowedTypes = [
+        'array',
+        'boolean',
+        'float',
+        'integer',
+        'mixed',
+        'object',
+        'string',
+        'resource',
+        'callable',
+    ];
+
+
+    /**
+     * Return TRUE if the path is a PHAR file.
+     *
+     * @param string $path The path to use.
+     *
+     * @return mixed
+     */
+    public static function isPharFile($path)
+    {
+        if (strpos($path, 'phar://') === 0) {
+            return true;
+        }
+
+        return false;
+
+    }//end isPharFile()
+
+
+    /**
+     * CodeSniffer alternative for realpath.
+     *
+     * Allows for PHAR support.
+     *
+     * @param string $path The path to use.
+     *
+     * @return mixed
+     */
+    public static function realpath($path)
+    {
+        // Support the path replacement of ~ with the user's home directory.
+        if (substr($path, 0, 2) === '~/') {
+            $homeDir = getenv('HOME');
+            if ($homeDir !== false) {
+                $path = $homeDir.substr($path, 1);
+            }
+        }
+
+        // Check for process substitution.
+        if (strpos($path, '/dev/fd') === 0) {
+            return str_replace('/dev/fd', 'php://fd', $path);
+        }
+
+        // No extra work needed if this is not a phar file.
+        if (self::isPharFile($path) === false) {
+            return realpath($path);
+        }
+
+        // Before trying to break down the file path,
+        // check if it exists first because it will mostly not
+        // change after running the below code.
+        if (file_exists($path) === true) {
+            return $path;
+        }
+
+        $phar  = \Phar::running(false);
+        $extra = str_replace('phar://'.$phar, '', $path);
+        $path  = realpath($phar);
+        if ($path === false) {
+            return false;
+        }
+
+        $path = 'phar://'.$path.$extra;
+        if (file_exists($path) === true) {
+            return $path;
+        }
+
+        return false;
+
+    }//end realpath()
+
+
+    /**
+     * Removes a base path from the front of a file path.
+     *
+     * @param string $path     The path of the file.
+     * @param string $basepath The base path to remove. This should not end
+     *                         with a directory separator.
+     *
+     * @return string
+     */
+    public static function stripBasepath($path, $basepath)
+    {
+        if (empty($basepath) === true) {
+            return $path;
+        }
+
+        $basepathLen = strlen($basepath);
+        if (substr($path, 0, $basepathLen) === $basepath) {
+            $path = substr($path, $basepathLen);
+        }
+
+        $path = ltrim($path, DIRECTORY_SEPARATOR);
+        if ($path === '') {
+            $path = '.';
+        }
+
+        return $path;
+
+    }//end stripBasepath()
+
+
+    /**
+     * Detects the EOL character being used in a string.
+     *
+     * @param string $contents The contents to check.
+     *
+     * @return string
+     */
+    public static function detectLineEndings($contents)
+    {
+        if (preg_match("/\r\n?|\n/", $contents, $matches) !== 1) {
+            // Assume there are no newlines.
+            $eolChar = "\n";
+        } else {
+            $eolChar = $matches[0];
+        }
+
+        return $eolChar;
+
+    }//end detectLineEndings()
+
+
+    /**
+     * Check if STDIN is a TTY.
+     *
+     * @return boolean
+     */
+    public static function isStdinATTY()
+    {
+        // The check is slow (especially calling `tty`) so we static
+        // cache the result.
+        static $isTTY = null;
+
+        if ($isTTY !== null) {
+            return $isTTY;
+        }
+
+        if (defined('STDIN') === false) {
+            return false;
+        }
+
+        // If PHP has the POSIX extensions we will use them.
+        if (function_exists('posix_isatty') === true) {
+            $isTTY = (posix_isatty(STDIN) === true);
+            return $isTTY;
+        }
+
+        // Next try is detecting whether we have `tty` installed and use that.
+        if (defined('PHP_WINDOWS_VERSION_PLATFORM') === true) {
+            $devnull = 'NUL';
+            $which   = 'where';
+        } else {
+            $devnull = '/dev/null';
+            $which   = 'which';
+        }
+
+        $tty = trim(shell_exec("$which tty 2> $devnull"));
+        if (empty($tty) === false) {
+            exec("tty -s 2> $devnull", $output, $returnValue);
+            $isTTY = ($returnValue === 0);
+            return $isTTY;
+        }
+
+        // Finally we will use fstat.  The solution borrowed from
+        // https://stackoverflow.com/questions/11327367/detect-if-a-php-script-is-being-run-interactively-or-not
+        // This doesn't work on Mingw/Cygwin/... using Mintty but they
+        // have `tty` installed.
+        $type = [
+            'S_IFMT'  => 0170000,
+            'S_IFIFO' => 0010000,
+        ];
+
+        $stat  = fstat(STDIN);
+        $mode  = ($stat['mode'] & $type['S_IFMT']);
+        $isTTY = ($mode !== $type['S_IFIFO']);
+
+        return $isTTY;
+
+    }//end isStdinATTY()
+
+
+    /**
+     * Prepares token content for output to screen.
+     *
+     * Replaces invisible characters so they are visible. On non-Windows
+     * OSes it will also colour the invisible characters.
+     *
+     * @param string   $content The content to prepare.
+     * @param string[] $exclude A list of characters to leave invisible.
+     *                          Can contain \r, \n, \t and a space.
+     *
+     * @return string
+     */
+    public static function prepareForOutput($content, $exclude=[])
+    {
+        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
+            if (in_array("\r", $exclude) === false) {
+                $content = str_replace("\r", '\r', $content);
+            }
+
+            if (in_array("\n", $exclude) === false) {
+                $content = str_replace("\n", '\n', $content);
+            }
+
+            if (in_array("\t", $exclude) === false) {
+                $content = str_replace("\t", '\t', $content);
+            }
+        } else {
+            if (in_array("\r", $exclude) === false) {
+                $content = str_replace("\r", "\033[30;1m\\r\033[0m", $content);
+            }
+
+            if (in_array("\n", $exclude) === false) {
+                $content = str_replace("\n", "\033[30;1m\\n\033[0m", $content);
+            }
+
+            if (in_array("\t", $exclude) === false) {
+                $content = str_replace("\t", "\033[30;1m\\t\033[0m", $content);
+            }
+
+            if (in_array(' ', $exclude) === false) {
+                $content = str_replace(' ', "\033[30;1m·\033[0m", $content);
+            }
+        }//end if
+
+        return $content;
+
+    }//end prepareForOutput()
+
+
+    /**
+     * Returns true if the specified string is in the camel caps format.
+     *
+     * @param string  $string      The string the verify.
+     * @param boolean $classFormat If true, check to see if the string is in the
+     *                             class format. Class format strings must start
+     *                             with a capital letter and contain no
+     *                             underscores.
+     * @param boolean $public      If true, the first character in the string
+     *                             must be an a-z character. If false, the
+     *                             character must be an underscore. This
+     *                             argument is only applicable if $classFormat
+     *                             is false.
+     * @param boolean $strict      If true, the string must not have two capital
+     *                             letters next to each other. If false, a
+     *                             relaxed camel caps policy is used to allow
+     *                             for acronyms.
+     *
+     * @return boolean
+     */
+    public static function isCamelCaps(
+        $string,
+        $classFormat=false,
+        $public=true,
+        $strict=true
+    ) {
+        // Check the first character first.
+        if ($classFormat === false) {
+            $legalFirstChar = '';
+            if ($public === false) {
+                $legalFirstChar = '[_]';
+            }
+
+            if ($strict === false) {
+                // Can either start with a lowercase letter, or multiple uppercase
+                // in a row, representing an acronym.
+                $legalFirstChar .= '([A-Z]{2,}|[a-z])';
+            } else {
+                $legalFirstChar .= '[a-z]';
+            }
+        } else {
+            $legalFirstChar = '[A-Z]';
+        }
+
+        if (preg_match("/^$legalFirstChar/", $string) === 0) {
+            return false;
+        }
+
+        // Check that the name only contains legal characters.
+        $legalChars = 'a-zA-Z0-9';
+        if (preg_match("|[^$legalChars]|", substr($string, 1)) > 0) {
+            return false;
+        }
+
+        if ($strict === true) {
+            // Check that there are not two capital letters next to each other.
+            $length          = strlen($string);
+            $lastCharWasCaps = $classFormat;
+
+            for ($i = 1; $i < $length; $i++) {
+                $ascii = ord($string{$i});
+                if ($ascii >= 48 && $ascii <= 57) {
+                    // The character is a number, so it cant be a capital.
+                    $isCaps = false;
+                } else {
+                    if (strtoupper($string{$i}) === $string{$i}) {
+                        $isCaps = true;
+                    } else {
+                        $isCaps = false;
+                    }
+                }
+
+                if ($isCaps === true && $lastCharWasCaps === true) {
+                    return false;
+                }
+
+                $lastCharWasCaps = $isCaps;
+            }
+        }//end if
+
+        return true;
+
+    }//end isCamelCaps()
+
+
+    /**
+     * Returns true if the specified string is in the underscore caps format.
+     *
+     * @param string $string The string to verify.
+     *
+     * @return boolean
+     */
+    public static function isUnderscoreName($string)
+    {
+        // If there are space in the name, it can't be valid.
+        if (strpos($string, ' ') !== false) {
+            return false;
+        }
+
+        $validName = true;
+        $nameBits  = explode('_', $string);
+
+        if (preg_match('|^[A-Z]|', $string) === 0) {
+            // Name does not begin with a capital letter.
+            $validName = false;
+        } else {
+            foreach ($nameBits as $bit) {
+                if ($bit === '') {
+                    continue;
+                }
+
+                if ($bit{0} !== strtoupper($bit{0})) {
+                    $validName = false;
+                    break;
+                }
+            }
+        }
+
+        return $validName;
+
+    }//end isUnderscoreName()
+
+
+    /**
+     * Returns a valid variable type for param/var tag.
+     *
+     * If type is not one of the standard type, it must be a custom type.
+     * Returns the correct type name suggestion if type name is invalid.
+     *
+     * @param string $varType The variable type to process.
+     *
+     * @return string
+     */
+    public static function suggestType($varType)
+    {
+        if ($varType === '') {
+            return '';
+        }
+
+        if (in_array($varType, self::$allowedTypes) === true) {
+            return $varType;
+        } else {
+            $lowerVarType = strtolower($varType);
+            switch ($lowerVarType) {
+            case 'bool':
+            case 'boolean':
+                return 'boolean';
+            case 'double':
+            case 'real':
+            case 'float':
+                return 'float';
+            case 'int':
+            case 'integer':
+                return 'integer';
+            case 'array()':
+            case 'array':
+                return 'array';
+            }//end switch
+
+            if (strpos($lowerVarType, 'array(') !== false) {
+                // Valid array declaration:
+                // array, array(type), array(type1 => type2).
+                $matches = [];
+                $pattern = '/^array\(\s*([^\s^=^>]*)(\s*=>\s*(.*))?\s*\)/i';
+                if (preg_match($pattern, $varType, $matches) !== 0) {
+                    $type1 = '';
+                    if (isset($matches[1]) === true) {
+                        $type1 = $matches[1];
+                    }
+
+                    $type2 = '';
+                    if (isset($matches[3]) === true) {
+                        $type2 = $matches[3];
+                    }
+
+                    $type1 = self::suggestType($type1);
+                    $type2 = self::suggestType($type2);
+                    if ($type2 !== '') {
+                        $type2 = ' => '.$type2;
+                    }
+
+                    return "array($type1$type2)";
+                } else {
+                    return 'array';
+                }//end if
+            } else if (in_array($lowerVarType, self::$allowedTypes) === true) {
+                // A valid type, but not lower cased.
+                return $lowerVarType;
+            } else {
+                // Must be a custom type name.
+                return $varType;
+            }//end if
+        }//end if
+
+    }//end suggestType()
+
+
+    /**
+     * Given a sniff class name, returns the code for the sniff.
+     *
+     * @param string $sniffClass The fully qualified sniff class name.
+     *
+     * @return string
+     */
+    public static function getSniffCode($sniffClass)
+    {
+        $parts = explode('\\', $sniffClass);
+        $sniff = array_pop($parts);
+
+        if (substr($sniff, -5) === 'Sniff') {
+            // Sniff class name.
+            $sniff = substr($sniff, 0, -5);
+        } else {
+            // Unit test class name.
+            $sniff = substr($sniff, 0, -8);
+        }
+
+        $category = array_pop($parts);
+        $sniffDir = array_pop($parts);
+        $standard = array_pop($parts);
+        $code     = $standard.'.'.$category.'.'.$sniff;
+        return $code;
+
+    }//end getSniffCode()
+
+
+    /**
+     * Removes project-specific information from a sniff class name.
+     *
+     * @param string $sniffClass The fully qualified sniff class name.
+     *
+     * @return string
+     */
+    public static function cleanSniffClass($sniffClass)
+    {
+        $newName = strtolower($sniffClass);
+
+        $sniffPos = strrpos($newName, '\sniffs\\');
+        if ($sniffPos === false) {
+            // Nothing we can do as it isn't in a known format.
+            return $newName;
+        }
+
+        $end   = (strlen($newName) - $sniffPos + 1);
+        $start = strrpos($newName, '\\', ($end * -1));
+
+        if ($start === false) {
+            // Nothing needs to be cleaned.
+            return $newName;
+        }
+
+        $newName = substr($newName, ($start + 1));
+        return $newName;
+
+    }//end cleanSniffClass()
+
+
+}//end class