From 0dc8387173e3297fe1316b114a1a59a01dde265f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 7 Apr 2019 12:44:45 +0200 Subject: [PATCH 01/21] Add the Path class --- src/Symfony/Component/Filesystem/Path.php | 990 ++++++++++++ .../Component/Filesystem/Tests/PathTest.php | 1341 +++++++++++++++++ 2 files changed, 2331 insertions(+) create mode 100644 src/Symfony/Component/Filesystem/Path.php create mode 100644 src/Symfony/Component/Filesystem/Tests/PathTest.php diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php new file mode 100644 index 0000000000000..a484bbf39ee8c --- /dev/null +++ b/src/Symfony/Component/Filesystem/Path.php @@ -0,0 +1,990 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem; + +use function array_pop; +use function array_slice; +use function basename; +use function ctype_alpha; +use function explode; +use function function_exists; +use function getenv; +use function implode; +use function in_array; +use InvalidArgumentException; +use function is_object; +use function ltrim; +use function mb_strtolower; +use function pathinfo; +use function rtrim; +use RuntimeException; +use function sprintf; +use function str_replace; +use function strlen; +use function strpos; +use function substr; + +/** + * Contains utility methods for handling path strings. + * + * The methods in this class are able to deal with both UNIX and Windows paths + * with both forward and backward slashes. All methods return normalized parts + * containing only forward slashes and no excess "." and ".." segments. + * + * @since 1.0 + * + * @author Bernhard Schussek + * @author Thomas Schulz + */ +final class Path +{ + /** + * The number of buffer entries that triggers a cleanup operation. + */ + public const CLEANUP_THRESHOLD = 1250; + + /** + * The buffer size after the cleanup operation. + */ + public const CLEANUP_SIZE = 1000; + + /** + * Buffers input/output of {@link canonicalize()}. + * + * @var array + */ + private static $buffer = []; + + /** + * The size of the buffer. + * + * @var int + */ + private static $bufferSize = 0; + + /** + * Canonicalizes the given path. + * + * During normalization, all slashes are replaced by forward slashes ("/"). + * Furthermore, all "." and ".." segments are removed as far as possible. + * ".." segments at the beginning of relative paths are not removed. + * + * ```php + * echo Path::canonicalize("\webmozart\puli\..\css\style.css"); + * // => /webmozart/css/style.css + * + * echo Path::canonicalize("../css/./style.css"); + * // => ../css/style.css + * ``` + * + * This method is able to deal with both UNIX and Windows paths. + * + * @param string $path A path string. + * + * @return string The canonical path. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + * @since 2.1 Added support for `~`. + */ + public static function canonicalize(string $path): string + { + if ('' === $path) { + return ''; + } + + // This method is called by many other methods in this class. Buffer + // the canonicalized paths to make up for the severe performance + // decrease. + if (isset(self::$buffer[$path])) { + return self::$buffer[$path]; + } + + // Replace "~" with user's home directory. + if ('~' === $path[0]) { + $path = static::getHomeDirectory().substr($path, 1); + } + + $path = str_replace('\\', '/', $path); + + [$root, $pathWithoutRoot] = self::split($path); + + $parts = explode('/', $pathWithoutRoot); + $canonicalParts = array(); + + // Collapse "." and "..", if possible + foreach ($parts as $part) { + if ('.' === $part || '' === $part) { + continue; + } + + // Collapse ".." with the previous part, if one exists + // Don't collapse ".." if the previous part is also ".." + if ('..' === $part && count($canonicalParts) > 0 + && '..' !== $canonicalParts[count($canonicalParts) - 1] + ) { + array_pop($canonicalParts); + + continue; + } + + // Only add ".." prefixes for relative paths + if ('..' !== $part || '' === $root) { + $canonicalParts[] = $part; + } + } + + // Add the root directory again + self::$buffer[$path] = $canonicalPath = $root.implode('/', $canonicalParts); + ++self::$bufferSize; + + // Clean up regularly to prevent memory leaks + if (self::$bufferSize > self::CLEANUP_THRESHOLD) { + self::$buffer = array_slice(self::$buffer, -self::CLEANUP_SIZE, null, true); + self::$bufferSize = self::CLEANUP_SIZE; + } + + return $canonicalPath; + } + + /** + * Normalizes the given path. + * + * During normalization, all slashes are replaced by forward slashes ("/"). + * Contrary to {@link canonicalize()}, this method does not remove invalid + * or dot path segments. Consequently, it is much more efficient and should + * be used whenever the given path is known to be a valid, absolute system + * path. + * + * This method is able to deal with both UNIX and Windows paths. + * + * @param string $path A path string. + * + * @return string The normalized path. + * + * @since 2.2 Added method. + */ + public static function normalize(string $path): string + { + return str_replace('\\', '/', $path); + } + + /** + * Returns the directory part of the path. + * + * This method is similar to PHP's dirname(), but handles various cases + * where dirname() returns a weird result: + * + * - dirname() does not accept backslashes on UNIX + * - dirname("C:/webmozart") returns "C:", not "C:/" + * - dirname("C:/") returns ".", not "C:/" + * - dirname("C:") returns ".", not "C:/" + * - dirname("webmozart") returns ".", not "" + * - dirname() does not canonicalize the result + * + * This method fixes these shortcomings and behaves like dirname() + * otherwise. + * + * The result is a canonical path. + * + * @param string $path A path string. + * + * @return string The canonical directory part. Returns the root directory + * if the root directory is passed. Returns an empty string + * if a relative path is passed that contains no slashes. + * Returns an empty string if an empty string is passed. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function getDirectory(string $path): string + { + if ('' === $path) { + return ''; + } + + $path = static::canonicalize($path); + + // Maintain scheme + if (false !== ($pos = strpos($path, '://'))) { + $scheme = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); + } else { + $scheme = ''; + } + + if (false !== ($pos = strrpos($path, '/'))) { + // Directory equals root directory "/" + if (0 === $pos) { + return $scheme.'/'; + } + + // Directory equals Windows root "C:/" + if (2 === $pos && ctype_alpha($path[0]) && ':' === $path[1]) { + return $scheme.substr($path, 0, 3); + } + + return $scheme.substr($path, 0, $pos); + } + + return ''; + } + + /** + * Returns canonical path of the user's home directory. + * + * Supported operating systems: + * + * - UNIX + * - Windows8 and upper + * + * If your operation system or environment isn't supported, an exception is thrown. + * + * The result is a canonical path. + * + * @return string The canonical home directory + * + * @throws RuntimeException If your operation system or environment isn't supported + * + * @since 2.1 Added method. + */ + public static function getHomeDirectory(): string + { + // For UNIX support + if (getenv('HOME')) { + return static::canonicalize(getenv('HOME')); + } + + // For >= Windows8 support + if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { + return static::canonicalize(getenv('HOMEDRIVE').getenv('HOMEPATH')); + } + + throw new RuntimeException("Your environment or operation system isn't supported"); + } + + /** + * Returns the root directory of a path. + * + * The result is a canonical path. + * + * @param string $path A path string. + * + * @return string The canonical root directory. Returns an empty string if + * the given path is relative or empty. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function getRoot(string $path): string + { + if ('' === $path) { + return ''; + } + + // Maintain scheme + if (false !== ($pos = strpos($path, '://'))) { + $scheme = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); + } else { + $scheme = ''; + } + + // UNIX root "/" or "\" (Windows style) + if ('/' === $path[0] || '\\' === $path[0]) { + return $scheme.'/'; + } + + $length = strlen($path); + + // Windows root + if ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + // Special case: "C:" + if (2 === $length) { + return $scheme.$path.'/'; + } + + // Normal case: "C:/ or "C:\" + if ('/' === $path[2] || '\\' === $path[2]) { + return $scheme.$path[0].$path[1].'/'; + } + } + + return ''; + } + + /** + * Returns the file name from a file path. + * + * @param string $path The path string. + * + * @return string The file name. + * + * @since 1.1 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function getFilename(string $path): string + { + if ('' === $path) { + return ''; + } + + return basename($path); + } + + /** + * Returns the file name without the extension from a file path. + * + * @param string $path The path string. + * @param string|null $extension If specified, only that extension is cut + * off (may contain leading dot). + * + * @return string The file name without extension. + * + * @since 1.1 Added method. + * @since 2.0 Method now fails if $path or $extension have invalid types. + */ + public static function getFilenameWithoutExtension(string $path, ?string $extension = null) + { + if ('' === $path) { + return ''; + } + + if (null !== $extension) { + // remove extension and trailing dot + return rtrim(basename($path, $extension), '.'); + } + + return pathinfo($path, PATHINFO_FILENAME); + } + + /** + * Returns the extension from a file path. + * + * @param string $path The path string. + * @param bool $forceLowerCase Forces the extension to be lower-case + * (requires mbstring extension for correct + * multi-byte character handling in extension). + * + * @return string The extension of the file path (without leading dot). + * + * @since 1.1 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function getExtension(string $path, bool $forceLowerCase = false): string + { + if ('' === $path) { + return ''; + } + + $extension = pathinfo($path, PATHINFO_EXTENSION); + + if ($forceLowerCase) { + $extension = self::toLower($extension); + } + + return $extension; + } + + /** + * Returns whether the path has an extension. + * + * @param string $path The path string. + * @param string|string[]|null $extensions If null or not provided, checks if + * an extension exists, otherwise + * checks for the specified extension + * or array of extensions (with or + * without leading dot). + * @param bool $ignoreCase Whether to ignore case-sensitivity + * (requires mbstring extension for + * correct multi-byte character + * handling in the extension). + * + * @return bool Returns `true` if the path has an (or the specified) + * extension and `false` otherwise. + * + * @since 1.1 Added method. + * @since 2.0 Method now fails if $path or $extensions have invalid types. + */ + public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool + { + if ('' === $path) { + return false; + } + + $actualExtension = self::getExtension($path, $ignoreCase); + + // Only check if path has any extension + if (empty($extensions)) { + return '' !== $actualExtension; + } + + foreach ($extensions as $key => $extension) { + if ($ignoreCase) { + $extension = self::toLower($extension); + } + + // remove leading '.' in extensions array + $extensions[$key] = ltrim($extension, '.'); + } + + return in_array($actualExtension, $extensions, true); + } + + /** + * Changes the extension of a path string. + * + * @param string $path The path string with filename.ext to change. + * @param string $extension New extension (with or without leading dot). + * + * @return string The path string with new file extension. + * + * @since 1.1 Added method. + * @since 2.0 Method now fails if $path or $extension is not a string. + */ + public static function changeExtension(string $path, string $extension): string + { + if ('' === $path) { + return ''; + } + + $actualExtension = self::getExtension($path); + $extension = ltrim($extension, '.'); + + // No extension for paths + if ('/' === substr($path, -1)) { + return $path; + } + + // No actual extension in path + if (empty($actualExtension)) { + return $path.('.' === substr($path, -1) ? '' : '.').$extension; + } + + return substr($path, 0, -strlen($actualExtension)).$extension; + } + + /** + * Returns whether a path is absolute. + * + * @param string $path A path string. + * + * @return bool Returns true if the path is absolute, false if it is + * relative or empty. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function isAbsolute(string $path): bool + { + if ('' === $path) { + return false; + } + + // Strip scheme + if (false !== ($pos = strpos($path, '://'))) { + $path = substr($path, $pos + 3); + } + + // UNIX root "/" or "\" (Windows style) + if ('/' === $path[0] || '\\' === $path[0]) { + return true; + } + + // Windows root + if (strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + // Special case: "C:" + if (2 === strlen($path)) { + return true; + } + + // Normal case: "C:/ or "C:\" + if ('/' === $path[2] || '\\' === $path[2]) { + return true; + } + } + + return false; + } + + /** + * Returns whether a path is relative. + * + * @param string $path A path string. + * + * @return bool Returns true if the path is relative or empty, false if + * it is absolute. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function isRelative(string $path): bool + { + return !static::isAbsolute($path); + } + + /** + * Turns a relative path into an absolute path. + * + * Usually, the relative path is appended to the given base path. Dot + * segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * echo Path::makeAbsolute("../style.css", "/webmozart/puli/css"); + * // => /webmozart/puli/style.css + * ``` + * + * If an absolute path is passed, that path is returned unless its root + * directory is different than the one of the base path. In that case, an + * exception is thrown. + * + * ```php + * Path::makeAbsolute("/style.css", "/webmozart/puli/css"); + * // => /style.css + * + * Path::makeAbsolute("C:/style.css", "C:/webmozart/puli/css"); + * // => C:/style.css + * + * Path::makeAbsolute("C:/style.css", "/webmozart/puli/css"); + * // InvalidArgumentException + * ``` + * + * If the base path is not an absolute path, an exception is thrown. + * + * The result is a canonical path. + * + * @param string $path A path to make absolute. + * @param string $basePath An absolute base path. + * + * @return string An absolute path in canonical form. + * + * @throws InvalidArgumentException If the base path is not absolute or if + * the given path is an absolute path with + * a different root than the base path. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path or $basePath is not a string. + * @since 2.2.2 Method does not fail anymore of $path and $basePath are + * absolute, but on different partitions. + */ + public static function makeAbsolute(string $path, string $basePath): string + { + if (!static::isAbsolute($basePath)) { + throw new InvalidArgumentException(sprintf( + 'The base path "%s" is not an absolute path.', + $basePath + )); + } + + if (static::isAbsolute($path)) { + return static::canonicalize($path); + } + + if (false !== ($pos = strpos($basePath, '://'))) { + $scheme = substr($basePath, 0, $pos + 3); + $basePath = substr($basePath, $pos + 3); + } else { + $scheme = ''; + } + + return $scheme.self::canonicalize(rtrim($basePath, '/\\').'/'.$path); + } + + /** + * Turns a path into a relative path. + * + * The relative path is created relative to the given base path: + * + * ```php + * echo Path::makeRelative("/webmozart/style.css", "/webmozart/puli"); + * // => ../style.css + * ``` + * + * If a relative path is passed and the base path is absolute, the relative + * path is returned unchanged: + * + * ```php + * Path::makeRelative("style.css", "/webmozart/puli/css"); + * // => style.css + * ``` + * + * If both paths are relative, the relative path is created with the + * assumption that both paths are relative to the same directory: + * + * ```php + * Path::makeRelative("style.css", "webmozart/puli/css"); + * // => ../../../style.css + * ``` + * + * If both paths are absolute, their root directory must be the same, + * otherwise an exception is thrown: + * + * ```php + * Path::makeRelative("C:/webmozart/style.css", "/webmozart/puli"); + * // InvalidArgumentException + * ``` + * + * If the passed path is absolute, but the base path is not, an exception + * is thrown as well: + * + * ```php + * Path::makeRelative("/webmozart/style.css", "webmozart/puli"); + * // InvalidArgumentException + * ``` + * + * If the base path is not an absolute path, an exception is thrown. + * + * The result is a canonical path. + * + * @param string $path A path to make relative. + * @param string $basePath A base path. + * + * @return string A relative path in canonical form. + * + * @throws InvalidArgumentException If the base path is not absolute or if + * the given path has a different root + * than the base path. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path or $basePath is not a string. + */ + public static function makeRelative(string $path, string $basePath): string + { + $path = static::canonicalize($path); + $basePath = static::canonicalize($basePath); + + [$root, $relativePath] = self::split($path); + [$baseRoot, $relativeBasePath] = self::split($basePath); + + // If the base path is given as absolute path and the path is already + // relative, consider it to be relative to the given absolute path + // already + if ('' === $root && '' !== $baseRoot) { + // If base path is already in its root + if ('' === $relativeBasePath) { + $relativePath = ltrim($relativePath, './\\'); + } + + return $relativePath; + } + + // If the passed path is absolute, but the base path is not, we + // cannot generate a relative path + if ('' !== $root && '' === $baseRoot) { + throw new InvalidArgumentException(sprintf( + 'The absolute path "%s" cannot be made relative to the '. + 'relative path "%s". You should provide an absolute base '. + 'path instead.', + $path, + $basePath + )); + } + + // Fail if the roots of the two paths are different + if ($baseRoot && $root !== $baseRoot) { + throw new InvalidArgumentException(sprintf( + 'The path "%s" cannot be made relative to "%s", because they '. + 'have different roots ("%s" and "%s").', + $path, + $basePath, + $root, + $baseRoot + )); + } + + if ('' === $relativeBasePath) { + return $relativePath; + } + + // Build a "../../" prefix with as many "../" parts as necessary + $parts = explode('/', $relativePath); + $baseParts = explode('/', $relativeBasePath); + $dotDotPrefix = ''; + + // Once we found a non-matching part in the prefix, we need to add + // "../" parts for all remaining parts + $match = true; + + foreach ($baseParts as $i => $basePart) { + if ($match && isset($parts[$i]) && $basePart === $parts[$i]) { + unset($parts[$i]); + + continue; + } + + $match = false; + $dotDotPrefix .= '../'; + } + + return rtrim($dotDotPrefix.implode('/', $parts), '/'); + } + + /** + * Returns whether the given path is on the local filesystem. + * + * @param string $path A path string. + * + * @return bool Returns true if the path is local, false for a URL. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $path is not a string. + */ + public static function isLocal(string $path): bool + { + return '' !== $path && false === strpos($path, '://'); + } + + /** + * Returns the longest common base path of a set of paths. + * + * Dot segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * $basePath = Path::getLongestCommonBasePath(array( + * '/webmozart/css/style.css', + * '/webmozart/css/..' + * )); + * // => /webmozart + * ``` + * + * The root is returned if no common base path can be found: + * + * ```php + * $basePath = Path::getLongestCommonBasePath(array( + * '/webmozart/css/style.css', + * '/puli/css/..' + * )); + * // => / + * ``` + * + * If the paths are located on different Windows partitions, `null` is + * returned. + * + * ```php + * $basePath = Path::getLongestCommonBasePath(array( + * 'C:/webmozart/css/style.css', + * 'D:/webmozart/css/..' + * )); + * // => null + * ``` + * + * @param string[] $paths A list of paths. + * + * @return string|null The longest common base path in canonical form or + * `null` if the paths are on different Windows + * partitions. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $paths are not strings. + */ + public static function getLongestCommonBasePath(array $paths): ?string + { + [$bpRoot, $basePath] = self::split(self::canonicalize(reset($paths))); + + for (next($paths); null !== key($paths) && '' !== $basePath; next($paths)) { + [$root, $path] = self::split(self::canonicalize(current($paths))); + + // If we deal with different roots (e.g. C:/ vs. D:/), it's time + // to quit + if ($root !== $bpRoot) { + return null; + } + + // Make the base path shorter until it fits into path + while (true) { + if ('.' === $basePath) { + // No more base paths + $basePath = ''; + + // Next path + continue 2; + } + + // Prevent false positives for common prefixes + // see isBasePath() + if (0 === strpos($path.'/', $basePath.'/')) { + // Next path + continue 2; + } + + $basePath = dirname($basePath); + } + } + + return $bpRoot.$basePath; + } + + /** + * Joins two or more path strings. + * + * The result is a canonical path. + * + * @param string[]|string $paths Path parts as parameters or array. + * + * @return string The joint path. + * + * @since 2.0 Added method. + */ + public static function join(string ...$paths): string + { + $finalPath = null; + $wasScheme = false; + + foreach ($paths as $path) { + $path = (string) $path; + + if ('' === $path) { + continue; + } + + if (null === $finalPath) { + // For first part we keep slashes, like '/top', 'C:\' or 'phar://' + $finalPath = $path; + $wasScheme = (strpos($path, '://') !== false); + continue; + } + + // Only add slash if previous part didn't end with '/' or '\' + if (!in_array(substr($finalPath, -1), array('/', '\\'))) { + $finalPath .= '/'; + } + + // If first part included a scheme like 'phar://' we allow current part to start with '/', otherwise trim + $finalPath .= $wasScheme ? $path : ltrim($path, '/'); + $wasScheme = false; + } + + if (null === $finalPath) { + return ''; + } + + return self::canonicalize($finalPath); + } + + /** + * Returns whether a path is a base path of another path. + * + * Dot segments ("." and "..") are removed/collapsed and all slashes turned + * into forward slashes. + * + * ```php + * Path::isBasePath('/webmozart', '/webmozart/css'); + * // => true + * + * Path::isBasePath('/webmozart', '/webmozart'); + * // => true + * + * Path::isBasePath('/webmozart', '/webmozart/..'); + * // => false + * + * Path::isBasePath('/webmozart', '/puli'); + * // => false + * ``` + * + * @param string $basePath The base path to test. + * @param string $ofPath The other path. + * + * @return bool Whether the base path is a base path of the other path. + * + * @since 1.0 Added method. + * @since 2.0 Method now fails if $basePath or $ofPath is not a string. + */ + public static function isBasePath(string $basePath, string $ofPath): bool + { + $basePath = self::canonicalize($basePath); + $ofPath = self::canonicalize($ofPath); + + // Append slashes to prevent false positives when two paths have + // a common prefix, for example /base/foo and /base/foobar. + // Don't append a slash for the root "/", because then that root + // won't be discovered as common prefix ("//" is not a prefix of + // "/foobar/"). + return 0 === strpos($ofPath.'/', rtrim($basePath, '/').'/'); + } + + /** + * Splits a part into its root directory and the remainder. + * + * If the path has no root directory, an empty root directory will be + * returned. + * + * If the root directory is a Windows style partition, the resulting root + * will always contain a trailing slash. + * + * list ($root, $path) = Path::split("C:/webmozart") + * // => array("C:/", "webmozart") + * + * list ($root, $path) = Path::split("C:") + * // => array("C:/", "") + * + * @param string $path The canonical path to split. + * + * @return string[] An array with the root directory and the remaining + * relative path. + */ + private static function split(string $path): array + { + if ('' === $path) { + return ['', '']; + } + + // Remember scheme as part of the root, if any + if (false !== ($pos = strpos($path, '://'))) { + $root = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); + } else { + $root = ''; + } + + $length = strlen($path); + + // Remove and remember root directory + if (strpos($path, '/') === 0) { + $root .= '/'; + $path = $length > 1 ? substr($path, 1) : ''; + } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + if (2 === $length) { + // Windows special case: "C:" + $root .= $path.'/'; + $path = ''; + } elseif ('/' === $path[2]) { + // Windows normal case: "C:/".. + $root .= substr($path, 0, 3); + $path = $length > 3 ? substr($path, 3) : ''; + } + } + + return [$root, $path]; + } + + /** + * Converts string to lower-case (multi-byte safe if mbstring is installed). + * + * @param string $str The string + * + * @return string Lower case string + */ + private static function toLower(string $str): string + { + if (function_exists('mb_strtolower')) { + return mb_strtolower($str, mb_detect_encoding($str)); + } + + return strtolower($str); + } + + private function __construct() + { + } +} diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php new file mode 100644 index 0000000000000..6b3b6921bb58a --- /dev/null +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -0,0 +1,1341 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Filesystem\Path; + +/** + * @since 1.0 + * + * @author Bernhard Schussek + * @author Thomas Schulz + */ +class PathTest extends TestCase +{ + protected $storedEnv = array(); + + public function setUp() + { + $this->storedEnv['HOME'] = getenv('HOME'); + $this->storedEnv['HOMEDRIVE'] = getenv('HOMEDRIVE'); + $this->storedEnv['HOMEPATH'] = getenv('HOMEPATH'); + + putenv('HOME=/home/webmozart'); + putenv('HOMEDRIVE='); + putenv('HOMEPATH='); + } + + public function tearDown() + { + putenv('HOME=' . $this->storedEnv['HOME']); + putenv('HOMEDRIVE=' . $this->storedEnv['HOMEDRIVE']); + putenv('HOMEPATH=' . $this->storedEnv['HOMEPATH']); + } + + public function provideCanonicalizationTests() + { + return array( + // relative paths (forward slash) + array('css/./style.css', 'css/style.css'), + array('css/../style.css', 'style.css'), + array('css/./../style.css', 'style.css'), + array('css/.././style.css', 'style.css'), + array('css/../../style.css', '../style.css'), + array('./css/style.css', 'css/style.css'), + array('../css/style.css', '../css/style.css'), + array('./../css/style.css', '../css/style.css'), + array('.././css/style.css', '../css/style.css'), + array('../../css/style.css', '../../css/style.css'), + array('', ''), + array('.', ''), + array('..', '..'), + array('./..', '..'), + array('../.', '..'), + array('../..', '../..'), + + // relative paths (backslash) + array('css\\.\\style.css', 'css/style.css'), + array('css\\..\\style.css', 'style.css'), + array('css\\.\\..\\style.css', 'style.css'), + array('css\\..\\.\\style.css', 'style.css'), + array('css\\..\\..\\style.css', '../style.css'), + array('.\\css\\style.css', 'css/style.css'), + array('..\\css\\style.css', '../css/style.css'), + array('.\\..\\css\\style.css', '../css/style.css'), + array('..\\.\\css\\style.css', '../css/style.css'), + array('..\\..\\css\\style.css', '../../css/style.css'), + + // absolute paths (forward slash, UNIX) + array('/css/style.css', '/css/style.css'), + array('/css/./style.css', '/css/style.css'), + array('/css/../style.css', '/style.css'), + array('/css/./../style.css', '/style.css'), + array('/css/.././style.css', '/style.css'), + array('/./css/style.css', '/css/style.css'), + array('/../css/style.css', '/css/style.css'), + array('/./../css/style.css', '/css/style.css'), + array('/.././css/style.css', '/css/style.css'), + array('/../../css/style.css', '/css/style.css'), + + // absolute paths (backslash, UNIX) + array('\\css\\style.css', '/css/style.css'), + array('\\css\\.\\style.css', '/css/style.css'), + array('\\css\\..\\style.css', '/style.css'), + array('\\css\\.\\..\\style.css', '/style.css'), + array('\\css\\..\\.\\style.css', '/style.css'), + array('\\.\\css\\style.css', '/css/style.css'), + array('\\..\\css\\style.css', '/css/style.css'), + array('\\.\\..\\css\\style.css', '/css/style.css'), + array('\\..\\.\\css\\style.css', '/css/style.css'), + array('\\..\\..\\css\\style.css', '/css/style.css'), + + // absolute paths (forward slash, Windows) + array('C:/css/style.css', 'C:/css/style.css'), + array('C:/css/./style.css', 'C:/css/style.css'), + array('C:/css/../style.css', 'C:/style.css'), + array('C:/css/./../style.css', 'C:/style.css'), + array('C:/css/.././style.css', 'C:/style.css'), + array('C:/./css/style.css', 'C:/css/style.css'), + array('C:/../css/style.css', 'C:/css/style.css'), + array('C:/./../css/style.css', 'C:/css/style.css'), + array('C:/.././css/style.css', 'C:/css/style.css'), + array('C:/../../css/style.css', 'C:/css/style.css'), + + // absolute paths (backslash, Windows) + array('C:\\css\\style.css', 'C:/css/style.css'), + array('C:\\css\\.\\style.css', 'C:/css/style.css'), + array('C:\\css\\..\\style.css', 'C:/style.css'), + array('C:\\css\\.\\..\\style.css', 'C:/style.css'), + array('C:\\css\\..\\.\\style.css', 'C:/style.css'), + array('C:\\.\\css\\style.css', 'C:/css/style.css'), + array('C:\\..\\css\\style.css', 'C:/css/style.css'), + array('C:\\.\\..\\css\\style.css', 'C:/css/style.css'), + array('C:\\..\\.\\css\\style.css', 'C:/css/style.css'), + array('C:\\..\\..\\css\\style.css', 'C:/css/style.css'), + + // Windows special case + array('C:', 'C:/'), + + // Don't change malformed path + array('C:css/style.css', 'C:css/style.css'), + + // absolute paths (stream, UNIX) + array('phar:///css/style.css', 'phar:///css/style.css'), + array('phar:///css/./style.css', 'phar:///css/style.css'), + array('phar:///css/../style.css', 'phar:///style.css'), + array('phar:///css/./../style.css', 'phar:///style.css'), + array('phar:///css/.././style.css', 'phar:///style.css'), + array('phar:///./css/style.css', 'phar:///css/style.css'), + array('phar:///../css/style.css', 'phar:///css/style.css'), + array('phar:///./../css/style.css', 'phar:///css/style.css'), + array('phar:///.././css/style.css', 'phar:///css/style.css'), + array('phar:///../../css/style.css', 'phar:///css/style.css'), + + // absolute paths (stream, Windows) + array('phar://C:/css/style.css', 'phar://C:/css/style.css'), + array('phar://C:/css/./style.css', 'phar://C:/css/style.css'), + array('phar://C:/css/../style.css', 'phar://C:/style.css'), + array('phar://C:/css/./../style.css', 'phar://C:/style.css'), + array('phar://C:/css/.././style.css', 'phar://C:/style.css'), + array('phar://C:/./css/style.css', 'phar://C:/css/style.css'), + array('phar://C:/../css/style.css', 'phar://C:/css/style.css'), + array('phar://C:/./../css/style.css', 'phar://C:/css/style.css'), + array('phar://C:/.././css/style.css', 'phar://C:/css/style.css'), + array('phar://C:/../../css/style.css', 'phar://C:/css/style.css'), + + // paths with "~" UNIX + array('~/css/style.css', '/home/webmozart/css/style.css'), + array('~/css/./style.css', '/home/webmozart/css/style.css'), + array('~/css/../style.css', '/home/webmozart/style.css'), + array('~/css/./../style.css', '/home/webmozart/style.css'), + array('~/css/.././style.css', '/home/webmozart/style.css'), + array('~/./css/style.css', '/home/webmozart/css/style.css'), + array('~/../css/style.css', '/home/css/style.css'), + array('~/./../css/style.css', '/home/css/style.css'), + array('~/.././css/style.css', '/home/css/style.css'), + array('~/../../css/style.css', '/css/style.css'), + ); + } + + /** + * @dataProvider provideCanonicalizationTests + */ + public function testCanonicalize($path, $canonicalized) + { + $this->assertSame($canonicalized, Path::canonicalize($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testCanonicalizeFailsIfInvalidPath() + { + Path::canonicalize(array()); + } + + public function provideGetDirectoryTests() + { + return array( + array('/webmozart/puli/style.css', '/webmozart/puli'), + array('/webmozart/puli', '/webmozart'), + array('/webmozart', '/'), + array('/', '/'), + array('', ''), + + array('\\webmozart\\puli\\style.css', '/webmozart/puli'), + array('\\webmozart\\puli', '/webmozart'), + array('\\webmozart', '/'), + array('\\', '/'), + + array('C:/webmozart/puli/style.css', 'C:/webmozart/puli'), + array('C:/webmozart/puli', 'C:/webmozart'), + array('C:/webmozart', 'C:/'), + array('C:/', 'C:/'), + array('C:', 'C:/'), + + array('C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli'), + array('C:\\webmozart\\puli', 'C:/webmozart'), + array('C:\\webmozart', 'C:/'), + array('C:\\', 'C:/'), + + array('phar:///webmozart/puli/style.css', 'phar:///webmozart/puli'), + array('phar:///webmozart/puli', 'phar:///webmozart'), + array('phar:///webmozart', 'phar:///'), + array('phar:///', 'phar:///'), + + array('phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli'), + array('phar://C:/webmozart/puli', 'phar://C:/webmozart'), + array('phar://C:/webmozart', 'phar://C:/'), + array('phar://C:/', 'phar://C:/'), + + array('webmozart/puli/style.css', 'webmozart/puli'), + array('webmozart/puli', 'webmozart'), + array('webmozart', ''), + + array('webmozart\\puli\\style.css', 'webmozart/puli'), + array('webmozart\\puli', 'webmozart'), + array('webmozart', ''), + + array('/webmozart/./puli/style.css', '/webmozart/puli'), + array('/webmozart/../puli/style.css', '/puli'), + array('/webmozart/./../puli/style.css', '/puli'), + array('/webmozart/.././puli/style.css', '/puli'), + array('/webmozart/../../puli/style.css', '/puli'), + array('/.', '/'), + array('/..', '/'), + + array('C:webmozart', ''), + ); + } + + /** + * @dataProvider provideGetDirectoryTests + */ + public function testGetDirectory($path, $directory) + { + $this->assertSame($directory, Path::getDirectory($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testGetDirectoryFailsIfInvalidPath() + { + Path::getDirectory(array()); + } + + public function provideGetFilenameTests() + { + return array( + array('/webmozart/puli/style.css', 'style.css'), + array('/webmozart/puli/STYLE.CSS', 'STYLE.CSS'), + array('/webmozart/puli/style.css/', 'style.css'), + array('/webmozart/puli/', 'puli'), + array('/webmozart/puli', 'puli'), + array('/', ''), + array('', ''), + ); + } + + /** + * @dataProvider provideGetFilenameTests + */ + public function testGetFilename($path, $filename) + { + $this->assertSame($filename, Path::getFilename($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testGetFilenameFailsIfInvalidPath() + { + Path::getFilename(array()); + } + + public function provideGetFilenameWithoutExtensionTests() + { + return array( + array('/webmozart/puli/style.css.twig', null, 'style.css'), + array('/webmozart/puli/style.css.', null, 'style.css'), + array('/webmozart/puli/style.css', null, 'style'), + array('/webmozart/puli/.style.css', null, '.style'), + array('/webmozart/puli/', null, 'puli'), + array('/webmozart/puli', null, 'puli'), + array('/', null, ''), + array('', null, ''), + + array('/webmozart/puli/style.css', 'css', 'style'), + array('/webmozart/puli/style.css', '.css', 'style'), + array('/webmozart/puli/style.css', 'twig', 'style.css'), + array('/webmozart/puli/style.css', '.twig', 'style.css'), + array('/webmozart/puli/style.css', '', 'style.css'), + array('/webmozart/puli/style.css.', '', 'style.css'), + array('/webmozart/puli/style.css.', '.', 'style.css'), + array('/webmozart/puli/style.css.', '.css', 'style.css'), + array('/webmozart/puli/.style.css', 'css', '.style'), + array('/webmozart/puli/.style.css', '.css', '.style'), + ); + } + + /** + * @dataProvider provideGetFilenameWithoutExtensionTests + */ + public function testGetFilenameWithoutExtension($path, $extension, $filename) + { + $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testGetFilenameWithoutExtensionFailsIfInvalidPath() + { + Path::getFilenameWithoutExtension(array(), '.css'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The extension must be a string or null. Got: array + */ + public function testGetFilenameWithoutExtensionFailsIfInvalidExtension() + { + Path::getFilenameWithoutExtension('/style.css', array()); + } + + public function provideGetExtensionTests() + { + $tests = array( + array('/webmozart/puli/style.css.twig', false, 'twig'), + array('/webmozart/puli/style.css', false, 'css'), + array('/webmozart/puli/style.css.', false, ''), + array('/webmozart/puli/', false, ''), + array('/webmozart/puli', false, ''), + array('/', false, ''), + array('', false, ''), + + array('/webmozart/puli/style.CSS', false, 'CSS'), + array('/webmozart/puli/style.CSS', true, 'css'), + array('/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ'), + ); + + if (extension_loaded('mbstring')) { + // This can only be tested, when mbstring is installed + $tests[] = array('/webmozart/puli/style.ÄÖÜ', true, 'äöü'); + } + + return $tests; + } + + /** + * @dataProvider provideGetExtensionTests + */ + public function testGetExtension($path, $forceLowerCase, $extension) + { + $this->assertSame($extension, Path::getExtension($path, $forceLowerCase)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testGetExtensionFailsIfInvalidPath() + { + Path::getExtension(array()); + } + + public function provideHasExtensionTests() + { + $tests = array( + array(true, '/webmozart/puli/style.css.twig', null, false), + array(true, '/webmozart/puli/style.css', null, false), + array(false, '/webmozart/puli/style.css.', null, false), + array(false, '/webmozart/puli/', null, false), + array(false, '/webmozart/puli', null, false), + array(false, '/', null, false), + array(false, '', null, false), + + array(true, '/webmozart/puli/style.css.twig', 'twig', false), + array(false, '/webmozart/puli/style.css.twig', 'css', false), + array(true, '/webmozart/puli/style.css', 'css', false), + array(true, '/webmozart/puli/style.css', '.css', false), + array(true, '/webmozart/puli/style.css.', '', false), + array(false, '/webmozart/puli/', 'ext', false), + array(false, '/webmozart/puli', 'ext', false), + array(false, '/', 'ext', false), + array(false, '', 'ext', false), + + array(false, '/webmozart/puli/style.css', 'CSS', false), + array(true, '/webmozart/puli/style.css', 'CSS', true), + array(false, '/webmozart/puli/style.CSS', 'css', false), + array(true, '/webmozart/puli/style.CSS', 'css', true), + array(true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false), + + array(true, '/webmozart/puli/style.css', array('ext', 'css'), false), + array(true, '/webmozart/puli/style.css', array('.ext', '.css'), false), + array(true, '/webmozart/puli/style.css.', array('ext', ''), false), + array(false, '/webmozart/puli/style.css', array('foo', 'bar', ''), false), + array(false, '/webmozart/puli/style.css', array('.foo', '.bar', ''), false), + ); + + if (extension_loaded('mbstring')) { + // This can only be tested, when mbstring is installed + $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true); + $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', array('äöü'), true); + } + + return $tests; + } + + /** + * @dataProvider provideHasExtensionTests + */ + public function testHasExtension($hasExtension, $path, $extension, $ignoreCase) + { + $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testHasExtensionFailsIfInvalidPath() + { + Path::hasExtension(array()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The extensions must be strings. Got: stdClass + */ + public function testHasExtensionFailsIfInvalidExtension() + { + Path::hasExtension('/style.css', (object)array()); + } + + public function provideChangeExtensionTests() + { + return array( + array('/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html'), + array('/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass'), + array('/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass'), + array('/webmozart/puli/style.css', '', '/webmozart/puli/style.'), + array('/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig'), + array('/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.'), + array('/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü'), + array('/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css'), + array('/webmozart/puli/', 'css', '/webmozart/puli/'), + array('/webmozart/puli', 'css', '/webmozart/puli.css'), + array('/', 'css', '/'), + array('', 'css', ''), + ); + } + + /** + * @dataProvider provideChangeExtensionTests + */ + public function testChangeExtension($path, $extension, $pathExpected) + { + static $call = 0; + $this->assertSame($pathExpected, Path::changeExtension($path, $extension)); + ++$call; + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testChangeExtensionFailsIfInvalidPath() + { + Path::changeExtension(array(), '.sass'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The extension must be a string. Got: array + */ + public function testChangeExtensionFailsIfInvalidExtension() + { + Path::changeExtension('/style.css', array()); + } + + public function provideIsAbsolutePathTests() + { + return array( + array('/css/style.css', true), + array('/', true), + array('css/style.css', false), + array('', false), + + array('\\css\\style.css', true), + array('\\', true), + array('css\\style.css', false), + + array('C:/css/style.css', true), + array('D:/', true), + + array('E:\\css\\style.css', true), + array('F:\\', true), + + array('phar:///css/style.css', true), + array('phar:///', true), + + // Windows special case + array('C:', true), + + // Not considered absolute + array('C:css/style.css', false), + ); + } + + /** + * @dataProvider provideIsAbsolutePathTests + */ + public function testIsAbsolute($path, $isAbsolute) + { + $this->assertSame($isAbsolute, Path::isAbsolute($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testIsAbsoluteFailsIfInvalidPath() + { + Path::isAbsolute(array()); + } + + /** + * @dataProvider provideIsAbsolutePathTests + */ + public function testIsRelative($path, $isAbsolute) + { + $this->assertSame(!$isAbsolute, Path::isRelative($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testIsRelativeFailsIfInvalidPath() + { + Path::isRelative(array()); + } + + public function provideGetRootTests() + { + return array( + array('/css/style.css', '/'), + array('/', '/'), + array('css/style.css', ''), + array('', ''), + + array('\\css\\style.css', '/'), + array('\\', '/'), + array('css\\style.css', ''), + + array('C:/css/style.css', 'C:/'), + array('C:/', 'C:/'), + array('C:', 'C:/'), + + array('D:\\css\\style.css', 'D:/'), + array('D:\\', 'D:/'), + + array('phar:///css/style.css', 'phar:///'), + array('phar:///', 'phar:///'), + + array('phar://C:/css/style.css', 'phar://C:/'), + array('phar://C:/', 'phar://C:/'), + array('phar://C:', 'phar://C:/'), + ); + } + + /** + * @dataProvider provideGetRootTests + */ + public function testGetRoot($path, $root) + { + $this->assertSame($root, Path::getRoot($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testGetRootFailsIfInvalidPath() + { + Path::getRoot(array()); + } + + public function providePathTests() + { + return array( + // relative to absolute path + array('css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), + array('../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'), + array('../../css/style.css', '/webmozart/puli', '/css/style.css'), + + // relative to root + array('css/style.css', '/', '/css/style.css'), + array('css/style.css', 'C:', 'C:/css/style.css'), + array('css/style.css', 'C:/', 'C:/css/style.css'), + + // same sub directories in different base directories + array('../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'), + + array('', '/webmozart/puli', '/webmozart/puli'), + array('..', '/webmozart/puli', '/webmozart'), + ); + } + + public function provideMakeAbsoluteTests() + { + return array_merge($this->providePathTests(), array( + // collapse dots + array('css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), + array('css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'), + array('css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'), + array('css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'), + array('./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), + + array('css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'), + array('css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), + array('css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), + array('css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), + array('.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'), + + // collapse dots on root + array('./css/style.css', '/', '/css/style.css'), + array('../css/style.css', '/', '/css/style.css'), + array('../css/./style.css', '/', '/css/style.css'), + array('../css/../style.css', '/', '/style.css'), + array('../css/./../style.css', '/', '/style.css'), + array('../css/.././style.css', '/', '/style.css'), + + array('.\\css\\style.css', '\\', '/css/style.css'), + array('..\\css\\style.css', '\\', '/css/style.css'), + array('..\\css\\.\\style.css', '\\', '/css/style.css'), + array('..\\css\\..\\style.css', '\\', '/style.css'), + array('..\\css\\.\\..\\style.css', '\\', '/style.css'), + array('..\\css\\..\\.\\style.css', '\\', '/style.css'), + + array('./css/style.css', 'C:/', 'C:/css/style.css'), + array('../css/style.css', 'C:/', 'C:/css/style.css'), + array('../css/./style.css', 'C:/', 'C:/css/style.css'), + array('../css/../style.css', 'C:/', 'C:/style.css'), + array('../css/./../style.css', 'C:/', 'C:/style.css'), + array('../css/.././style.css', 'C:/', 'C:/style.css'), + + array('.\\css\\style.css', 'C:\\', 'C:/css/style.css'), + array('..\\css\\style.css', 'C:\\', 'C:/css/style.css'), + array('..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'), + array('..\\css\\..\\style.css', 'C:\\', 'C:/style.css'), + array('..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'), + array('..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'), + + array('./css/style.css', 'phar:///', 'phar:///css/style.css'), + array('../css/style.css', 'phar:///', 'phar:///css/style.css'), + array('../css/./style.css', 'phar:///', 'phar:///css/style.css'), + array('../css/../style.css', 'phar:///', 'phar:///style.css'), + array('../css/./../style.css', 'phar:///', 'phar:///style.css'), + array('../css/.././style.css', 'phar:///', 'phar:///style.css'), + + array('./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'), + array('../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'), + array('../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'), + array('../css/../style.css', 'phar://C:/', 'phar://C:/style.css'), + array('../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'), + array('../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'), + + // absolute paths + array('/css/style.css', '/webmozart/puli', '/css/style.css'), + array('\\css\\style.css', '/webmozart/puli', '/css/style.css'), + array('C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'), + array('D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'), + )); + } + + /** + * @dataProvider provideMakeAbsoluteTests + */ + public function testMakeAbsolute($relativePath, $basePath, $absolutePath) + { + $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testMakeAbsoluteFailsIfInvalidPath() + { + Path::makeAbsolute(array(), '/webmozart/puli'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a non-empty string. Got: array + */ + public function testMakeAbsoluteFailsIfInvalidBasePath() + { + Path::makeAbsolute('css/style.css', array()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path "webmozart/puli" is not an absolute path. + */ + public function testMakeAbsoluteFailsIfBasePathNotAbsolute() + { + Path::makeAbsolute('css/style.css', 'webmozart/puli'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a non-empty string. Got: "" + */ + public function testMakeAbsoluteFailsIfBasePathEmpty() + { + Path::makeAbsolute('css/style.css', ''); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a non-empty string. Got: NULL + */ + public function testMakeAbsoluteFailsIfBasePathNull() + { + Path::makeAbsolute('css/style.css', null); + } + + public function provideAbsolutePathsWithDifferentRoots() + { + return array( + array('C:/css/style.css', '/webmozart/puli'), + array('C:/css/style.css', '\\webmozart\\puli'), + array('C:\\css\\style.css', '/webmozart/puli'), + array('C:\\css\\style.css', '\\webmozart\\puli'), + + array('/css/style.css', 'C:/webmozart/puli'), + array('/css/style.css', 'C:\\webmozart\\puli'), + array('\\css\\style.css', 'C:/webmozart/puli'), + array('\\css\\style.css', 'C:\\webmozart\\puli'), + + array('D:/css/style.css', 'C:/webmozart/puli'), + array('D:/css/style.css', 'C:\\webmozart\\puli'), + array('D:\\css\\style.css', 'C:/webmozart/puli'), + array('D:\\css\\style.css', 'C:\\webmozart\\puli'), + + array('phar:///css/style.css', '/webmozart/puli'), + array('/css/style.css', 'phar:///webmozart/puli'), + + array('phar://C:/css/style.css', 'C:/webmozart/puli'), + array('phar://C:/css/style.css', 'C:\\webmozart\\puli'), + array('phar://C:\\css\\style.css', 'C:/webmozart/puli'), + array('phar://C:\\css\\style.css', 'C:\\webmozart\\puli'), + ); + } + + /** + * @dataProvider provideAbsolutePathsWithDifferentRoots + */ + public function testMakeAbsoluteDoesNotFailIfDifferentRoot($basePath, $absolutePath) + { + // If a path in partition D: is passed, but $basePath is in partition + // C:, the path should be returned unchanged + $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath)); + } + + public function provideMakeRelativeTests() + { + $paths = array_map(function (array $arguments) { + return array($arguments[2], $arguments[1], $arguments[0]); + }, $this->providePathTests()); + + return array_merge($paths, array( + array('/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'), + array('/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'), + array('/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'), + array('/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'), + array('/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'), + array('/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'), + array('/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'), + array('/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'), + array('/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'), + array('/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'), + + // first argument shorter than second + array('/css', '/webmozart/puli', '../../css'), + + // second argument shorter than first + array('/webmozart/puli', '/css', '../webmozart/puli'), + + array('\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'), + array('\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'), + array('\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'), + + array('C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'), + array('C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'), + array('C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'), + + array('C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'), + array('C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'), + array('C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'), + + array('phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'), + array('phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'), + array('phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'), + + array('phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'), + array('phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'), + array('phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'), + + // already relative + already in root basepath + array('../style.css', '/', 'style.css'), + array('./style.css', '/', 'style.css'), + array('../../style.css', '/', 'style.css'), + array('..\\style.css', 'C:\\', 'style.css'), + array('.\\style.css', 'C:\\', 'style.css'), + array('..\\..\\style.css', 'C:\\', 'style.css'), + array('../style.css', 'C:/', 'style.css'), + array('./style.css', 'C:/', 'style.css'), + array('../../style.css', 'C:/', 'style.css'), + array('..\\style.css', '\\', 'style.css'), + array('.\\style.css', '\\', 'style.css'), + array('..\\..\\style.css', '\\', 'style.css'), + array('../style.css', 'phar:///', 'style.css'), + array('./style.css', 'phar:///', 'style.css'), + array('../../style.css', 'phar:///', 'style.css'), + array('..\\style.css', 'phar://C:\\', 'style.css'), + array('.\\style.css', 'phar://C:\\', 'style.css'), + array('..\\..\\style.css', 'phar://C:\\', 'style.css'), + + array('css/../style.css', '/', 'style.css'), + array('css/./style.css', '/', 'css/style.css'), + array('css\\..\\style.css', 'C:\\', 'style.css'), + array('css\\.\\style.css', 'C:\\', 'css/style.css'), + array('css/../style.css', 'C:/', 'style.css'), + array('css/./style.css', 'C:/', 'css/style.css'), + array('css\\..\\style.css', '\\', 'style.css'), + array('css\\.\\style.css', '\\', 'css/style.css'), + array('css/../style.css', 'phar:///', 'style.css'), + array('css/./style.css', 'phar:///', 'css/style.css'), + array('css\\..\\style.css', 'phar://C:\\', 'style.css'), + array('css\\.\\style.css', 'phar://C:\\', 'css/style.css'), + + // already relative + array('css/style.css', '/webmozart/puli', 'css/style.css'), + array('css\\style.css', '\\webmozart\\puli', 'css/style.css'), + + // both relative + array('css/style.css', 'webmozart/puli', '../../css/style.css'), + array('css\\style.css', 'webmozart\\puli', '../../css/style.css'), + + // relative to empty + array('css/style.css', '', 'css/style.css'), + array('css\\style.css', '', 'css/style.css'), + + // different slashes in path and base path + array('/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'), + array('\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'), + )); + } + + /** + * @dataProvider provideMakeRelativeTests + */ + public function testMakeRelative($absolutePath, $basePath, $relativePath) + { + $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testMakeRelativeFailsIfInvalidPath() + { + Path::makeRelative(array(), '/webmozart/puli'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a string. Got: array + */ + public function testMakeRelativeFailsIfInvalidBasePath() + { + Path::makeRelative('/webmozart/puli/css/style.css', array()); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "webmozart/puli". You should provide an absolute base path instead. + */ + public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute() + { + Path::makeRelative('/webmozart/puli/css/style.css', 'webmozart/puli'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead. + */ + public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty() + { + Path::makeRelative('/webmozart/puli/css/style.css', ''); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a string. Got: NULL + */ + public function testMakeRelativeFailsIfBasePathNull() + { + Path::makeRelative('/webmozart/puli/css/style.css', null); + } + + /** + * @dataProvider provideAbsolutePathsWithDifferentRoots + * @expectedException \InvalidArgumentException + */ + public function testMakeRelativeFailsIfDifferentRoot($absolutePath, $basePath) + { + Path::makeRelative($absolutePath, $basePath); + } + + public function provideIsLocalTests() + { + return array( + array('/bg.png', true), + array('bg.png', true), + array('http://example.com/bg.png', false), + array('http://example.com', false), + array('', false), + ); + } + + /** + * @dataProvider provideIsLocalTests + */ + public function testIsLocal($path, $isLocal) + { + $this->assertSame($isLocal, Path::isLocal($path)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testIsLocalFailsIfInvalidPath() + { + Path::isLocal(array()); + } + + public function provideGetLongestCommonBasePathTests() + { + return array( + // same paths + array(array('/base/path', '/base/path'), '/base/path'), + array(array('C:/base/path', 'C:/base/path'), 'C:/base/path'), + array(array('C:\\base\\path', 'C:\\base\\path'), 'C:/base/path'), + array(array('C:/base/path', 'C:\\base\\path'), 'C:/base/path'), + array(array('phar:///base/path', 'phar:///base/path'), 'phar:///base/path'), + array(array('phar://C:/base/path', 'phar://C:/base/path'), 'phar://C:/base/path'), + + // trailing slash + array(array('/base/path/', '/base/path'), '/base/path'), + array(array('C:/base/path/', 'C:/base/path'), 'C:/base/path'), + array(array('C:\\base\\path\\', 'C:\\base\\path'), 'C:/base/path'), + array(array('C:/base/path/', 'C:\\base\\path'), 'C:/base/path'), + array(array('phar:///base/path/', 'phar:///base/path'), 'phar:///base/path'), + array(array('phar://C:/base/path/', 'phar://C:/base/path'), 'phar://C:/base/path'), + + array(array('/base/path', '/base/path/'), '/base/path'), + array(array('C:/base/path', 'C:/base/path/'), 'C:/base/path'), + array(array('C:\\base\\path', 'C:\\base\\path\\'), 'C:/base/path'), + array(array('C:/base/path', 'C:\\base\\path\\'), 'C:/base/path'), + array(array('phar:///base/path', 'phar:///base/path/'), 'phar:///base/path'), + array(array('phar://C:/base/path', 'phar://C:/base/path/'), 'phar://C:/base/path'), + + // first in second + array(array('/base/path/sub', '/base/path'), '/base/path'), + array(array('C:/base/path/sub', 'C:/base/path'), 'C:/base/path'), + array(array('C:\\base\\path\\sub', 'C:\\base\\path'), 'C:/base/path'), + array(array('C:/base/path/sub', 'C:\\base\\path'), 'C:/base/path'), + array(array('phar:///base/path/sub', 'phar:///base/path'), 'phar:///base/path'), + array(array('phar://C:/base/path/sub', 'phar://C:/base/path'), 'phar://C:/base/path'), + + // second in first + array(array('/base/path', '/base/path/sub'), '/base/path'), + array(array('C:/base/path', 'C:/base/path/sub'), 'C:/base/path'), + array(array('C:\\base\\path', 'C:\\base\\path\\sub'), 'C:/base/path'), + array(array('C:/base/path', 'C:\\base\\path\\sub'), 'C:/base/path'), + array(array('phar:///base/path', 'phar:///base/path/sub'), 'phar:///base/path'), + array(array('phar://C:/base/path', 'phar://C:/base/path/sub'), 'phar://C:/base/path'), + + // first is prefix + array(array('/base/path/di', '/base/path/dir'), '/base/path'), + array(array('C:/base/path/di', 'C:/base/path/dir'), 'C:/base/path'), + array(array('C:\\base\\path\\di', 'C:\\base\\path\\dir'), 'C:/base/path'), + array(array('C:/base/path/di', 'C:\\base\\path\\dir'), 'C:/base/path'), + array(array('phar:///base/path/di', 'phar:///base/path/dir'), 'phar:///base/path'), + array(array('phar://C:/base/path/di', 'phar://C:/base/path/dir'), 'phar://C:/base/path'), + + // second is prefix + array(array('/base/path/dir', '/base/path/di'), '/base/path'), + array(array('C:/base/path/dir', 'C:/base/path/di'), 'C:/base/path'), + array(array('C:\\base\\path\\dir', 'C:\\base\\path\\di'), 'C:/base/path'), + array(array('C:/base/path/dir', 'C:\\base\\path\\di'), 'C:/base/path'), + array(array('phar:///base/path/dir', 'phar:///base/path/di'), 'phar:///base/path'), + array(array('phar://C:/base/path/dir', 'phar://C:/base/path/di'), 'phar://C:/base/path'), + + // root is common base path + array(array('/first', '/second'), '/'), + array(array('C:/first', 'C:/second'), 'C:/'), + array(array('C:\\first', 'C:\\second'), 'C:/'), + array(array('C:/first', 'C:\\second'), 'C:/'), + array(array('phar:///first', 'phar:///second'), 'phar:///'), + array(array('phar://C:/first', 'phar://C:/second'), 'phar://C:/'), + + // windows vs unix + array(array('/base/path', 'C:/base/path'), null), + array(array('C:/base/path', '/base/path'), null), + array(array('/base/path', 'C:\\base\\path'), null), + array(array('phar:///base/path', 'phar://C:/base/path'), null), + + // different partitions + array(array('C:/base/path', 'D:/base/path'), null), + array(array('C:/base/path', 'D:\\base\\path'), null), + array(array('C:\\base\\path', 'D:\\base\\path'), null), + array(array('phar://C:/base/path', 'phar://D:/base/path'), null), + + // three paths + array(array('/base/path/foo', '/base/path', '/base/path/bar'), '/base/path'), + array(array('C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'), 'C:/base/path'), + array(array('C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'), 'C:/base/path'), + array(array('C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'), 'C:/base/path'), + array(array('phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'), 'phar:///base/path'), + array(array('phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'), 'phar://C:/base/path'), + + // three paths with root + array(array('/base/path/foo', '/', '/base/path/bar'), '/'), + array(array('C:/base/path/foo', 'C:/', 'C:/base/path/bar'), 'C:/'), + array(array('C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'), 'C:/'), + array(array('C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'), 'C:/'), + array(array('phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'), 'phar:///'), + array(array('phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'), 'phar://C:/'), + + // three paths, different roots + array(array('/base/path/foo', 'C:/base/path', '/base/path/bar'), null), + array(array('/base/path/foo', 'C:\\base\\path', '/base/path/bar'), null), + array(array('C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'), null), + array(array('C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'), null), + array(array('C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'), null), + array(array('phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'), null), + array(array('phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'), null), + + // only one path + array(array('/base/path'), '/base/path'), + array(array('C:/base/path'), 'C:/base/path'), + array(array('C:\\base\\path'), 'C:/base/path'), + array(array('phar:///base/path'), 'phar:///base/path'), + array(array('phar://C:/base/path'), 'phar://C:/base/path'), + ); + } + + /** + * @dataProvider provideGetLongestCommonBasePathTests + */ + public function testGetLongestCommonBasePath(array $paths, $basePath) + { + $this->assertSame($basePath, Path::getLongestCommonBasePath($paths)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The paths must be strings. Got: array + */ + public function testGetLongestCommonBasePathFailsIfInvalidPath() + { + Path::getLongestCommonBasePath(array(array())); + } + + public function provideIsBasePathTests() + { + return [ + // same paths + ['/base/path', '/base/path', true], + ['C:/base/path', 'C:/base/path', true], + ['C:\\base\\path', 'C:\\base\\path', true], + ['C:/base/path', 'C:\\base\\path', true], + ['phar:///base/path', 'phar:///base/path', true], + ['phar://C:/base/path', 'phar://C:/base/path', true], + + // trailing slash + ['/base/path/', '/base/path', true], + ['C:/base/path/', 'C:/base/path', true], + ['C:\\base\\path\\', 'C:\\base\\path', true], + ['C:/base/path/', 'C:\\base\\path', true], + ['phar:///base/path/', 'phar:///base/path', true], + ['phar://C:/base/path/', 'phar://C:/base/path', true], + + ['/base/path', '/base/path/', true], + ['C:/base/path', 'C:/base/path/', true], + ['C:\\base\\path', 'C:\\base\\path\\', true], + ['C:/base/path', 'C:\\base\\path\\', true], + ['phar:///base/path', 'phar:///base/path/', true], + ['phar://C:/base/path', 'phar://C:/base/path/', true], + + // first in second + ['/base/path/sub', '/base/path', false], + ['C:/base/path/sub', 'C:/base/path', false], + ['C:\\base\\path\\sub', 'C:\\base\\path', false], + ['C:/base/path/sub', 'C:\\base\\path', false], + ['phar:///base/path/sub', 'phar:///base/path', false], + ['phar://C:/base/path/sub', 'phar://C:/base/path', false], + + // second in first + ['/base/path', '/base/path/sub', true], + ['C:/base/path', 'C:/base/path/sub', true], + ['C:\\base\\path', 'C:\\base\\path\\sub', true], + ['C:/base/path', 'C:\\base\\path\\sub', true], + ['phar:///base/path', 'phar:///base/path/sub', true], + ['phar://C:/base/path', 'phar://C:/base/path/sub', true], + + // first is prefix + ['/base/path/di', '/base/path/dir', false], + ['C:/base/path/di', 'C:/base/path/dir', false], + ['C:\\base\\path\\di', 'C:\\base\\path\\dir', false], + ['C:/base/path/di', 'C:\\base\\path\\dir', false], + ['phar:///base/path/di', 'phar:///base/path/dir', false], + ['phar://C:/base/path/di', 'phar://C:/base/path/dir', false], + + // second is prefix + ['/base/path/dir', '/base/path/di', false], + ['C:/base/path/dir', 'C:/base/path/di', false], + ['C:\\base\\path\\dir', 'C:\\base\\path\\di', false], + ['C:/base/path/dir', 'C:\\base\\path\\di', false], + ['phar:///base/path/dir', 'phar:///base/path/di', false], + ['phar://C:/base/path/dir', 'phar://C:/base/path/di', false], + + // root + ['/', '/second', true], + ['C:/', 'C:/second', true], + ['C:', 'C:/second', true], + ['C:\\', 'C:\\second', true], + ['C:/', 'C:\\second', true], + ['phar:///', 'phar:///second', true], + ['phar://C:/', 'phar://C:/second', true], + + // windows vs unix + ['/base/path', 'C:/base/path', false], + ['C:/base/path', '/base/path', false], + ['/base/path', 'C:\\base\\path', false], + ['/base/path', 'phar:///base/path', false], + ['phar:///base/path', 'phar://C:/base/path', false], + + // different partitions + ['C:/base/path', 'D:/base/path', false], + ['C:/base/path', 'D:\\base\\path', false], + ['C:\\base\\path', 'D:\\base\\path', false], + ['C:/base/path', 'phar://C:/base/path', false], + ['phar://C:/base/path', 'phar://D:/base/path', false], + ]; + } + + /** + * @dataProvider provideIsBasePathTests + */ + public function testIsBasePath($path, $ofPath, $result) + { + $this->assertSame($result, Path::isBasePath($path, $ofPath)); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The base path must be a string. Got: array + */ + public function testIsBasePathFailsIfInvalidBasePath() + { + Path::isBasePath(array(), '/base/path'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The path must be a string. Got: array + */ + public function testIsBasePathFailsIfInvalidPath() + { + Path::isBasePath('/base/path', array()); + } + + public function provideJoinTests() + { + return [ + ['', '', ''], + ['/path/to/test', '', '/path/to/test'], + ['/path/to//test', '', '/path/to/test'], + ['', '/path/to/test', '/path/to/test'], + ['', '/path/to//test', '/path/to/test'], + + ['/path/to/test', 'subdir', '/path/to/test/subdir'], + ['/path/to/test/', 'subdir', '/path/to/test/subdir'], + ['/path/to/test', '/subdir', '/path/to/test/subdir'], + ['/path/to/test/', '/subdir', '/path/to/test/subdir'], + ['/path/to/test', './subdir', '/path/to/test/subdir'], + ['/path/to/test/', './subdir', '/path/to/test/subdir'], + ['/path/to/test/', '../parentdir', '/path/to/parentdir'], + ['/path/to/test', '../parentdir', '/path/to/parentdir'], + ['path/to/test/', '/subdir', 'path/to/test/subdir'], + ['path/to/test', '/subdir', 'path/to/test/subdir'], + ['../path/to/test', '/subdir', '../path/to/test/subdir'], + ['path', '../../subdir', '../subdir'], + ['/path', '../../subdir', '/subdir'], + ['../path', '../../subdir', '../../subdir'], + + [['/path/to/test', 'subdir'], '', '/path/to/test/subdir'], + [['/path/to/test', '/subdir'], '', '/path/to/test/subdir'], + [['/path/to/test/', 'subdir'], '', '/path/to/test/subdir'], + [['/path/to/test/', '/subdir'], '', '/path/to/test/subdir'], + + [['/path'], '', '/path'], + [['/path', 'to', '/test'], '', '/path/to/test'], + [['/path', '', '/test'], '', '/path/test'], + [['path', 'to', 'test'], '', 'path/to/test'], + [[], '', ''], + + ['base/path', 'to/test', 'base/path/to/test'], + + ['C:\\path\\to\\test', 'subdir', 'C:/path/to/test/subdir'], + ['C:\\path\\to\\test\\', 'subdir', 'C:/path/to/test/subdir'], + ['C:\\path\\to\\test', '/subdir', 'C:/path/to/test/subdir'], + ['C:\\path\\to\\test\\', '/subdir', 'C:/path/to/test/subdir'], + + ['/', 'subdir', '/subdir'], + ['/', '/subdir', '/subdir'], + ['C:/', 'subdir', 'C:/subdir'], + ['C:/', '/subdir', 'C:/subdir'], + ['C:\\', 'subdir', 'C:/subdir'], + ['C:\\', '/subdir', 'C:/subdir'], + ['C:', 'subdir', 'C:/subdir'], + ['C:', '/subdir', 'C:/subdir'], + + ['phar://', '/path/to/test', 'phar:///path/to/test'], + ['phar:///', '/path/to/test', 'phar:///path/to/test'], + ['phar:///path/to/test', 'subdir', 'phar:///path/to/test/subdir'], + ['phar:///path/to/test', 'subdir/', 'phar:///path/to/test/subdir'], + ['phar:///path/to/test', '/subdir', 'phar:///path/to/test/subdir'], + ['phar:///path/to/test/', 'subdir', 'phar:///path/to/test/subdir'], + ['phar:///path/to/test/', '/subdir', 'phar:///path/to/test/subdir'], + + ['phar://', 'C:/path/to/test', 'phar://C:/path/to/test'], + ['phar://', 'C:\\path\\to\\test', 'phar://C:/path/to/test'], + ['phar://C:/path/to/test', 'subdir', 'phar://C:/path/to/test/subdir'], + ['phar://C:/path/to/test', 'subdir/', 'phar://C:/path/to/test/subdir'], + ['phar://C:/path/to/test', '/subdir', 'phar://C:/path/to/test/subdir'], + ['phar://C:/path/to/test/', 'subdir', 'phar://C:/path/to/test/subdir'], + ['phar://C:/path/to/test/', '/subdir', 'phar://C:/path/to/test/subdir'], + ['phar://C:', 'path/to/test', 'phar://C:/path/to/test'], + ['phar://C:', '/path/to/test', 'phar://C:/path/to/test'], + ['phar://C:/', 'path/to/test', 'phar://C:/path/to/test'], + ['phar://C:/', '/path/to/test', 'phar://C:/path/to/test'], + ]; + } + + /** + * @dataProvider provideJoinTests + */ + public function testJoin($path1, $path2, $result) + { + $this->assertSame($result, Path::join($path1, $path2)); + } + + public function testJoinVarArgs() + { + $this->assertSame('/path', Path::join('/path')); + $this->assertSame('/path/to', Path::join('/path', 'to')); + $this->assertSame('/path/to/test', Path::join('/path', 'to', '/test')); + $this->assertSame('/path/to/test/subdir', Path::join('/path', 'to', '/test', 'subdir/')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The paths must be strings. Got: array + */ + public function testJoinFailsIfInvalidPath() + { + Path::join('/path', []); + } + + /** + * @expectedException \RuntimeException + * @expectedExceptionMessage Your environment or operation system isn't supported + */ + public function testGetHomeDirectoryFailsIfNotSupportedOperationSystem() + { + putenv('HOME='); + + Path::getHomeDirectory(); + } + + public function testGetHomeDirectoryForUnix() + { + $this->assertEquals('/home/webmozart', Path::getHomeDirectory()); + } + + public function testGetHomeDirectoryForWindows() + { + putenv('HOME='); + putenv('HOMEDRIVE=C:'); + putenv('HOMEPATH=/users/webmozart'); + + $this->assertEquals('C:/users/webmozart', Path::getHomeDirectory()); + } + + public function testNormalize() + { + $this->assertSame('C:/Foo/Bar/test', Path::normalize('C:\\Foo\\Bar/test')); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testNormalizeFailsIfNoString() + { + Path::normalize(true); + } +} From 7a1066ad95baa07c75242dd52d53b4e52ed0152c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 7 Apr 2019 14:02:31 +0200 Subject: [PATCH 02/21] Cleanup - Apply fabbot CS fixes - Change the header - Remove the `@since` tags --- src/Symfony/Component/Filesystem/Path.php | 215 ++-- .../Component/Filesystem/Tests/PathTest.php | 1122 ++++++++--------- 2 files changed, 638 insertions(+), 699 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index a484bbf39ee8c..b9d63c46ff6ab 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -1,9 +1,9 @@ + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -12,16 +12,12 @@ namespace Symfony\Component\Filesystem; use function array_pop; -use function array_slice; use function basename; use function ctype_alpha; use function explode; -use function function_exists; use function getenv; use function implode; -use function in_array; use InvalidArgumentException; -use function is_object; use function ltrim; use function mb_strtolower; use function pathinfo; @@ -29,7 +25,6 @@ use RuntimeException; use function sprintf; use function str_replace; -use function strlen; use function strpos; use function substr; @@ -40,8 +35,6 @@ * with both forward and backward slashes. All methods return normalized parts * containing only forward slashes and no excess "." and ".." segments. * - * @since 1.0 - * * @author Bernhard Schussek * @author Thomas Schulz */ @@ -88,13 +81,9 @@ final class Path * * This method is able to deal with both UNIX and Windows paths. * - * @param string $path A path string. - * - * @return string The canonical path. + * @param string $path a path string * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. - * @since 2.1 Added support for `~`. + * @return string the canonical path */ public static function canonicalize(string $path): string { @@ -119,7 +108,7 @@ public static function canonicalize(string $path): string [$root, $pathWithoutRoot] = self::split($path); $parts = explode('/', $pathWithoutRoot); - $canonicalParts = array(); + $canonicalParts = []; // Collapse "." and "..", if possible foreach ($parts as $part) { @@ -129,8 +118,8 @@ public static function canonicalize(string $path): string // Collapse ".." with the previous part, if one exists // Don't collapse ".." if the previous part is also ".." - if ('..' === $part && count($canonicalParts) > 0 - && '..' !== $canonicalParts[count($canonicalParts) - 1] + if ('..' === $part && \count($canonicalParts) > 0 + && '..' !== $canonicalParts[\count($canonicalParts) - 1] ) { array_pop($canonicalParts); @@ -149,7 +138,7 @@ public static function canonicalize(string $path): string // Clean up regularly to prevent memory leaks if (self::$bufferSize > self::CLEANUP_THRESHOLD) { - self::$buffer = array_slice(self::$buffer, -self::CLEANUP_SIZE, null, true); + self::$buffer = \array_slice(self::$buffer, -self::CLEANUP_SIZE, null, true); self::$bufferSize = self::CLEANUP_SIZE; } @@ -167,11 +156,9 @@ public static function canonicalize(string $path): string * * This method is able to deal with both UNIX and Windows paths. * - * @param string $path A path string. - * - * @return string The normalized path. + * @param string $path a path string * - * @since 2.2 Added method. + * @return string the normalized path */ public static function normalize(string $path): string { @@ -196,15 +183,12 @@ public static function normalize(string $path): string * * The result is a canonical path. * - * @param string $path A path string. + * @param string $path a path string * * @return string The canonical directory part. Returns the root directory * if the root directory is passed. Returns an empty string * if a relative path is passed that contains no slashes. * Returns an empty string if an empty string is passed. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. */ public static function getDirectory(string $path): string { @@ -254,8 +238,6 @@ public static function getDirectory(string $path): string * @return string The canonical home directory * * @throws RuntimeException If your operation system or environment isn't supported - * - * @since 2.1 Added method. */ public static function getHomeDirectory(): string { @@ -277,13 +259,10 @@ public static function getHomeDirectory(): string * * The result is a canonical path. * - * @param string $path A path string. + * @param string $path a path string * * @return string The canonical root directory. Returns an empty string if * the given path is relative or empty. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. */ public static function getRoot(string $path): string { @@ -304,7 +283,7 @@ public static function getRoot(string $path): string return $scheme.'/'; } - $length = strlen($path); + $length = \strlen($path); // Windows root if ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { @@ -325,12 +304,9 @@ public static function getRoot(string $path): string /** * Returns the file name from a file path. * - * @param string $path The path string. - * - * @return string The file name. + * @param string $path the path string * - * @since 1.1 Added method. - * @since 2.0 Method now fails if $path is not a string. + * @return string the file name */ public static function getFilename(string $path): string { @@ -344,14 +320,11 @@ public static function getFilename(string $path): string /** * Returns the file name without the extension from a file path. * - * @param string $path The path string. - * @param string|null $extension If specified, only that extension is cut - * off (may contain leading dot). + * @param string $path the path string + * @param string|null $extension if specified, only that extension is cut + * off (may contain leading dot) * - * @return string The file name without extension. - * - * @since 1.1 Added method. - * @since 2.0 Method now fails if $path or $extension have invalid types. + * @return string the file name without extension */ public static function getFilenameWithoutExtension(string $path, ?string $extension = null) { @@ -370,15 +343,12 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens /** * Returns the extension from a file path. * - * @param string $path The path string. - * @param bool $forceLowerCase Forces the extension to be lower-case + * @param string $path the path string + * @param bool $forceLowerCase forces the extension to be lower-case * (requires mbstring extension for correct - * multi-byte character handling in extension). - * - * @return string The extension of the file path (without leading dot). + * multi-byte character handling in extension) * - * @since 1.1 Added method. - * @since 2.0 Method now fails if $path is not a string. + * @return string the extension of the file path (without leading dot) */ public static function getExtension(string $path, bool $forceLowerCase = false): string { @@ -398,22 +368,19 @@ public static function getExtension(string $path, bool $forceLowerCase = false): /** * Returns whether the path has an extension. * - * @param string $path The path string. - * @param string|string[]|null $extensions If null or not provided, checks if - * an extension exists, otherwise - * checks for the specified extension - * or array of extensions (with or - * without leading dot). - * @param bool $ignoreCase Whether to ignore case-sensitivity - * (requires mbstring extension for - * correct multi-byte character - * handling in the extension). - * - * @return bool Returns `true` if the path has an (or the specified) - * extension and `false` otherwise. - * - * @since 1.1 Added method. - * @since 2.0 Method now fails if $path or $extensions have invalid types. + * @param string $path the path string + * @param string|string[]|null $extensions if null or not provided, checks if + * an extension exists, otherwise + * checks for the specified extension + * or array of extensions (with or + * without leading dot) + * @param bool $ignoreCase whether to ignore case-sensitivity + * (requires mbstring extension for + * correct multi-byte character + * handling in the extension) + * + * @return bool returns `true` if the path has an (or the specified) + * extension and `false` otherwise */ public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool { @@ -437,19 +404,16 @@ public static function hasExtension(string $path, $extensions = null, bool $igno $extensions[$key] = ltrim($extension, '.'); } - return in_array($actualExtension, $extensions, true); + return \in_array($actualExtension, $extensions, true); } /** * Changes the extension of a path string. * * @param string $path The path string with filename.ext to change. - * @param string $extension New extension (with or without leading dot). + * @param string $extension new extension (with or without leading dot) * - * @return string The path string with new file extension. - * - * @since 1.1 Added method. - * @since 2.0 Method now fails if $path or $extension is not a string. + * @return string the path string with new file extension */ public static function changeExtension(string $path, string $extension): string { @@ -470,19 +434,16 @@ public static function changeExtension(string $path, string $extension): string return $path.('.' === substr($path, -1) ? '' : '.').$extension; } - return substr($path, 0, -strlen($actualExtension)).$extension; + return substr($path, 0, -\strlen($actualExtension)).$extension; } /** * Returns whether a path is absolute. * - * @param string $path A path string. - * - * @return bool Returns true if the path is absolute, false if it is - * relative or empty. + * @param string $path a path string * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. + * @return bool returns true if the path is absolute, false if it is + * relative or empty */ public static function isAbsolute(string $path): bool { @@ -501,9 +462,9 @@ public static function isAbsolute(string $path): bool } // Windows root - if (strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + if (\strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" - if (2 === strlen($path)) { + if (2 === \strlen($path)) { return true; } @@ -519,13 +480,10 @@ public static function isAbsolute(string $path): bool /** * Returns whether a path is relative. * - * @param string $path A path string. - * - * @return bool Returns true if the path is relative or empty, false if - * it is absolute. + * @param string $path a path string * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. + * @return bool returns true if the path is relative or empty, false if + * it is absolute */ public static function isRelative(string $path): bool { @@ -563,19 +521,14 @@ public static function isRelative(string $path): bool * * The result is a canonical path. * - * @param string $path A path to make absolute. - * @param string $basePath An absolute base path. + * @param string $path a path to make absolute + * @param string $basePath an absolute base path * - * @return string An absolute path in canonical form. + * @return string an absolute path in canonical form * - * @throws InvalidArgumentException If the base path is not absolute or if + * @throws InvalidArgumentException if the base path is not absolute or if * the given path is an absolute path with - * a different root than the base path. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path or $basePath is not a string. - * @since 2.2.2 Method does not fail anymore of $path and $basePath are - * absolute, but on different partitions. + * a different root than the base path */ public static function makeAbsolute(string $path, string $basePath): string { @@ -646,17 +599,14 @@ public static function makeAbsolute(string $path, string $basePath): string * * The result is a canonical path. * - * @param string $path A path to make relative. - * @param string $basePath A base path. + * @param string $path a path to make relative + * @param string $basePath a base path * - * @return string A relative path in canonical form. + * @return string a relative path in canonical form * - * @throws InvalidArgumentException If the base path is not absolute or if + * @throws InvalidArgumentException if the base path is not absolute or if * the given path has a different root - * than the base path. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path or $basePath is not a string. + * than the base path */ public static function makeRelative(string $path, string $basePath): string { @@ -732,12 +682,9 @@ public static function makeRelative(string $path, string $basePath): string /** * Returns whether the given path is on the local filesystem. * - * @param string $path A path string. + * @param string $path a path string * - * @return bool Returns true if the path is local, false for a URL. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $path is not a string. + * @return bool returns true if the path is local, false for a URL */ public static function isLocal(string $path): bool { @@ -779,14 +726,11 @@ public static function isLocal(string $path): bool * // => null * ``` * - * @param string[] $paths A list of paths. + * @param string[] $paths a list of paths * - * @return string|null The longest common base path in canonical form or + * @return string|null the longest common base path in canonical form or * `null` if the paths are on different Windows - * partitions. - * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $paths are not strings. + * partitions */ public static function getLongestCommonBasePath(array $paths): ?string { @@ -818,7 +762,7 @@ public static function getLongestCommonBasePath(array $paths): ?string continue 2; } - $basePath = dirname($basePath); + $basePath = \dirname($basePath); } } @@ -830,11 +774,9 @@ public static function getLongestCommonBasePath(array $paths): ?string * * The result is a canonical path. * - * @param string[]|string $paths Path parts as parameters or array. + * @param string[]|string $paths path parts as parameters or array * - * @return string The joint path. - * - * @since 2.0 Added method. + * @return string the joint path */ public static function join(string ...$paths): string { @@ -851,12 +793,12 @@ public static function join(string ...$paths): string if (null === $finalPath) { // For first part we keep slashes, like '/top', 'C:\' or 'phar://' $finalPath = $path; - $wasScheme = (strpos($path, '://') !== false); + $wasScheme = (false !== strpos($path, '://')); continue; } // Only add slash if previous part didn't end with '/' or '\' - if (!in_array(substr($finalPath, -1), array('/', '\\'))) { + if (!\in_array(substr($finalPath, -1), ['/', '\\'])) { $finalPath .= '/'; } @@ -892,13 +834,10 @@ public static function join(string ...$paths): string * // => false * ``` * - * @param string $basePath The base path to test. - * @param string $ofPath The other path. - * - * @return bool Whether the base path is a base path of the other path. + * @param string $basePath the base path to test + * @param string $ofPath the other path * - * @since 1.0 Added method. - * @since 2.0 Method now fails if $basePath or $ofPath is not a string. + * @return bool whether the base path is a base path of the other path */ public static function isBasePath(string $basePath, string $ofPath): bool { @@ -928,10 +867,10 @@ public static function isBasePath(string $basePath, string $ofPath): bool * list ($root, $path) = Path::split("C:") * // => array("C:/", "") * - * @param string $path The canonical path to split. + * @param string $path the canonical path to split * - * @return string[] An array with the root directory and the remaining - * relative path. + * @return string[] an array with the root directory and the remaining + * relative path */ private static function split(string $path): array { @@ -947,10 +886,10 @@ private static function split(string $path): array $root = ''; } - $length = strlen($path); + $length = \strlen($path); // Remove and remember root directory - if (strpos($path, '/') === 0) { + if (0 === strpos($path, '/')) { $root .= '/'; $path = $length > 1 ? substr($path, 1) : ''; } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { @@ -977,7 +916,7 @@ private static function split(string $path): array */ private static function toLower(string $str): string { - if (function_exists('mb_strtolower')) { + if (\function_exists('mb_strtolower')) { return mb_strtolower($str, mb_detect_encoding($str)); } diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 6b3b6921bb58a..c008fbb18dd26 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -1,9 +1,9 @@ + * (c) Fabien Potencier * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. @@ -22,7 +22,7 @@ */ class PathTest extends TestCase { - protected $storedEnv = array(); + protected $storedEnv = []; public function setUp() { @@ -37,134 +37,134 @@ public function setUp() public function tearDown() { - putenv('HOME=' . $this->storedEnv['HOME']); - putenv('HOMEDRIVE=' . $this->storedEnv['HOMEDRIVE']); - putenv('HOMEPATH=' . $this->storedEnv['HOMEPATH']); + putenv('HOME='.$this->storedEnv['HOME']); + putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']); + putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']); } public function provideCanonicalizationTests() { - return array( + return [ // relative paths (forward slash) - array('css/./style.css', 'css/style.css'), - array('css/../style.css', 'style.css'), - array('css/./../style.css', 'style.css'), - array('css/.././style.css', 'style.css'), - array('css/../../style.css', '../style.css'), - array('./css/style.css', 'css/style.css'), - array('../css/style.css', '../css/style.css'), - array('./../css/style.css', '../css/style.css'), - array('.././css/style.css', '../css/style.css'), - array('../../css/style.css', '../../css/style.css'), - array('', ''), - array('.', ''), - array('..', '..'), - array('./..', '..'), - array('../.', '..'), - array('../..', '../..'), + ['css/./style.css', 'css/style.css'], + ['css/../style.css', 'style.css'], + ['css/./../style.css', 'style.css'], + ['css/.././style.css', 'style.css'], + ['css/../../style.css', '../style.css'], + ['./css/style.css', 'css/style.css'], + ['../css/style.css', '../css/style.css'], + ['./../css/style.css', '../css/style.css'], + ['.././css/style.css', '../css/style.css'], + ['../../css/style.css', '../../css/style.css'], + ['', ''], + ['.', ''], + ['..', '..'], + ['./..', '..'], + ['../.', '..'], + ['../..', '../..'], // relative paths (backslash) - array('css\\.\\style.css', 'css/style.css'), - array('css\\..\\style.css', 'style.css'), - array('css\\.\\..\\style.css', 'style.css'), - array('css\\..\\.\\style.css', 'style.css'), - array('css\\..\\..\\style.css', '../style.css'), - array('.\\css\\style.css', 'css/style.css'), - array('..\\css\\style.css', '../css/style.css'), - array('.\\..\\css\\style.css', '../css/style.css'), - array('..\\.\\css\\style.css', '../css/style.css'), - array('..\\..\\css\\style.css', '../../css/style.css'), + ['css\\.\\style.css', 'css/style.css'], + ['css\\..\\style.css', 'style.css'], + ['css\\.\\..\\style.css', 'style.css'], + ['css\\..\\.\\style.css', 'style.css'], + ['css\\..\\..\\style.css', '../style.css'], + ['.\\css\\style.css', 'css/style.css'], + ['..\\css\\style.css', '../css/style.css'], + ['.\\..\\css\\style.css', '../css/style.css'], + ['..\\.\\css\\style.css', '../css/style.css'], + ['..\\..\\css\\style.css', '../../css/style.css'], // absolute paths (forward slash, UNIX) - array('/css/style.css', '/css/style.css'), - array('/css/./style.css', '/css/style.css'), - array('/css/../style.css', '/style.css'), - array('/css/./../style.css', '/style.css'), - array('/css/.././style.css', '/style.css'), - array('/./css/style.css', '/css/style.css'), - array('/../css/style.css', '/css/style.css'), - array('/./../css/style.css', '/css/style.css'), - array('/.././css/style.css', '/css/style.css'), - array('/../../css/style.css', '/css/style.css'), + ['/css/style.css', '/css/style.css'], + ['/css/./style.css', '/css/style.css'], + ['/css/../style.css', '/style.css'], + ['/css/./../style.css', '/style.css'], + ['/css/.././style.css', '/style.css'], + ['/./css/style.css', '/css/style.css'], + ['/../css/style.css', '/css/style.css'], + ['/./../css/style.css', '/css/style.css'], + ['/.././css/style.css', '/css/style.css'], + ['/../../css/style.css', '/css/style.css'], // absolute paths (backslash, UNIX) - array('\\css\\style.css', '/css/style.css'), - array('\\css\\.\\style.css', '/css/style.css'), - array('\\css\\..\\style.css', '/style.css'), - array('\\css\\.\\..\\style.css', '/style.css'), - array('\\css\\..\\.\\style.css', '/style.css'), - array('\\.\\css\\style.css', '/css/style.css'), - array('\\..\\css\\style.css', '/css/style.css'), - array('\\.\\..\\css\\style.css', '/css/style.css'), - array('\\..\\.\\css\\style.css', '/css/style.css'), - array('\\..\\..\\css\\style.css', '/css/style.css'), + ['\\css\\style.css', '/css/style.css'], + ['\\css\\.\\style.css', '/css/style.css'], + ['\\css\\..\\style.css', '/style.css'], + ['\\css\\.\\..\\style.css', '/style.css'], + ['\\css\\..\\.\\style.css', '/style.css'], + ['\\.\\css\\style.css', '/css/style.css'], + ['\\..\\css\\style.css', '/css/style.css'], + ['\\.\\..\\css\\style.css', '/css/style.css'], + ['\\..\\.\\css\\style.css', '/css/style.css'], + ['\\..\\..\\css\\style.css', '/css/style.css'], // absolute paths (forward slash, Windows) - array('C:/css/style.css', 'C:/css/style.css'), - array('C:/css/./style.css', 'C:/css/style.css'), - array('C:/css/../style.css', 'C:/style.css'), - array('C:/css/./../style.css', 'C:/style.css'), - array('C:/css/.././style.css', 'C:/style.css'), - array('C:/./css/style.css', 'C:/css/style.css'), - array('C:/../css/style.css', 'C:/css/style.css'), - array('C:/./../css/style.css', 'C:/css/style.css'), - array('C:/.././css/style.css', 'C:/css/style.css'), - array('C:/../../css/style.css', 'C:/css/style.css'), + ['C:/css/style.css', 'C:/css/style.css'], + ['C:/css/./style.css', 'C:/css/style.css'], + ['C:/css/../style.css', 'C:/style.css'], + ['C:/css/./../style.css', 'C:/style.css'], + ['C:/css/.././style.css', 'C:/style.css'], + ['C:/./css/style.css', 'C:/css/style.css'], + ['C:/../css/style.css', 'C:/css/style.css'], + ['C:/./../css/style.css', 'C:/css/style.css'], + ['C:/.././css/style.css', 'C:/css/style.css'], + ['C:/../../css/style.css', 'C:/css/style.css'], // absolute paths (backslash, Windows) - array('C:\\css\\style.css', 'C:/css/style.css'), - array('C:\\css\\.\\style.css', 'C:/css/style.css'), - array('C:\\css\\..\\style.css', 'C:/style.css'), - array('C:\\css\\.\\..\\style.css', 'C:/style.css'), - array('C:\\css\\..\\.\\style.css', 'C:/style.css'), - array('C:\\.\\css\\style.css', 'C:/css/style.css'), - array('C:\\..\\css\\style.css', 'C:/css/style.css'), - array('C:\\.\\..\\css\\style.css', 'C:/css/style.css'), - array('C:\\..\\.\\css\\style.css', 'C:/css/style.css'), - array('C:\\..\\..\\css\\style.css', 'C:/css/style.css'), + ['C:\\css\\style.css', 'C:/css/style.css'], + ['C:\\css\\.\\style.css', 'C:/css/style.css'], + ['C:\\css\\..\\style.css', 'C:/style.css'], + ['C:\\css\\.\\..\\style.css', 'C:/style.css'], + ['C:\\css\\..\\.\\style.css', 'C:/style.css'], + ['C:\\.\\css\\style.css', 'C:/css/style.css'], + ['C:\\..\\css\\style.css', 'C:/css/style.css'], + ['C:\\.\\..\\css\\style.css', 'C:/css/style.css'], + ['C:\\..\\.\\css\\style.css', 'C:/css/style.css'], + ['C:\\..\\..\\css\\style.css', 'C:/css/style.css'], // Windows special case - array('C:', 'C:/'), + ['C:', 'C:/'], // Don't change malformed path - array('C:css/style.css', 'C:css/style.css'), + ['C:css/style.css', 'C:css/style.css'], // absolute paths (stream, UNIX) - array('phar:///css/style.css', 'phar:///css/style.css'), - array('phar:///css/./style.css', 'phar:///css/style.css'), - array('phar:///css/../style.css', 'phar:///style.css'), - array('phar:///css/./../style.css', 'phar:///style.css'), - array('phar:///css/.././style.css', 'phar:///style.css'), - array('phar:///./css/style.css', 'phar:///css/style.css'), - array('phar:///../css/style.css', 'phar:///css/style.css'), - array('phar:///./../css/style.css', 'phar:///css/style.css'), - array('phar:///.././css/style.css', 'phar:///css/style.css'), - array('phar:///../../css/style.css', 'phar:///css/style.css'), + ['phar:///css/style.css', 'phar:///css/style.css'], + ['phar:///css/./style.css', 'phar:///css/style.css'], + ['phar:///css/../style.css', 'phar:///style.css'], + ['phar:///css/./../style.css', 'phar:///style.css'], + ['phar:///css/.././style.css', 'phar:///style.css'], + ['phar:///./css/style.css', 'phar:///css/style.css'], + ['phar:///../css/style.css', 'phar:///css/style.css'], + ['phar:///./../css/style.css', 'phar:///css/style.css'], + ['phar:///.././css/style.css', 'phar:///css/style.css'], + ['phar:///../../css/style.css', 'phar:///css/style.css'], // absolute paths (stream, Windows) - array('phar://C:/css/style.css', 'phar://C:/css/style.css'), - array('phar://C:/css/./style.css', 'phar://C:/css/style.css'), - array('phar://C:/css/../style.css', 'phar://C:/style.css'), - array('phar://C:/css/./../style.css', 'phar://C:/style.css'), - array('phar://C:/css/.././style.css', 'phar://C:/style.css'), - array('phar://C:/./css/style.css', 'phar://C:/css/style.css'), - array('phar://C:/../css/style.css', 'phar://C:/css/style.css'), - array('phar://C:/./../css/style.css', 'phar://C:/css/style.css'), - array('phar://C:/.././css/style.css', 'phar://C:/css/style.css'), - array('phar://C:/../../css/style.css', 'phar://C:/css/style.css'), + ['phar://C:/css/style.css', 'phar://C:/css/style.css'], + ['phar://C:/css/./style.css', 'phar://C:/css/style.css'], + ['phar://C:/css/../style.css', 'phar://C:/style.css'], + ['phar://C:/css/./../style.css', 'phar://C:/style.css'], + ['phar://C:/css/.././style.css', 'phar://C:/style.css'], + ['phar://C:/./css/style.css', 'phar://C:/css/style.css'], + ['phar://C:/../css/style.css', 'phar://C:/css/style.css'], + ['phar://C:/./../css/style.css', 'phar://C:/css/style.css'], + ['phar://C:/.././css/style.css', 'phar://C:/css/style.css'], + ['phar://C:/../../css/style.css', 'phar://C:/css/style.css'], // paths with "~" UNIX - array('~/css/style.css', '/home/webmozart/css/style.css'), - array('~/css/./style.css', '/home/webmozart/css/style.css'), - array('~/css/../style.css', '/home/webmozart/style.css'), - array('~/css/./../style.css', '/home/webmozart/style.css'), - array('~/css/.././style.css', '/home/webmozart/style.css'), - array('~/./css/style.css', '/home/webmozart/css/style.css'), - array('~/../css/style.css', '/home/css/style.css'), - array('~/./../css/style.css', '/home/css/style.css'), - array('~/.././css/style.css', '/home/css/style.css'), - array('~/../../css/style.css', '/css/style.css'), - ); + ['~/css/style.css', '/home/webmozart/css/style.css'], + ['~/css/./style.css', '/home/webmozart/css/style.css'], + ['~/css/../style.css', '/home/webmozart/style.css'], + ['~/css/./../style.css', '/home/webmozart/style.css'], + ['~/css/.././style.css', '/home/webmozart/style.css'], + ['~/./css/style.css', '/home/webmozart/css/style.css'], + ['~/../css/style.css', '/home/css/style.css'], + ['~/./../css/style.css', '/home/css/style.css'], + ['~/.././css/style.css', '/home/css/style.css'], + ['~/../../css/style.css', '/css/style.css'], + ]; } /** @@ -181,62 +181,62 @@ public function testCanonicalize($path, $canonicalized) */ public function testCanonicalizeFailsIfInvalidPath() { - Path::canonicalize(array()); + Path::canonicalize([]); } public function provideGetDirectoryTests() { - return array( - array('/webmozart/puli/style.css', '/webmozart/puli'), - array('/webmozart/puli', '/webmozart'), - array('/webmozart', '/'), - array('/', '/'), - array('', ''), - - array('\\webmozart\\puli\\style.css', '/webmozart/puli'), - array('\\webmozart\\puli', '/webmozart'), - array('\\webmozart', '/'), - array('\\', '/'), - - array('C:/webmozart/puli/style.css', 'C:/webmozart/puli'), - array('C:/webmozart/puli', 'C:/webmozart'), - array('C:/webmozart', 'C:/'), - array('C:/', 'C:/'), - array('C:', 'C:/'), - - array('C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli'), - array('C:\\webmozart\\puli', 'C:/webmozart'), - array('C:\\webmozart', 'C:/'), - array('C:\\', 'C:/'), - - array('phar:///webmozart/puli/style.css', 'phar:///webmozart/puli'), - array('phar:///webmozart/puli', 'phar:///webmozart'), - array('phar:///webmozart', 'phar:///'), - array('phar:///', 'phar:///'), - - array('phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli'), - array('phar://C:/webmozart/puli', 'phar://C:/webmozart'), - array('phar://C:/webmozart', 'phar://C:/'), - array('phar://C:/', 'phar://C:/'), - - array('webmozart/puli/style.css', 'webmozart/puli'), - array('webmozart/puli', 'webmozart'), - array('webmozart', ''), - - array('webmozart\\puli\\style.css', 'webmozart/puli'), - array('webmozart\\puli', 'webmozart'), - array('webmozart', ''), - - array('/webmozart/./puli/style.css', '/webmozart/puli'), - array('/webmozart/../puli/style.css', '/puli'), - array('/webmozart/./../puli/style.css', '/puli'), - array('/webmozart/.././puli/style.css', '/puli'), - array('/webmozart/../../puli/style.css', '/puli'), - array('/.', '/'), - array('/..', '/'), - - array('C:webmozart', ''), - ); + return [ + ['/webmozart/puli/style.css', '/webmozart/puli'], + ['/webmozart/puli', '/webmozart'], + ['/webmozart', '/'], + ['/', '/'], + ['', ''], + + ['\\webmozart\\puli\\style.css', '/webmozart/puli'], + ['\\webmozart\\puli', '/webmozart'], + ['\\webmozart', '/'], + ['\\', '/'], + + ['C:/webmozart/puli/style.css', 'C:/webmozart/puli'], + ['C:/webmozart/puli', 'C:/webmozart'], + ['C:/webmozart', 'C:/'], + ['C:/', 'C:/'], + ['C:', 'C:/'], + + ['C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli'], + ['C:\\webmozart\\puli', 'C:/webmozart'], + ['C:\\webmozart', 'C:/'], + ['C:\\', 'C:/'], + + ['phar:///webmozart/puli/style.css', 'phar:///webmozart/puli'], + ['phar:///webmozart/puli', 'phar:///webmozart'], + ['phar:///webmozart', 'phar:///'], + ['phar:///', 'phar:///'], + + ['phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli'], + ['phar://C:/webmozart/puli', 'phar://C:/webmozart'], + ['phar://C:/webmozart', 'phar://C:/'], + ['phar://C:/', 'phar://C:/'], + + ['webmozart/puli/style.css', 'webmozart/puli'], + ['webmozart/puli', 'webmozart'], + ['webmozart', ''], + + ['webmozart\\puli\\style.css', 'webmozart/puli'], + ['webmozart\\puli', 'webmozart'], + ['webmozart', ''], + + ['/webmozart/./puli/style.css', '/webmozart/puli'], + ['/webmozart/../puli/style.css', '/puli'], + ['/webmozart/./../puli/style.css', '/puli'], + ['/webmozart/.././puli/style.css', '/puli'], + ['/webmozart/../../puli/style.css', '/puli'], + ['/.', '/'], + ['/..', '/'], + + ['C:webmozart', ''], + ]; } /** @@ -253,20 +253,20 @@ public function testGetDirectory($path, $directory) */ public function testGetDirectoryFailsIfInvalidPath() { - Path::getDirectory(array()); + Path::getDirectory([]); } public function provideGetFilenameTests() { - return array( - array('/webmozart/puli/style.css', 'style.css'), - array('/webmozart/puli/STYLE.CSS', 'STYLE.CSS'), - array('/webmozart/puli/style.css/', 'style.css'), - array('/webmozart/puli/', 'puli'), - array('/webmozart/puli', 'puli'), - array('/', ''), - array('', ''), - ); + return [ + ['/webmozart/puli/style.css', 'style.css'], + ['/webmozart/puli/STYLE.CSS', 'STYLE.CSS'], + ['/webmozart/puli/style.css/', 'style.css'], + ['/webmozart/puli/', 'puli'], + ['/webmozart/puli', 'puli'], + ['/', ''], + ['', ''], + ]; } /** @@ -283,32 +283,32 @@ public function testGetFilename($path, $filename) */ public function testGetFilenameFailsIfInvalidPath() { - Path::getFilename(array()); + Path::getFilename([]); } public function provideGetFilenameWithoutExtensionTests() { - return array( - array('/webmozart/puli/style.css.twig', null, 'style.css'), - array('/webmozart/puli/style.css.', null, 'style.css'), - array('/webmozart/puli/style.css', null, 'style'), - array('/webmozart/puli/.style.css', null, '.style'), - array('/webmozart/puli/', null, 'puli'), - array('/webmozart/puli', null, 'puli'), - array('/', null, ''), - array('', null, ''), - - array('/webmozart/puli/style.css', 'css', 'style'), - array('/webmozart/puli/style.css', '.css', 'style'), - array('/webmozart/puli/style.css', 'twig', 'style.css'), - array('/webmozart/puli/style.css', '.twig', 'style.css'), - array('/webmozart/puli/style.css', '', 'style.css'), - array('/webmozart/puli/style.css.', '', 'style.css'), - array('/webmozart/puli/style.css.', '.', 'style.css'), - array('/webmozart/puli/style.css.', '.css', 'style.css'), - array('/webmozart/puli/.style.css', 'css', '.style'), - array('/webmozart/puli/.style.css', '.css', '.style'), - ); + return [ + ['/webmozart/puli/style.css.twig', null, 'style.css'], + ['/webmozart/puli/style.css.', null, 'style.css'], + ['/webmozart/puli/style.css', null, 'style'], + ['/webmozart/puli/.style.css', null, '.style'], + ['/webmozart/puli/', null, 'puli'], + ['/webmozart/puli', null, 'puli'], + ['/', null, ''], + ['', null, ''], + + ['/webmozart/puli/style.css', 'css', 'style'], + ['/webmozart/puli/style.css', '.css', 'style'], + ['/webmozart/puli/style.css', 'twig', 'style.css'], + ['/webmozart/puli/style.css', '.twig', 'style.css'], + ['/webmozart/puli/style.css', '', 'style.css'], + ['/webmozart/puli/style.css.', '', 'style.css'], + ['/webmozart/puli/style.css.', '.', 'style.css'], + ['/webmozart/puli/style.css.', '.css', 'style.css'], + ['/webmozart/puli/.style.css', 'css', '.style'], + ['/webmozart/puli/.style.css', '.css', '.style'], + ]; } /** @@ -325,7 +325,7 @@ public function testGetFilenameWithoutExtension($path, $extension, $filename) */ public function testGetFilenameWithoutExtensionFailsIfInvalidPath() { - Path::getFilenameWithoutExtension(array(), '.css'); + Path::getFilenameWithoutExtension([], '.css'); } /** @@ -334,28 +334,28 @@ public function testGetFilenameWithoutExtensionFailsIfInvalidPath() */ public function testGetFilenameWithoutExtensionFailsIfInvalidExtension() { - Path::getFilenameWithoutExtension('/style.css', array()); + Path::getFilenameWithoutExtension('/style.css', []); } public function provideGetExtensionTests() { - $tests = array( - array('/webmozart/puli/style.css.twig', false, 'twig'), - array('/webmozart/puli/style.css', false, 'css'), - array('/webmozart/puli/style.css.', false, ''), - array('/webmozart/puli/', false, ''), - array('/webmozart/puli', false, ''), - array('/', false, ''), - array('', false, ''), - - array('/webmozart/puli/style.CSS', false, 'CSS'), - array('/webmozart/puli/style.CSS', true, 'css'), - array('/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ'), - ); - - if (extension_loaded('mbstring')) { + $tests = [ + ['/webmozart/puli/style.css.twig', false, 'twig'], + ['/webmozart/puli/style.css', false, 'css'], + ['/webmozart/puli/style.css.', false, ''], + ['/webmozart/puli/', false, ''], + ['/webmozart/puli', false, ''], + ['/', false, ''], + ['', false, ''], + + ['/webmozart/puli/style.CSS', false, 'CSS'], + ['/webmozart/puli/style.CSS', true, 'css'], + ['/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ'], + ]; + + if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - $tests[] = array('/webmozart/puli/style.ÄÖÜ', true, 'äöü'); + $tests[] = ['/webmozart/puli/style.ÄÖÜ', true, 'äöü']; } return $tests; @@ -375,47 +375,47 @@ public function testGetExtension($path, $forceLowerCase, $extension) */ public function testGetExtensionFailsIfInvalidPath() { - Path::getExtension(array()); + Path::getExtension([]); } public function provideHasExtensionTests() { - $tests = array( - array(true, '/webmozart/puli/style.css.twig', null, false), - array(true, '/webmozart/puli/style.css', null, false), - array(false, '/webmozart/puli/style.css.', null, false), - array(false, '/webmozart/puli/', null, false), - array(false, '/webmozart/puli', null, false), - array(false, '/', null, false), - array(false, '', null, false), - - array(true, '/webmozart/puli/style.css.twig', 'twig', false), - array(false, '/webmozart/puli/style.css.twig', 'css', false), - array(true, '/webmozart/puli/style.css', 'css', false), - array(true, '/webmozart/puli/style.css', '.css', false), - array(true, '/webmozart/puli/style.css.', '', false), - array(false, '/webmozart/puli/', 'ext', false), - array(false, '/webmozart/puli', 'ext', false), - array(false, '/', 'ext', false), - array(false, '', 'ext', false), - - array(false, '/webmozart/puli/style.css', 'CSS', false), - array(true, '/webmozart/puli/style.css', 'CSS', true), - array(false, '/webmozart/puli/style.CSS', 'css', false), - array(true, '/webmozart/puli/style.CSS', 'css', true), - array(true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false), - - array(true, '/webmozart/puli/style.css', array('ext', 'css'), false), - array(true, '/webmozart/puli/style.css', array('.ext', '.css'), false), - array(true, '/webmozart/puli/style.css.', array('ext', ''), false), - array(false, '/webmozart/puli/style.css', array('foo', 'bar', ''), false), - array(false, '/webmozart/puli/style.css', array('.foo', '.bar', ''), false), - ); - - if (extension_loaded('mbstring')) { + $tests = [ + [true, '/webmozart/puli/style.css.twig', null, false], + [true, '/webmozart/puli/style.css', null, false], + [false, '/webmozart/puli/style.css.', null, false], + [false, '/webmozart/puli/', null, false], + [false, '/webmozart/puli', null, false], + [false, '/', null, false], + [false, '', null, false], + + [true, '/webmozart/puli/style.css.twig', 'twig', false], + [false, '/webmozart/puli/style.css.twig', 'css', false], + [true, '/webmozart/puli/style.css', 'css', false], + [true, '/webmozart/puli/style.css', '.css', false], + [true, '/webmozart/puli/style.css.', '', false], + [false, '/webmozart/puli/', 'ext', false], + [false, '/webmozart/puli', 'ext', false], + [false, '/', 'ext', false], + [false, '', 'ext', false], + + [false, '/webmozart/puli/style.css', 'CSS', false], + [true, '/webmozart/puli/style.css', 'CSS', true], + [false, '/webmozart/puli/style.CSS', 'css', false], + [true, '/webmozart/puli/style.CSS', 'css', true], + [true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false], + + [true, '/webmozart/puli/style.css', ['ext', 'css'], false], + [true, '/webmozart/puli/style.css', ['.ext', '.css'], false], + [true, '/webmozart/puli/style.css.', ['ext', ''], false], + [false, '/webmozart/puli/style.css', ['foo', 'bar', ''], false], + [false, '/webmozart/puli/style.css', ['.foo', '.bar', ''], false], + ]; + + if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true); - $tests[] = array(true, '/webmozart/puli/style.ÄÖÜ', array('äöü'), true); + $tests[] = [true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true]; + $tests[] = [true, '/webmozart/puli/style.ÄÖÜ', ['äöü'], true]; } return $tests; @@ -435,7 +435,7 @@ public function testHasExtension($hasExtension, $path, $extension, $ignoreCase) */ public function testHasExtensionFailsIfInvalidPath() { - Path::hasExtension(array()); + Path::hasExtension([]); } /** @@ -444,25 +444,25 @@ public function testHasExtensionFailsIfInvalidPath() */ public function testHasExtensionFailsIfInvalidExtension() { - Path::hasExtension('/style.css', (object)array()); + Path::hasExtension('/style.css', (object) []); } public function provideChangeExtensionTests() { - return array( - array('/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html'), - array('/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass'), - array('/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass'), - array('/webmozart/puli/style.css', '', '/webmozart/puli/style.'), - array('/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig'), - array('/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.'), - array('/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü'), - array('/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css'), - array('/webmozart/puli/', 'css', '/webmozart/puli/'), - array('/webmozart/puli', 'css', '/webmozart/puli.css'), - array('/', 'css', '/'), - array('', 'css', ''), - ); + return [ + ['/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html'], + ['/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass'], + ['/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass'], + ['/webmozart/puli/style.css', '', '/webmozart/puli/style.'], + ['/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig'], + ['/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.'], + ['/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü'], + ['/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css'], + ['/webmozart/puli/', 'css', '/webmozart/puli/'], + ['/webmozart/puli', 'css', '/webmozart/puli.css'], + ['/', 'css', '/'], + ['', 'css', ''], + ]; } /** @@ -481,7 +481,7 @@ public function testChangeExtension($path, $extension, $pathExpected) */ public function testChangeExtensionFailsIfInvalidPath() { - Path::changeExtension(array(), '.sass'); + Path::changeExtension([], '.sass'); } /** @@ -490,36 +490,36 @@ public function testChangeExtensionFailsIfInvalidPath() */ public function testChangeExtensionFailsIfInvalidExtension() { - Path::changeExtension('/style.css', array()); + Path::changeExtension('/style.css', []); } public function provideIsAbsolutePathTests() { - return array( - array('/css/style.css', true), - array('/', true), - array('css/style.css', false), - array('', false), + return [ + ['/css/style.css', true], + ['/', true], + ['css/style.css', false], + ['', false], - array('\\css\\style.css', true), - array('\\', true), - array('css\\style.css', false), + ['\\css\\style.css', true], + ['\\', true], + ['css\\style.css', false], - array('C:/css/style.css', true), - array('D:/', true), + ['C:/css/style.css', true], + ['D:/', true], - array('E:\\css\\style.css', true), - array('F:\\', true), + ['E:\\css\\style.css', true], + ['F:\\', true], - array('phar:///css/style.css', true), - array('phar:///', true), + ['phar:///css/style.css', true], + ['phar:///', true], // Windows special case - array('C:', true), + ['C:', true], // Not considered absolute - array('C:css/style.css', false), - ); + ['C:css/style.css', false], + ]; } /** @@ -536,7 +536,7 @@ public function testIsAbsolute($path, $isAbsolute) */ public function testIsAbsoluteFailsIfInvalidPath() { - Path::isAbsolute(array()); + Path::isAbsolute([]); } /** @@ -553,35 +553,35 @@ public function testIsRelative($path, $isAbsolute) */ public function testIsRelativeFailsIfInvalidPath() { - Path::isRelative(array()); + Path::isRelative([]); } public function provideGetRootTests() { - return array( - array('/css/style.css', '/'), - array('/', '/'), - array('css/style.css', ''), - array('', ''), + return [ + ['/css/style.css', '/'], + ['/', '/'], + ['css/style.css', ''], + ['', ''], - array('\\css\\style.css', '/'), - array('\\', '/'), - array('css\\style.css', ''), + ['\\css\\style.css', '/'], + ['\\', '/'], + ['css\\style.css', ''], - array('C:/css/style.css', 'C:/'), - array('C:/', 'C:/'), - array('C:', 'C:/'), + ['C:/css/style.css', 'C:/'], + ['C:/', 'C:/'], + ['C:', 'C:/'], - array('D:\\css\\style.css', 'D:/'), - array('D:\\', 'D:/'), + ['D:\\css\\style.css', 'D:/'], + ['D:\\', 'D:/'], - array('phar:///css/style.css', 'phar:///'), - array('phar:///', 'phar:///'), + ['phar:///css/style.css', 'phar:///'], + ['phar:///', 'phar:///'], - array('phar://C:/css/style.css', 'phar://C:/'), - array('phar://C:/', 'phar://C:/'), - array('phar://C:', 'phar://C:/'), - ); + ['phar://C:/css/style.css', 'phar://C:/'], + ['phar://C:/', 'phar://C:/'], + ['phar://C:', 'phar://C:/'], + ]; } /** @@ -598,95 +598,95 @@ public function testGetRoot($path, $root) */ public function testGetRootFailsIfInvalidPath() { - Path::getRoot(array()); + Path::getRoot([]); } public function providePathTests() { - return array( + return [ // relative to absolute path - array('css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), - array('../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'), - array('../../css/style.css', '/webmozart/puli', '/css/style.css'), + ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], + ['../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'], + ['../../css/style.css', '/webmozart/puli', '/css/style.css'], // relative to root - array('css/style.css', '/', '/css/style.css'), - array('css/style.css', 'C:', 'C:/css/style.css'), - array('css/style.css', 'C:/', 'C:/css/style.css'), + ['css/style.css', '/', '/css/style.css'], + ['css/style.css', 'C:', 'C:/css/style.css'], + ['css/style.css', 'C:/', 'C:/css/style.css'], // same sub directories in different base directories - array('../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'), + ['../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'], - array('', '/webmozart/puli', '/webmozart/puli'), - array('..', '/webmozart/puli', '/webmozart'), - ); + ['', '/webmozart/puli', '/webmozart/puli'], + ['..', '/webmozart/puli', '/webmozart'], + ]; } public function provideMakeAbsoluteTests() { - return array_merge($this->providePathTests(), array( + return array_merge($this->providePathTests(), [ // collapse dots - array('css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), - array('css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'), - array('css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'), - array('css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'), - array('./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'), - - array('css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'), - array('css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), - array('css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), - array('css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'), - array('.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'), + ['css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], + ['css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'], + ['css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'], + ['css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'], + ['./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], + + ['css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'], + ['css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], + ['css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], + ['css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], + ['.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'], // collapse dots on root - array('./css/style.css', '/', '/css/style.css'), - array('../css/style.css', '/', '/css/style.css'), - array('../css/./style.css', '/', '/css/style.css'), - array('../css/../style.css', '/', '/style.css'), - array('../css/./../style.css', '/', '/style.css'), - array('../css/.././style.css', '/', '/style.css'), - - array('.\\css\\style.css', '\\', '/css/style.css'), - array('..\\css\\style.css', '\\', '/css/style.css'), - array('..\\css\\.\\style.css', '\\', '/css/style.css'), - array('..\\css\\..\\style.css', '\\', '/style.css'), - array('..\\css\\.\\..\\style.css', '\\', '/style.css'), - array('..\\css\\..\\.\\style.css', '\\', '/style.css'), - - array('./css/style.css', 'C:/', 'C:/css/style.css'), - array('../css/style.css', 'C:/', 'C:/css/style.css'), - array('../css/./style.css', 'C:/', 'C:/css/style.css'), - array('../css/../style.css', 'C:/', 'C:/style.css'), - array('../css/./../style.css', 'C:/', 'C:/style.css'), - array('../css/.././style.css', 'C:/', 'C:/style.css'), - - array('.\\css\\style.css', 'C:\\', 'C:/css/style.css'), - array('..\\css\\style.css', 'C:\\', 'C:/css/style.css'), - array('..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'), - array('..\\css\\..\\style.css', 'C:\\', 'C:/style.css'), - array('..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'), - array('..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'), - - array('./css/style.css', 'phar:///', 'phar:///css/style.css'), - array('../css/style.css', 'phar:///', 'phar:///css/style.css'), - array('../css/./style.css', 'phar:///', 'phar:///css/style.css'), - array('../css/../style.css', 'phar:///', 'phar:///style.css'), - array('../css/./../style.css', 'phar:///', 'phar:///style.css'), - array('../css/.././style.css', 'phar:///', 'phar:///style.css'), - - array('./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'), - array('../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'), - array('../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'), - array('../css/../style.css', 'phar://C:/', 'phar://C:/style.css'), - array('../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'), - array('../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'), + ['./css/style.css', '/', '/css/style.css'], + ['../css/style.css', '/', '/css/style.css'], + ['../css/./style.css', '/', '/css/style.css'], + ['../css/../style.css', '/', '/style.css'], + ['../css/./../style.css', '/', '/style.css'], + ['../css/.././style.css', '/', '/style.css'], + + ['.\\css\\style.css', '\\', '/css/style.css'], + ['..\\css\\style.css', '\\', '/css/style.css'], + ['..\\css\\.\\style.css', '\\', '/css/style.css'], + ['..\\css\\..\\style.css', '\\', '/style.css'], + ['..\\css\\.\\..\\style.css', '\\', '/style.css'], + ['..\\css\\..\\.\\style.css', '\\', '/style.css'], + + ['./css/style.css', 'C:/', 'C:/css/style.css'], + ['../css/style.css', 'C:/', 'C:/css/style.css'], + ['../css/./style.css', 'C:/', 'C:/css/style.css'], + ['../css/../style.css', 'C:/', 'C:/style.css'], + ['../css/./../style.css', 'C:/', 'C:/style.css'], + ['../css/.././style.css', 'C:/', 'C:/style.css'], + + ['.\\css\\style.css', 'C:\\', 'C:/css/style.css'], + ['..\\css\\style.css', 'C:\\', 'C:/css/style.css'], + ['..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'], + ['..\\css\\..\\style.css', 'C:\\', 'C:/style.css'], + ['..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'], + ['..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'], + + ['./css/style.css', 'phar:///', 'phar:///css/style.css'], + ['../css/style.css', 'phar:///', 'phar:///css/style.css'], + ['../css/./style.css', 'phar:///', 'phar:///css/style.css'], + ['../css/../style.css', 'phar:///', 'phar:///style.css'], + ['../css/./../style.css', 'phar:///', 'phar:///style.css'], + ['../css/.././style.css', 'phar:///', 'phar:///style.css'], + + ['./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'], + ['../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'], + ['../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'], + ['../css/../style.css', 'phar://C:/', 'phar://C:/style.css'], + ['../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'], + ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'], // absolute paths - array('/css/style.css', '/webmozart/puli', '/css/style.css'), - array('\\css\\style.css', '/webmozart/puli', '/css/style.css'), - array('C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'), - array('D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'), - )); + ['/css/style.css', '/webmozart/puli', '/css/style.css'], + ['\\css\\style.css', '/webmozart/puli', '/css/style.css'], + ['C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'], + ['D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'], + ]); } /** @@ -703,7 +703,7 @@ public function testMakeAbsolute($relativePath, $basePath, $absolutePath) */ public function testMakeAbsoluteFailsIfInvalidPath() { - Path::makeAbsolute(array(), '/webmozart/puli'); + Path::makeAbsolute([], '/webmozart/puli'); } /** @@ -712,7 +712,7 @@ public function testMakeAbsoluteFailsIfInvalidPath() */ public function testMakeAbsoluteFailsIfInvalidBasePath() { - Path::makeAbsolute('css/style.css', array()); + Path::makeAbsolute('css/style.css', []); } /** @@ -744,30 +744,30 @@ public function testMakeAbsoluteFailsIfBasePathNull() public function provideAbsolutePathsWithDifferentRoots() { - return array( - array('C:/css/style.css', '/webmozart/puli'), - array('C:/css/style.css', '\\webmozart\\puli'), - array('C:\\css\\style.css', '/webmozart/puli'), - array('C:\\css\\style.css', '\\webmozart\\puli'), - - array('/css/style.css', 'C:/webmozart/puli'), - array('/css/style.css', 'C:\\webmozart\\puli'), - array('\\css\\style.css', 'C:/webmozart/puli'), - array('\\css\\style.css', 'C:\\webmozart\\puli'), - - array('D:/css/style.css', 'C:/webmozart/puli'), - array('D:/css/style.css', 'C:\\webmozart\\puli'), - array('D:\\css\\style.css', 'C:/webmozart/puli'), - array('D:\\css\\style.css', 'C:\\webmozart\\puli'), - - array('phar:///css/style.css', '/webmozart/puli'), - array('/css/style.css', 'phar:///webmozart/puli'), - - array('phar://C:/css/style.css', 'C:/webmozart/puli'), - array('phar://C:/css/style.css', 'C:\\webmozart\\puli'), - array('phar://C:\\css\\style.css', 'C:/webmozart/puli'), - array('phar://C:\\css\\style.css', 'C:\\webmozart\\puli'), - ); + return [ + ['C:/css/style.css', '/webmozart/puli'], + ['C:/css/style.css', '\\webmozart\\puli'], + ['C:\\css\\style.css', '/webmozart/puli'], + ['C:\\css\\style.css', '\\webmozart\\puli'], + + ['/css/style.css', 'C:/webmozart/puli'], + ['/css/style.css', 'C:\\webmozart\\puli'], + ['\\css\\style.css', 'C:/webmozart/puli'], + ['\\css\\style.css', 'C:\\webmozart\\puli'], + + ['D:/css/style.css', 'C:/webmozart/puli'], + ['D:/css/style.css', 'C:\\webmozart\\puli'], + ['D:\\css\\style.css', 'C:/webmozart/puli'], + ['D:\\css\\style.css', 'C:\\webmozart\\puli'], + + ['phar:///css/style.css', '/webmozart/puli'], + ['/css/style.css', 'phar:///webmozart/puli'], + + ['phar://C:/css/style.css', 'C:/webmozart/puli'], + ['phar://C:/css/style.css', 'C:\\webmozart\\puli'], + ['phar://C:\\css\\style.css', 'C:/webmozart/puli'], + ['phar://C:\\css\\style.css', 'C:\\webmozart\\puli'], + ]; } /** @@ -783,96 +783,96 @@ public function testMakeAbsoluteDoesNotFailIfDifferentRoot($basePath, $absoluteP public function provideMakeRelativeTests() { $paths = array_map(function (array $arguments) { - return array($arguments[2], $arguments[1], $arguments[0]); + return [$arguments[2], $arguments[1], $arguments[0]]; }, $this->providePathTests()); - return array_merge($paths, array( - array('/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'), - array('/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'), - array('/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'), - array('/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'), - array('/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'), - array('/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'), - array('/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'), - array('/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'), - array('/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'), - array('/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'), + return array_merge($paths, [ + ['/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'], + ['/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'], + ['/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'], + ['/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'], + ['/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'], + ['/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'], + ['/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'], + ['/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'], + ['/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'], + ['/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'], // first argument shorter than second - array('/css', '/webmozart/puli', '../../css'), + ['/css', '/webmozart/puli', '../../css'], // second argument shorter than first - array('/webmozart/puli', '/css', '../webmozart/puli'), + ['/webmozart/puli', '/css', '../webmozart/puli'], - array('\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'), - array('\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'), - array('\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'), + ['\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'], + ['\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'], + ['\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'], - array('C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'), - array('C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'), - array('C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'), + ['C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'], + ['C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'], + ['C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'], - array('C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'), - array('C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'), - array('C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'), + ['C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'], + ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'], + ['C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'], - array('phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'), - array('phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'), - array('phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'), + ['phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'], + ['phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'], + ['phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'], - array('phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'), - array('phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'), - array('phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'), + ['phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'], + ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'], + ['phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'], // already relative + already in root basepath - array('../style.css', '/', 'style.css'), - array('./style.css', '/', 'style.css'), - array('../../style.css', '/', 'style.css'), - array('..\\style.css', 'C:\\', 'style.css'), - array('.\\style.css', 'C:\\', 'style.css'), - array('..\\..\\style.css', 'C:\\', 'style.css'), - array('../style.css', 'C:/', 'style.css'), - array('./style.css', 'C:/', 'style.css'), - array('../../style.css', 'C:/', 'style.css'), - array('..\\style.css', '\\', 'style.css'), - array('.\\style.css', '\\', 'style.css'), - array('..\\..\\style.css', '\\', 'style.css'), - array('../style.css', 'phar:///', 'style.css'), - array('./style.css', 'phar:///', 'style.css'), - array('../../style.css', 'phar:///', 'style.css'), - array('..\\style.css', 'phar://C:\\', 'style.css'), - array('.\\style.css', 'phar://C:\\', 'style.css'), - array('..\\..\\style.css', 'phar://C:\\', 'style.css'), - - array('css/../style.css', '/', 'style.css'), - array('css/./style.css', '/', 'css/style.css'), - array('css\\..\\style.css', 'C:\\', 'style.css'), - array('css\\.\\style.css', 'C:\\', 'css/style.css'), - array('css/../style.css', 'C:/', 'style.css'), - array('css/./style.css', 'C:/', 'css/style.css'), - array('css\\..\\style.css', '\\', 'style.css'), - array('css\\.\\style.css', '\\', 'css/style.css'), - array('css/../style.css', 'phar:///', 'style.css'), - array('css/./style.css', 'phar:///', 'css/style.css'), - array('css\\..\\style.css', 'phar://C:\\', 'style.css'), - array('css\\.\\style.css', 'phar://C:\\', 'css/style.css'), + ['../style.css', '/', 'style.css'], + ['./style.css', '/', 'style.css'], + ['../../style.css', '/', 'style.css'], + ['..\\style.css', 'C:\\', 'style.css'], + ['.\\style.css', 'C:\\', 'style.css'], + ['..\\..\\style.css', 'C:\\', 'style.css'], + ['../style.css', 'C:/', 'style.css'], + ['./style.css', 'C:/', 'style.css'], + ['../../style.css', 'C:/', 'style.css'], + ['..\\style.css', '\\', 'style.css'], + ['.\\style.css', '\\', 'style.css'], + ['..\\..\\style.css', '\\', 'style.css'], + ['../style.css', 'phar:///', 'style.css'], + ['./style.css', 'phar:///', 'style.css'], + ['../../style.css', 'phar:///', 'style.css'], + ['..\\style.css', 'phar://C:\\', 'style.css'], + ['.\\style.css', 'phar://C:\\', 'style.css'], + ['..\\..\\style.css', 'phar://C:\\', 'style.css'], + + ['css/../style.css', '/', 'style.css'], + ['css/./style.css', '/', 'css/style.css'], + ['css\\..\\style.css', 'C:\\', 'style.css'], + ['css\\.\\style.css', 'C:\\', 'css/style.css'], + ['css/../style.css', 'C:/', 'style.css'], + ['css/./style.css', 'C:/', 'css/style.css'], + ['css\\..\\style.css', '\\', 'style.css'], + ['css\\.\\style.css', '\\', 'css/style.css'], + ['css/../style.css', 'phar:///', 'style.css'], + ['css/./style.css', 'phar:///', 'css/style.css'], + ['css\\..\\style.css', 'phar://C:\\', 'style.css'], + ['css\\.\\style.css', 'phar://C:\\', 'css/style.css'], // already relative - array('css/style.css', '/webmozart/puli', 'css/style.css'), - array('css\\style.css', '\\webmozart\\puli', 'css/style.css'), + ['css/style.css', '/webmozart/puli', 'css/style.css'], + ['css\\style.css', '\\webmozart\\puli', 'css/style.css'], // both relative - array('css/style.css', 'webmozart/puli', '../../css/style.css'), - array('css\\style.css', 'webmozart\\puli', '../../css/style.css'), + ['css/style.css', 'webmozart/puli', '../../css/style.css'], + ['css\\style.css', 'webmozart\\puli', '../../css/style.css'], // relative to empty - array('css/style.css', '', 'css/style.css'), - array('css\\style.css', '', 'css/style.css'), + ['css/style.css', '', 'css/style.css'], + ['css\\style.css', '', 'css/style.css'], // different slashes in path and base path - array('/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'), - array('\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'), - )); + ['/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'], + ['\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'], + ]); } /** @@ -889,7 +889,7 @@ public function testMakeRelative($absolutePath, $basePath, $relativePath) */ public function testMakeRelativeFailsIfInvalidPath() { - Path::makeRelative(array(), '/webmozart/puli'); + Path::makeRelative([], '/webmozart/puli'); } /** @@ -898,7 +898,7 @@ public function testMakeRelativeFailsIfInvalidPath() */ public function testMakeRelativeFailsIfInvalidBasePath() { - Path::makeRelative('/webmozart/puli/css/style.css', array()); + Path::makeRelative('/webmozart/puli/css/style.css', []); } /** @@ -939,13 +939,13 @@ public function testMakeRelativeFailsIfDifferentRoot($absolutePath, $basePath) public function provideIsLocalTests() { - return array( - array('/bg.png', true), - array('bg.png', true), - array('http://example.com/bg.png', false), - array('http://example.com', false), - array('', false), - ); + return [ + ['/bg.png', true], + ['bg.png', true], + ['http://example.com/bg.png', false], + ['http://example.com', false], + ['', false], + ]; } /** @@ -962,119 +962,119 @@ public function testIsLocal($path, $isLocal) */ public function testIsLocalFailsIfInvalidPath() { - Path::isLocal(array()); + Path::isLocal([]); } public function provideGetLongestCommonBasePathTests() { - return array( + return [ // same paths - array(array('/base/path', '/base/path'), '/base/path'), - array(array('C:/base/path', 'C:/base/path'), 'C:/base/path'), - array(array('C:\\base\\path', 'C:\\base\\path'), 'C:/base/path'), - array(array('C:/base/path', 'C:\\base\\path'), 'C:/base/path'), - array(array('phar:///base/path', 'phar:///base/path'), 'phar:///base/path'), - array(array('phar://C:/base/path', 'phar://C:/base/path'), 'phar://C:/base/path'), + [['/base/path', '/base/path'], '/base/path'], + [['C:/base/path', 'C:/base/path'], 'C:/base/path'], + [['C:\\base\\path', 'C:\\base\\path'], 'C:/base/path'], + [['C:/base/path', 'C:\\base\\path'], 'C:/base/path'], + [['phar:///base/path', 'phar:///base/path'], 'phar:///base/path'], + [['phar://C:/base/path', 'phar://C:/base/path'], 'phar://C:/base/path'], // trailing slash - array(array('/base/path/', '/base/path'), '/base/path'), - array(array('C:/base/path/', 'C:/base/path'), 'C:/base/path'), - array(array('C:\\base\\path\\', 'C:\\base\\path'), 'C:/base/path'), - array(array('C:/base/path/', 'C:\\base\\path'), 'C:/base/path'), - array(array('phar:///base/path/', 'phar:///base/path'), 'phar:///base/path'), - array(array('phar://C:/base/path/', 'phar://C:/base/path'), 'phar://C:/base/path'), - - array(array('/base/path', '/base/path/'), '/base/path'), - array(array('C:/base/path', 'C:/base/path/'), 'C:/base/path'), - array(array('C:\\base\\path', 'C:\\base\\path\\'), 'C:/base/path'), - array(array('C:/base/path', 'C:\\base\\path\\'), 'C:/base/path'), - array(array('phar:///base/path', 'phar:///base/path/'), 'phar:///base/path'), - array(array('phar://C:/base/path', 'phar://C:/base/path/'), 'phar://C:/base/path'), + [['/base/path/', '/base/path'], '/base/path'], + [['C:/base/path/', 'C:/base/path'], 'C:/base/path'], + [['C:\\base\\path\\', 'C:\\base\\path'], 'C:/base/path'], + [['C:/base/path/', 'C:\\base\\path'], 'C:/base/path'], + [['phar:///base/path/', 'phar:///base/path'], 'phar:///base/path'], + [['phar://C:/base/path/', 'phar://C:/base/path'], 'phar://C:/base/path'], + + [['/base/path', '/base/path/'], '/base/path'], + [['C:/base/path', 'C:/base/path/'], 'C:/base/path'], + [['C:\\base\\path', 'C:\\base\\path\\'], 'C:/base/path'], + [['C:/base/path', 'C:\\base\\path\\'], 'C:/base/path'], + [['phar:///base/path', 'phar:///base/path/'], 'phar:///base/path'], + [['phar://C:/base/path', 'phar://C:/base/path/'], 'phar://C:/base/path'], // first in second - array(array('/base/path/sub', '/base/path'), '/base/path'), - array(array('C:/base/path/sub', 'C:/base/path'), 'C:/base/path'), - array(array('C:\\base\\path\\sub', 'C:\\base\\path'), 'C:/base/path'), - array(array('C:/base/path/sub', 'C:\\base\\path'), 'C:/base/path'), - array(array('phar:///base/path/sub', 'phar:///base/path'), 'phar:///base/path'), - array(array('phar://C:/base/path/sub', 'phar://C:/base/path'), 'phar://C:/base/path'), + [['/base/path/sub', '/base/path'], '/base/path'], + [['C:/base/path/sub', 'C:/base/path'], 'C:/base/path'], + [['C:\\base\\path\\sub', 'C:\\base\\path'], 'C:/base/path'], + [['C:/base/path/sub', 'C:\\base\\path'], 'C:/base/path'], + [['phar:///base/path/sub', 'phar:///base/path'], 'phar:///base/path'], + [['phar://C:/base/path/sub', 'phar://C:/base/path'], 'phar://C:/base/path'], // second in first - array(array('/base/path', '/base/path/sub'), '/base/path'), - array(array('C:/base/path', 'C:/base/path/sub'), 'C:/base/path'), - array(array('C:\\base\\path', 'C:\\base\\path\\sub'), 'C:/base/path'), - array(array('C:/base/path', 'C:\\base\\path\\sub'), 'C:/base/path'), - array(array('phar:///base/path', 'phar:///base/path/sub'), 'phar:///base/path'), - array(array('phar://C:/base/path', 'phar://C:/base/path/sub'), 'phar://C:/base/path'), + [['/base/path', '/base/path/sub'], '/base/path'], + [['C:/base/path', 'C:/base/path/sub'], 'C:/base/path'], + [['C:\\base\\path', 'C:\\base\\path\\sub'], 'C:/base/path'], + [['C:/base/path', 'C:\\base\\path\\sub'], 'C:/base/path'], + [['phar:///base/path', 'phar:///base/path/sub'], 'phar:///base/path'], + [['phar://C:/base/path', 'phar://C:/base/path/sub'], 'phar://C:/base/path'], // first is prefix - array(array('/base/path/di', '/base/path/dir'), '/base/path'), - array(array('C:/base/path/di', 'C:/base/path/dir'), 'C:/base/path'), - array(array('C:\\base\\path\\di', 'C:\\base\\path\\dir'), 'C:/base/path'), - array(array('C:/base/path/di', 'C:\\base\\path\\dir'), 'C:/base/path'), - array(array('phar:///base/path/di', 'phar:///base/path/dir'), 'phar:///base/path'), - array(array('phar://C:/base/path/di', 'phar://C:/base/path/dir'), 'phar://C:/base/path'), + [['/base/path/di', '/base/path/dir'], '/base/path'], + [['C:/base/path/di', 'C:/base/path/dir'], 'C:/base/path'], + [['C:\\base\\path\\di', 'C:\\base\\path\\dir'], 'C:/base/path'], + [['C:/base/path/di', 'C:\\base\\path\\dir'], 'C:/base/path'], + [['phar:///base/path/di', 'phar:///base/path/dir'], 'phar:///base/path'], + [['phar://C:/base/path/di', 'phar://C:/base/path/dir'], 'phar://C:/base/path'], // second is prefix - array(array('/base/path/dir', '/base/path/di'), '/base/path'), - array(array('C:/base/path/dir', 'C:/base/path/di'), 'C:/base/path'), - array(array('C:\\base\\path\\dir', 'C:\\base\\path\\di'), 'C:/base/path'), - array(array('C:/base/path/dir', 'C:\\base\\path\\di'), 'C:/base/path'), - array(array('phar:///base/path/dir', 'phar:///base/path/di'), 'phar:///base/path'), - array(array('phar://C:/base/path/dir', 'phar://C:/base/path/di'), 'phar://C:/base/path'), + [['/base/path/dir', '/base/path/di'], '/base/path'], + [['C:/base/path/dir', 'C:/base/path/di'], 'C:/base/path'], + [['C:\\base\\path\\dir', 'C:\\base\\path\\di'], 'C:/base/path'], + [['C:/base/path/dir', 'C:\\base\\path\\di'], 'C:/base/path'], + [['phar:///base/path/dir', 'phar:///base/path/di'], 'phar:///base/path'], + [['phar://C:/base/path/dir', 'phar://C:/base/path/di'], 'phar://C:/base/path'], // root is common base path - array(array('/first', '/second'), '/'), - array(array('C:/first', 'C:/second'), 'C:/'), - array(array('C:\\first', 'C:\\second'), 'C:/'), - array(array('C:/first', 'C:\\second'), 'C:/'), - array(array('phar:///first', 'phar:///second'), 'phar:///'), - array(array('phar://C:/first', 'phar://C:/second'), 'phar://C:/'), + [['/first', '/second'], '/'], + [['C:/first', 'C:/second'], 'C:/'], + [['C:\\first', 'C:\\second'], 'C:/'], + [['C:/first', 'C:\\second'], 'C:/'], + [['phar:///first', 'phar:///second'], 'phar:///'], + [['phar://C:/first', 'phar://C:/second'], 'phar://C:/'], // windows vs unix - array(array('/base/path', 'C:/base/path'), null), - array(array('C:/base/path', '/base/path'), null), - array(array('/base/path', 'C:\\base\\path'), null), - array(array('phar:///base/path', 'phar://C:/base/path'), null), + [['/base/path', 'C:/base/path'], null], + [['C:/base/path', '/base/path'], null], + [['/base/path', 'C:\\base\\path'], null], + [['phar:///base/path', 'phar://C:/base/path'], null], // different partitions - array(array('C:/base/path', 'D:/base/path'), null), - array(array('C:/base/path', 'D:\\base\\path'), null), - array(array('C:\\base\\path', 'D:\\base\\path'), null), - array(array('phar://C:/base/path', 'phar://D:/base/path'), null), + [['C:/base/path', 'D:/base/path'], null], + [['C:/base/path', 'D:\\base\\path'], null], + [['C:\\base\\path', 'D:\\base\\path'], null], + [['phar://C:/base/path', 'phar://D:/base/path'], null], // three paths - array(array('/base/path/foo', '/base/path', '/base/path/bar'), '/base/path'), - array(array('C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'), 'C:/base/path'), - array(array('C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'), 'C:/base/path'), - array(array('C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'), 'C:/base/path'), - array(array('phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'), 'phar:///base/path'), - array(array('phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'), 'phar://C:/base/path'), + [['/base/path/foo', '/base/path', '/base/path/bar'], '/base/path'], + [['C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'], 'C:/base/path'], + [['C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'], 'C:/base/path'], + [['C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'], 'C:/base/path'], + [['phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'], 'phar:///base/path'], + [['phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'], 'phar://C:/base/path'], // three paths with root - array(array('/base/path/foo', '/', '/base/path/bar'), '/'), - array(array('C:/base/path/foo', 'C:/', 'C:/base/path/bar'), 'C:/'), - array(array('C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'), 'C:/'), - array(array('C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'), 'C:/'), - array(array('phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'), 'phar:///'), - array(array('phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'), 'phar://C:/'), + [['/base/path/foo', '/', '/base/path/bar'], '/'], + [['C:/base/path/foo', 'C:/', 'C:/base/path/bar'], 'C:/'], + [['C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'], 'C:/'], + [['C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'], 'C:/'], + [['phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'], 'phar:///'], + [['phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'], 'phar://C:/'], // three paths, different roots - array(array('/base/path/foo', 'C:/base/path', '/base/path/bar'), null), - array(array('/base/path/foo', 'C:\\base\\path', '/base/path/bar'), null), - array(array('C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'), null), - array(array('C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'), null), - array(array('C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'), null), - array(array('phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'), null), - array(array('phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'), null), + [['/base/path/foo', 'C:/base/path', '/base/path/bar'], null], + [['/base/path/foo', 'C:\\base\\path', '/base/path/bar'], null], + [['C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'], null], + [['C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'], null], + [['C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'], null], + [['phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'], null], + [['phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'], null], // only one path - array(array('/base/path'), '/base/path'), - array(array('C:/base/path'), 'C:/base/path'), - array(array('C:\\base\\path'), 'C:/base/path'), - array(array('phar:///base/path'), 'phar:///base/path'), - array(array('phar://C:/base/path'), 'phar://C:/base/path'), - ); + [['/base/path'], '/base/path'], + [['C:/base/path'], 'C:/base/path'], + [['C:\\base\\path'], 'C:/base/path'], + [['phar:///base/path'], 'phar:///base/path'], + [['phar://C:/base/path'], 'phar://C:/base/path'], + ]; } /** @@ -1091,7 +1091,7 @@ public function testGetLongestCommonBasePath(array $paths, $basePath) */ public function testGetLongestCommonBasePathFailsIfInvalidPath() { - Path::getLongestCommonBasePath(array(array())); + Path::getLongestCommonBasePath([[]]); } public function provideIsBasePathTests() @@ -1191,7 +1191,7 @@ public function testIsBasePath($path, $ofPath, $result) */ public function testIsBasePathFailsIfInvalidBasePath() { - Path::isBasePath(array(), '/base/path'); + Path::isBasePath([], '/base/path'); } /** @@ -1200,7 +1200,7 @@ public function testIsBasePathFailsIfInvalidBasePath() */ public function testIsBasePathFailsIfInvalidPath() { - Path::isBasePath('/base/path', array()); + Path::isBasePath('/base/path', []); } public function provideJoinTests() From 9cfa4aaef77fa1c6031cc56e5ea9c8cc80411f30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Wed, 10 Apr 2019 21:16:31 +0200 Subject: [PATCH 03/21] Fix the tests --- src/Symfony/Component/Filesystem/Path.php | 13 +- .../Component/Filesystem/Tests/PathTest.php | 1855 +++++++---------- 2 files changed, 809 insertions(+), 1059 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index b9d63c46ff6ab..0afd9790bd519 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -18,6 +18,7 @@ use function getenv; use function implode; use InvalidArgumentException; +use function is_string; use function ltrim; use function mb_strtolower; use function pathinfo; @@ -391,10 +392,14 @@ public static function hasExtension(string $path, $extensions = null, bool $igno $actualExtension = self::getExtension($path, $ignoreCase); // Only check if path has any extension - if (empty($extensions)) { + if ([] === $extensions || null === $extensions) { return '' !== $actualExtension; } + if (is_string($extensions)) { + $extensions = [$extensions]; + } + foreach ($extensions as $key => $extension) { if ($ignoreCase) { $extension = self::toLower($extension); @@ -532,6 +537,10 @@ public static function isRelative(string $path): bool */ public static function makeAbsolute(string $path, string $basePath): string { + if ('' === $basePath) { + throw new \InvalidArgumentException(sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); + } + if (!static::isAbsolute($basePath)) { throw new InvalidArgumentException(sprintf( 'The base path "%s" is not an absolute path.', @@ -774,8 +783,6 @@ public static function getLongestCommonBasePath(array $paths): ?string * * The result is a canonical path. * - * @param string[]|string $paths path parts as parameters or array - * * @return string the joint path */ public static function join(string ...$paths): string diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index c008fbb18dd26..b7dad1bd33178 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Filesystem\Tests; +use Generator; use PHPUnit\Framework\TestCase; use Symfony\Component\Filesystem\Path; @@ -24,7 +25,7 @@ class PathTest extends TestCase { protected $storedEnv = []; - public function setUp() + public function setUp(): void { $this->storedEnv['HOME'] = getenv('HOME'); $this->storedEnv['HOMEDRIVE'] = getenv('HOMEDRIVE'); @@ -35,1256 +36,1016 @@ public function setUp() putenv('HOMEPATH='); } - public function tearDown() + public function tearDown(): void { putenv('HOME='.$this->storedEnv['HOME']); putenv('HOMEDRIVE='.$this->storedEnv['HOMEDRIVE']); putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']); } - public function provideCanonicalizationTests() - { - return [ - // relative paths (forward slash) - ['css/./style.css', 'css/style.css'], - ['css/../style.css', 'style.css'], - ['css/./../style.css', 'style.css'], - ['css/.././style.css', 'style.css'], - ['css/../../style.css', '../style.css'], - ['./css/style.css', 'css/style.css'], - ['../css/style.css', '../css/style.css'], - ['./../css/style.css', '../css/style.css'], - ['.././css/style.css', '../css/style.css'], - ['../../css/style.css', '../../css/style.css'], - ['', ''], - ['.', ''], - ['..', '..'], - ['./..', '..'], - ['../.', '..'], - ['../..', '../..'], - - // relative paths (backslash) - ['css\\.\\style.css', 'css/style.css'], - ['css\\..\\style.css', 'style.css'], - ['css\\.\\..\\style.css', 'style.css'], - ['css\\..\\.\\style.css', 'style.css'], - ['css\\..\\..\\style.css', '../style.css'], - ['.\\css\\style.css', 'css/style.css'], - ['..\\css\\style.css', '../css/style.css'], - ['.\\..\\css\\style.css', '../css/style.css'], - ['..\\.\\css\\style.css', '../css/style.css'], - ['..\\..\\css\\style.css', '../../css/style.css'], - - // absolute paths (forward slash, UNIX) - ['/css/style.css', '/css/style.css'], - ['/css/./style.css', '/css/style.css'], - ['/css/../style.css', '/style.css'], - ['/css/./../style.css', '/style.css'], - ['/css/.././style.css', '/style.css'], - ['/./css/style.css', '/css/style.css'], - ['/../css/style.css', '/css/style.css'], - ['/./../css/style.css', '/css/style.css'], - ['/.././css/style.css', '/css/style.css'], - ['/../../css/style.css', '/css/style.css'], - - // absolute paths (backslash, UNIX) - ['\\css\\style.css', '/css/style.css'], - ['\\css\\.\\style.css', '/css/style.css'], - ['\\css\\..\\style.css', '/style.css'], - ['\\css\\.\\..\\style.css', '/style.css'], - ['\\css\\..\\.\\style.css', '/style.css'], - ['\\.\\css\\style.css', '/css/style.css'], - ['\\..\\css\\style.css', '/css/style.css'], - ['\\.\\..\\css\\style.css', '/css/style.css'], - ['\\..\\.\\css\\style.css', '/css/style.css'], - ['\\..\\..\\css\\style.css', '/css/style.css'], - - // absolute paths (forward slash, Windows) - ['C:/css/style.css', 'C:/css/style.css'], - ['C:/css/./style.css', 'C:/css/style.css'], - ['C:/css/../style.css', 'C:/style.css'], - ['C:/css/./../style.css', 'C:/style.css'], - ['C:/css/.././style.css', 'C:/style.css'], - ['C:/./css/style.css', 'C:/css/style.css'], - ['C:/../css/style.css', 'C:/css/style.css'], - ['C:/./../css/style.css', 'C:/css/style.css'], - ['C:/.././css/style.css', 'C:/css/style.css'], - ['C:/../../css/style.css', 'C:/css/style.css'], - - // absolute paths (backslash, Windows) - ['C:\\css\\style.css', 'C:/css/style.css'], - ['C:\\css\\.\\style.css', 'C:/css/style.css'], - ['C:\\css\\..\\style.css', 'C:/style.css'], - ['C:\\css\\.\\..\\style.css', 'C:/style.css'], - ['C:\\css\\..\\.\\style.css', 'C:/style.css'], - ['C:\\.\\css\\style.css', 'C:/css/style.css'], - ['C:\\..\\css\\style.css', 'C:/css/style.css'], - ['C:\\.\\..\\css\\style.css', 'C:/css/style.css'], - ['C:\\..\\.\\css\\style.css', 'C:/css/style.css'], - ['C:\\..\\..\\css\\style.css', 'C:/css/style.css'], - - // Windows special case - ['C:', 'C:/'], - - // Don't change malformed path - ['C:css/style.css', 'C:css/style.css'], - - // absolute paths (stream, UNIX) - ['phar:///css/style.css', 'phar:///css/style.css'], - ['phar:///css/./style.css', 'phar:///css/style.css'], - ['phar:///css/../style.css', 'phar:///style.css'], - ['phar:///css/./../style.css', 'phar:///style.css'], - ['phar:///css/.././style.css', 'phar:///style.css'], - ['phar:///./css/style.css', 'phar:///css/style.css'], - ['phar:///../css/style.css', 'phar:///css/style.css'], - ['phar:///./../css/style.css', 'phar:///css/style.css'], - ['phar:///.././css/style.css', 'phar:///css/style.css'], - ['phar:///../../css/style.css', 'phar:///css/style.css'], - - // absolute paths (stream, Windows) - ['phar://C:/css/style.css', 'phar://C:/css/style.css'], - ['phar://C:/css/./style.css', 'phar://C:/css/style.css'], - ['phar://C:/css/../style.css', 'phar://C:/style.css'], - ['phar://C:/css/./../style.css', 'phar://C:/style.css'], - ['phar://C:/css/.././style.css', 'phar://C:/style.css'], - ['phar://C:/./css/style.css', 'phar://C:/css/style.css'], - ['phar://C:/../css/style.css', 'phar://C:/css/style.css'], - ['phar://C:/./../css/style.css', 'phar://C:/css/style.css'], - ['phar://C:/.././css/style.css', 'phar://C:/css/style.css'], - ['phar://C:/../../css/style.css', 'phar://C:/css/style.css'], - - // paths with "~" UNIX - ['~/css/style.css', '/home/webmozart/css/style.css'], - ['~/css/./style.css', '/home/webmozart/css/style.css'], - ['~/css/../style.css', '/home/webmozart/style.css'], - ['~/css/./../style.css', '/home/webmozart/style.css'], - ['~/css/.././style.css', '/home/webmozart/style.css'], - ['~/./css/style.css', '/home/webmozart/css/style.css'], - ['~/../css/style.css', '/home/css/style.css'], - ['~/./../css/style.css', '/home/css/style.css'], - ['~/.././css/style.css', '/home/css/style.css'], - ['~/../../css/style.css', '/css/style.css'], - ]; + public function provideCanonicalizationTests(): Generator + { + // relative paths (forward slash) + yield ['css/./style.css', 'css/style.css']; + yield ['css/../style.css', 'style.css']; + yield ['css/./../style.css', 'style.css']; + yield ['css/.././style.css', 'style.css']; + yield ['css/../../style.css', '../style.css']; + yield ['./css/style.css', 'css/style.css']; + yield ['../css/style.css', '../css/style.css']; + yield ['./../css/style.css', '../css/style.css']; + yield ['.././css/style.css', '../css/style.css']; + yield ['../../css/style.css', '../../css/style.css']; + yield ['', '']; + yield ['.', '']; + yield ['..', '..']; + yield ['./..', '..']; + yield ['../.', '..']; + yield ['../..', '../..']; + + // relative paths (backslash) + yield ['css\\.\\style.css', 'css/style.css']; + yield ['css\\..\\style.css', 'style.css']; + yield ['css\\.\\..\\style.css', 'style.css']; + yield ['css\\..\\.\\style.css', 'style.css']; + yield ['css\\..\\..\\style.css', '../style.css']; + yield ['.\\css\\style.css', 'css/style.css']; + yield ['..\\css\\style.css', '../css/style.css']; + yield ['.\\..\\css\\style.css', '../css/style.css']; + yield ['..\\.\\css\\style.css', '../css/style.css']; + yield ['..\\..\\css\\style.css', '../../css/style.css']; + + // absolute paths (forward slash, UNIX) + yield ['/css/style.css', '/css/style.css']; + yield ['/css/./style.css', '/css/style.css']; + yield ['/css/../style.css', '/style.css']; + yield ['/css/./../style.css', '/style.css']; + yield ['/css/.././style.css', '/style.css']; + yield ['/./css/style.css', '/css/style.css']; + yield ['/../css/style.css', '/css/style.css']; + yield ['/./../css/style.css', '/css/style.css']; + yield ['/.././css/style.css', '/css/style.css']; + yield ['/../../css/style.css', '/css/style.css']; + + // absolute paths (backslash, UNIX) + yield ['\\css\\style.css', '/css/style.css']; + yield ['\\css\\.\\style.css', '/css/style.css']; + yield ['\\css\\..\\style.css', '/style.css']; + yield ['\\css\\.\\..\\style.css', '/style.css']; + yield ['\\css\\..\\.\\style.css', '/style.css']; + yield ['\\.\\css\\style.css', '/css/style.css']; + yield ['\\..\\css\\style.css', '/css/style.css']; + yield ['\\.\\..\\css\\style.css', '/css/style.css']; + yield ['\\..\\.\\css\\style.css', '/css/style.css']; + yield ['\\..\\..\\css\\style.css', '/css/style.css']; + + // absolute paths (forward slash, Windows) + yield ['C:/css/style.css', 'C:/css/style.css']; + yield ['C:/css/./style.css', 'C:/css/style.css']; + yield ['C:/css/../style.css', 'C:/style.css']; + yield ['C:/css/./../style.css', 'C:/style.css']; + yield ['C:/css/.././style.css', 'C:/style.css']; + yield ['C:/./css/style.css', 'C:/css/style.css']; + yield ['C:/../css/style.css', 'C:/css/style.css']; + yield ['C:/./../css/style.css', 'C:/css/style.css']; + yield ['C:/.././css/style.css', 'C:/css/style.css']; + yield ['C:/../../css/style.css', 'C:/css/style.css']; + + // absolute paths (backslash, Windows) + yield ['C:\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\css\\.\\style.css', 'C:/css/style.css']; + yield ['C:\\css\\..\\style.css', 'C:/style.css']; + yield ['C:\\css\\.\\..\\style.css', 'C:/style.css']; + yield ['C:\\css\\..\\.\\style.css', 'C:/style.css']; + yield ['C:\\.\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\.\\..\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\.\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\..\\css\\style.css', 'C:/css/style.css']; + + // Windows special case + yield ['C:', 'C:/']; + + // Don't change malformed path + yield ['C:css/style.css', 'C:css/style.css']; + + // absolute paths (stream, UNIX) + yield ['phar:///css/style.css', 'phar:///css/style.css']; + yield ['phar:///css/./style.css', 'phar:///css/style.css']; + yield ['phar:///css/../style.css', 'phar:///style.css']; + yield ['phar:///css/./../style.css', 'phar:///style.css']; + yield ['phar:///css/.././style.css', 'phar:///style.css']; + yield ['phar:///./css/style.css', 'phar:///css/style.css']; + yield ['phar:///../css/style.css', 'phar:///css/style.css']; + yield ['phar:///./../css/style.css', 'phar:///css/style.css']; + yield ['phar:///.././css/style.css', 'phar:///css/style.css']; + yield ['phar:///../../css/style.css', 'phar:///css/style.css']; + + // absolute paths (stream, Windows) + yield ['phar://C:/css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/css/./style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/css/../style.css', 'phar://C:/style.css']; + yield ['phar://C:/css/./../style.css', 'phar://C:/style.css']; + yield ['phar://C:/css/.././style.css', 'phar://C:/style.css']; + yield ['phar://C:/./css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/../css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/./../css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/.././css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/../../css/style.css', 'phar://C:/css/style.css']; + + // paths with "~" UNIX + yield ['~/css/style.css', '/home/webmozart/css/style.css']; + yield ['~/css/./style.css', '/home/webmozart/css/style.css']; + yield ['~/css/../style.css', '/home/webmozart/style.css']; + yield ['~/css/./../style.css', '/home/webmozart/style.css']; + yield ['~/css/.././style.css', '/home/webmozart/style.css']; + yield ['~/./css/style.css', '/home/webmozart/css/style.css']; + yield ['~/../css/style.css', '/home/css/style.css']; + yield ['~/./../css/style.css', '/home/css/style.css']; + yield ['~/.././css/style.css', '/home/css/style.css']; + yield ['~/../../css/style.css', '/css/style.css']; } /** * @dataProvider provideCanonicalizationTests */ - public function testCanonicalize($path, $canonicalized) + public function testCanonicalize(string $path, string $canonicalized): void { $this->assertSame($canonicalized, Path::canonicalize($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testCanonicalizeFailsIfInvalidPath() + public function provideGetDirectoryTests(): Generator { - Path::canonicalize([]); - } + yield ['/webmozart/puli/style.css', '/webmozart/puli']; + yield ['/webmozart/puli', '/webmozart']; + yield ['/webmozart', '/']; + yield ['/', '/']; + yield ['', '']; - public function provideGetDirectoryTests() - { - return [ - ['/webmozart/puli/style.css', '/webmozart/puli'], - ['/webmozart/puli', '/webmozart'], - ['/webmozart', '/'], - ['/', '/'], - ['', ''], - - ['\\webmozart\\puli\\style.css', '/webmozart/puli'], - ['\\webmozart\\puli', '/webmozart'], - ['\\webmozart', '/'], - ['\\', '/'], - - ['C:/webmozart/puli/style.css', 'C:/webmozart/puli'], - ['C:/webmozart/puli', 'C:/webmozart'], - ['C:/webmozart', 'C:/'], - ['C:/', 'C:/'], - ['C:', 'C:/'], - - ['C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli'], - ['C:\\webmozart\\puli', 'C:/webmozart'], - ['C:\\webmozart', 'C:/'], - ['C:\\', 'C:/'], - - ['phar:///webmozart/puli/style.css', 'phar:///webmozart/puli'], - ['phar:///webmozart/puli', 'phar:///webmozart'], - ['phar:///webmozart', 'phar:///'], - ['phar:///', 'phar:///'], - - ['phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli'], - ['phar://C:/webmozart/puli', 'phar://C:/webmozart'], - ['phar://C:/webmozart', 'phar://C:/'], - ['phar://C:/', 'phar://C:/'], - - ['webmozart/puli/style.css', 'webmozart/puli'], - ['webmozart/puli', 'webmozart'], - ['webmozart', ''], - - ['webmozart\\puli\\style.css', 'webmozart/puli'], - ['webmozart\\puli', 'webmozart'], - ['webmozart', ''], - - ['/webmozart/./puli/style.css', '/webmozart/puli'], - ['/webmozart/../puli/style.css', '/puli'], - ['/webmozart/./../puli/style.css', '/puli'], - ['/webmozart/.././puli/style.css', '/puli'], - ['/webmozart/../../puli/style.css', '/puli'], - ['/.', '/'], - ['/..', '/'], - - ['C:webmozart', ''], - ]; + yield ['\\webmozart\\puli\\style.css', '/webmozart/puli']; + yield ['\\webmozart\\puli', '/webmozart']; + yield ['\\webmozart', '/']; + yield ['\\', '/']; + + yield ['C:/webmozart/puli/style.css', 'C:/webmozart/puli']; + yield ['C:/webmozart/puli', 'C:/webmozart']; + yield ['C:/webmozart', 'C:/']; + yield ['C:/', 'C:/']; + yield ['C:', 'C:/']; + + yield ['C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli']; + yield ['C:\\webmozart\\puli', 'C:/webmozart']; + yield ['C:\\webmozart', 'C:/']; + yield ['C:\\', 'C:/']; + + yield ['phar:///webmozart/puli/style.css', 'phar:///webmozart/puli']; + yield ['phar:///webmozart/puli', 'phar:///webmozart']; + yield ['phar:///webmozart', 'phar:///']; + yield ['phar:///', 'phar:///']; + + yield ['phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli']; + yield ['phar://C:/webmozart/puli', 'phar://C:/webmozart']; + yield ['phar://C:/webmozart', 'phar://C:/']; + yield ['phar://C:/', 'phar://C:/']; + + yield ['webmozart/puli/style.css', 'webmozart/puli']; + yield ['webmozart/puli', 'webmozart']; + yield ['webmozart', '']; + + yield ['webmozart\\puli\\style.css', 'webmozart/puli']; + yield ['webmozart\\puli', 'webmozart']; + yield ['webmozart', '']; + + yield ['/webmozart/./puli/style.css', '/webmozart/puli']; + yield ['/webmozart/../puli/style.css', '/puli']; + yield ['/webmozart/./../puli/style.css', '/puli']; + yield ['/webmozart/.././puli/style.css', '/puli']; + yield ['/webmozart/../../puli/style.css', '/puli']; + yield ['/.', '/']; + yield ['/..', '/']; + + yield ['C:webmozart', '']; } /** * @dataProvider provideGetDirectoryTests */ - public function testGetDirectory($path, $directory) + public function testGetDirectory(string $path, string $directory): void { $this->assertSame($directory, Path::getDirectory($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testGetDirectoryFailsIfInvalidPath() - { - Path::getDirectory([]); - } - - public function provideGetFilenameTests() + public function provideGetFilenameTests(): Generator { - return [ - ['/webmozart/puli/style.css', 'style.css'], - ['/webmozart/puli/STYLE.CSS', 'STYLE.CSS'], - ['/webmozart/puli/style.css/', 'style.css'], - ['/webmozart/puli/', 'puli'], - ['/webmozart/puli', 'puli'], - ['/', ''], - ['', ''], - ]; + yield ['/webmozart/puli/style.css', 'style.css']; + yield ['/webmozart/puli/STYLE.CSS', 'STYLE.CSS']; + yield ['/webmozart/puli/style.css/', 'style.css']; + yield ['/webmozart/puli/', 'puli']; + yield ['/webmozart/puli', 'puli']; + yield ['/', '']; + yield ['', '']; } /** * @dataProvider provideGetFilenameTests */ - public function testGetFilename($path, $filename) + public function testGetFilename(string $path, string $filename): void { $this->assertSame($filename, Path::getFilename($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testGetFilenameFailsIfInvalidPath() + public function provideGetFilenameWithoutExtensionTests(): Generator { - Path::getFilename([]); - } + yield ['/webmozart/puli/style.css.twig', null, 'style.css']; + yield ['/webmozart/puli/style.css.', null, 'style.css']; + yield ['/webmozart/puli/style.css', null, 'style']; + yield ['/webmozart/puli/.style.css', null, '.style']; + yield ['/webmozart/puli/', null, 'puli']; + yield ['/webmozart/puli', null, 'puli']; + yield ['/', null, '']; + yield ['', null, '']; - public function provideGetFilenameWithoutExtensionTests() - { - return [ - ['/webmozart/puli/style.css.twig', null, 'style.css'], - ['/webmozart/puli/style.css.', null, 'style.css'], - ['/webmozart/puli/style.css', null, 'style'], - ['/webmozart/puli/.style.css', null, '.style'], - ['/webmozart/puli/', null, 'puli'], - ['/webmozart/puli', null, 'puli'], - ['/', null, ''], - ['', null, ''], - - ['/webmozart/puli/style.css', 'css', 'style'], - ['/webmozart/puli/style.css', '.css', 'style'], - ['/webmozart/puli/style.css', 'twig', 'style.css'], - ['/webmozart/puli/style.css', '.twig', 'style.css'], - ['/webmozart/puli/style.css', '', 'style.css'], - ['/webmozart/puli/style.css.', '', 'style.css'], - ['/webmozart/puli/style.css.', '.', 'style.css'], - ['/webmozart/puli/style.css.', '.css', 'style.css'], - ['/webmozart/puli/.style.css', 'css', '.style'], - ['/webmozart/puli/.style.css', '.css', '.style'], - ]; + yield ['/webmozart/puli/style.css', 'css', 'style']; + yield ['/webmozart/puli/style.css', '.css', 'style']; + yield ['/webmozart/puli/style.css', 'twig', 'style.css']; + yield ['/webmozart/puli/style.css', '.twig', 'style.css']; + yield ['/webmozart/puli/style.css', '', 'style.css']; + yield ['/webmozart/puli/style.css.', '', 'style.css']; + yield ['/webmozart/puli/style.css.', '.', 'style.css']; + yield ['/webmozart/puli/style.css.', '.css', 'style.css']; + yield ['/webmozart/puli/.style.css', 'css', '.style']; + yield ['/webmozart/puli/.style.css', '.css', '.style']; } /** * @dataProvider provideGetFilenameWithoutExtensionTests */ - public function testGetFilenameWithoutExtension($path, $extension, $filename) + public function testGetFilenameWithoutExtension(string $path, ?string $extension, string $filename): void { $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testGetFilenameWithoutExtensionFailsIfInvalidPath() + public function provideGetExtensionTests(): Generator { - Path::getFilenameWithoutExtension([], '.css'); - } + yield ['/webmozart/puli/style.css.twig', false, 'twig']; + yield ['/webmozart/puli/style.css', false, 'css']; + yield ['/webmozart/puli/style.css.', false, '']; + yield ['/webmozart/puli/', false, '']; + yield ['/webmozart/puli', false, '']; + yield ['/', false, '']; + yield ['', false, '']; - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The extension must be a string or null. Got: array - */ - public function testGetFilenameWithoutExtensionFailsIfInvalidExtension() - { - Path::getFilenameWithoutExtension('/style.css', []); - } - - public function provideGetExtensionTests() - { - $tests = [ - ['/webmozart/puli/style.css.twig', false, 'twig'], - ['/webmozart/puli/style.css', false, 'css'], - ['/webmozart/puli/style.css.', false, ''], - ['/webmozart/puli/', false, ''], - ['/webmozart/puli', false, ''], - ['/', false, ''], - ['', false, ''], - - ['/webmozart/puli/style.CSS', false, 'CSS'], - ['/webmozart/puli/style.CSS', true, 'css'], - ['/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ'], - ]; + yield ['/webmozart/puli/style.CSS', false, 'CSS']; + yield ['/webmozart/puli/style.CSS', true, 'css']; + yield ['/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ']; if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - $tests[] = ['/webmozart/puli/style.ÄÖÜ', true, 'äöü']; + yield ['/webmozart/puli/style.ÄÖÜ', true, 'äöü']; } - - return $tests; } /** * @dataProvider provideGetExtensionTests */ - public function testGetExtension($path, $forceLowerCase, $extension) + public function testGetExtension(string $path, bool $forceLowerCase, string $extension): void { $this->assertSame($extension, Path::getExtension($path, $forceLowerCase)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testGetExtensionFailsIfInvalidPath() - { - Path::getExtension([]); - } - - public function provideHasExtensionTests() - { - $tests = [ - [true, '/webmozart/puli/style.css.twig', null, false], - [true, '/webmozart/puli/style.css', null, false], - [false, '/webmozart/puli/style.css.', null, false], - [false, '/webmozart/puli/', null, false], - [false, '/webmozart/puli', null, false], - [false, '/', null, false], - [false, '', null, false], - - [true, '/webmozart/puli/style.css.twig', 'twig', false], - [false, '/webmozart/puli/style.css.twig', 'css', false], - [true, '/webmozart/puli/style.css', 'css', false], - [true, '/webmozart/puli/style.css', '.css', false], - [true, '/webmozart/puli/style.css.', '', false], - [false, '/webmozart/puli/', 'ext', false], - [false, '/webmozart/puli', 'ext', false], - [false, '/', 'ext', false], - [false, '', 'ext', false], - - [false, '/webmozart/puli/style.css', 'CSS', false], - [true, '/webmozart/puli/style.css', 'CSS', true], - [false, '/webmozart/puli/style.CSS', 'css', false], - [true, '/webmozart/puli/style.CSS', 'css', true], - [true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false], - - [true, '/webmozart/puli/style.css', ['ext', 'css'], false], - [true, '/webmozart/puli/style.css', ['.ext', '.css'], false], - [true, '/webmozart/puli/style.css.', ['ext', ''], false], - [false, '/webmozart/puli/style.css', ['foo', 'bar', ''], false], - [false, '/webmozart/puli/style.css', ['.foo', '.bar', ''], false], - ]; + public function provideHasExtensionTests(): Generator + { + yield [true, '/webmozart/puli/style.css.twig', null, false]; + yield [true, '/webmozart/puli/style.css', null, false]; + yield [false, '/webmozart/puli/style.css.', null, false]; + yield [false, '/webmozart/puli/', null, false]; + yield [false, '/webmozart/puli', null, false]; + yield [false, '/', null, false]; + yield [false, '', null, false]; + + yield [true, '/webmozart/puli/style.css.twig', 'twig', false]; + yield [false, '/webmozart/puli/style.css.twig', 'css', false]; + yield [true, '/webmozart/puli/style.css', 'css', false]; + yield [true, '/webmozart/puli/style.css', '.css', false]; + yield [true, '/webmozart/puli/style.css.', '', false]; + yield [false, '/webmozart/puli/', 'ext', false]; + yield [false, '/webmozart/puli', 'ext', false]; + yield [false, '/', 'ext', false]; + yield [false, '', 'ext', false]; + + yield [false, '/webmozart/puli/style.css', 'CSS', false]; + yield [true, '/webmozart/puli/style.css', 'CSS', true]; + yield [false, '/webmozart/puli/style.CSS', 'css', false]; + yield [true, '/webmozart/puli/style.CSS', 'css', true]; + yield [true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false]; + + yield [true, '/webmozart/puli/style.css', ['ext', 'css'], false]; + yield [true, '/webmozart/puli/style.css', ['.ext', '.css'], false]; + yield [true, '/webmozart/puli/style.css.', ['ext', ''], false]; + yield [false, '/webmozart/puli/style.css', ['foo', 'bar', ''], false]; + yield [false, '/webmozart/puli/style.css', ['.foo', '.bar', ''], false]; if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - $tests[] = [true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true]; - $tests[] = [true, '/webmozart/puli/style.ÄÖÜ', ['äöü'], true]; + yield [true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true]; + yield [true, '/webmozart/puli/style.ÄÖÜ', ['äöü'], true]; } - - return $tests; } /** * @dataProvider provideHasExtensionTests + * + * @param string|string[]|null $extension */ - public function testHasExtension($hasExtension, $path, $extension, $ignoreCase) + public function testHasExtension(bool $hasExtension, string $path, $extension, bool $ignoreCase): void { $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testHasExtensionFailsIfInvalidPath() - { - Path::hasExtension([]); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The extensions must be strings. Got: stdClass - */ - public function testHasExtensionFailsIfInvalidExtension() - { - Path::hasExtension('/style.css', (object) []); - } - - public function provideChangeExtensionTests() + public function provideChangeExtensionTests(): Generator { - return [ - ['/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html'], - ['/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass'], - ['/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass'], - ['/webmozart/puli/style.css', '', '/webmozart/puli/style.'], - ['/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig'], - ['/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.'], - ['/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü'], - ['/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css'], - ['/webmozart/puli/', 'css', '/webmozart/puli/'], - ['/webmozart/puli', 'css', '/webmozart/puli.css'], - ['/', 'css', '/'], - ['', 'css', ''], - ]; + yield ['/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html']; + yield ['/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass']; + yield ['/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass']; + yield ['/webmozart/puli/style.css', '', '/webmozart/puli/style.']; + yield ['/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig']; + yield ['/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.']; + yield ['/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü']; + yield ['/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css']; + yield ['/webmozart/puli/', 'css', '/webmozart/puli/']; + yield ['/webmozart/puli', 'css', '/webmozart/puli.css']; + yield ['/', 'css', '/']; + yield ['', 'css', '']; } /** * @dataProvider provideChangeExtensionTests */ - public function testChangeExtension($path, $extension, $pathExpected) + public function testChangeExtension(string $path, string $extension, string $pathExpected): void { static $call = 0; $this->assertSame($pathExpected, Path::changeExtension($path, $extension)); ++$call; } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testChangeExtensionFailsIfInvalidPath() - { - Path::changeExtension([], '.sass'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The extension must be a string. Got: array - */ - public function testChangeExtensionFailsIfInvalidExtension() - { - Path::changeExtension('/style.css', []); - } - - public function provideIsAbsolutePathTests() + public function provideIsAbsolutePathTests(): Generator { - return [ - ['/css/style.css', true], - ['/', true], - ['css/style.css', false], - ['', false], + yield ['/css/style.css', true]; + yield ['/', true]; + yield ['css/style.css', false]; + yield ['', false]; - ['\\css\\style.css', true], - ['\\', true], - ['css\\style.css', false], + yield ['\\css\\style.css', true]; + yield ['\\', true]; + yield ['css\\style.css', false]; - ['C:/css/style.css', true], - ['D:/', true], + yield ['C:/css/style.css', true]; + yield ['D:/', true]; - ['E:\\css\\style.css', true], - ['F:\\', true], + yield ['E:\\css\\style.css', true]; + yield ['F:\\', true]; - ['phar:///css/style.css', true], - ['phar:///', true], + yield ['phar:///css/style.css', true]; + yield ['phar:///', true]; - // Windows special case - ['C:', true], + // Windows special case + yield ['C:', true]; - // Not considered absolute - ['C:css/style.css', false], - ]; + // Not considered absolute + yield ['C:css/style.css', false]; } /** * @dataProvider provideIsAbsolutePathTests */ - public function testIsAbsolute($path, $isAbsolute) + public function testIsAbsolute(string $path, bool $isAbsolute): void { $this->assertSame($isAbsolute, Path::isAbsolute($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testIsAbsoluteFailsIfInvalidPath() - { - Path::isAbsolute([]); - } - /** * @dataProvider provideIsAbsolutePathTests */ - public function testIsRelative($path, $isAbsolute) + public function testIsRelative(string $path, bool $isAbsolute): void { $this->assertSame(!$isAbsolute, Path::isRelative($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testIsRelativeFailsIfInvalidPath() + public function provideGetRootTests(): Generator { - Path::isRelative([]); - } + yield ['/css/style.css', '/']; + yield ['/', '/']; + yield ['css/style.css', '']; + yield ['', '']; - public function provideGetRootTests() - { - return [ - ['/css/style.css', '/'], - ['/', '/'], - ['css/style.css', ''], - ['', ''], - - ['\\css\\style.css', '/'], - ['\\', '/'], - ['css\\style.css', ''], - - ['C:/css/style.css', 'C:/'], - ['C:/', 'C:/'], - ['C:', 'C:/'], - - ['D:\\css\\style.css', 'D:/'], - ['D:\\', 'D:/'], - - ['phar:///css/style.css', 'phar:///'], - ['phar:///', 'phar:///'], - - ['phar://C:/css/style.css', 'phar://C:/'], - ['phar://C:/', 'phar://C:/'], - ['phar://C:', 'phar://C:/'], - ]; + yield ['\\css\\style.css', '/']; + yield ['\\', '/']; + yield ['css\\style.css', '']; + + yield ['C:/css/style.css', 'C:/']; + yield ['C:/', 'C:/']; + yield ['C:', 'C:/']; + + yield ['D:\\css\\style.css', 'D:/']; + yield ['D:\\', 'D:/']; + + yield ['phar:///css/style.css', 'phar:///']; + yield ['phar:///', 'phar:///']; + + yield ['phar://C:/css/style.css', 'phar://C:/']; + yield ['phar://C:/', 'phar://C:/']; + yield ['phar://C:', 'phar://C:/']; } /** * @dataProvider provideGetRootTests */ - public function testGetRoot($path, $root) + public function testGetRoot(string $path, string $root): void { $this->assertSame($root, Path::getRoot($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testGetRootFailsIfInvalidPath() + public function providePathTests(): Generator { - Path::getRoot([]); - } + // relative to absolute path + yield ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; + yield ['../css/style.css', '/webmozart/puli', '/webmozart/css/style.css']; + yield ['../../css/style.css', '/webmozart/puli', '/css/style.css']; - public function providePathTests() - { - return [ - // relative to absolute path - ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], - ['../css/style.css', '/webmozart/puli', '/webmozart/css/style.css'], - ['../../css/style.css', '/webmozart/puli', '/css/style.css'], - - // relative to root - ['css/style.css', '/', '/css/style.css'], - ['css/style.css', 'C:', 'C:/css/style.css'], - ['css/style.css', 'C:/', 'C:/css/style.css'], - - // same sub directories in different base directories - ['../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css'], - - ['', '/webmozart/puli', '/webmozart/puli'], - ['..', '/webmozart/puli', '/webmozart'], - ]; + // relative to root + yield ['css/style.css', '/', '/css/style.css']; + yield ['css/style.css', 'C:', 'C:/css/style.css']; + yield ['css/style.css', 'C:/', 'C:/css/style.css']; + + // same sub directories in different base directories + yield ['../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css']; + + yield ['', '/webmozart/puli', '/webmozart/puli']; + yield ['..', '/webmozart/puli', '/webmozart']; } - public function provideMakeAbsoluteTests() + public function provideMakeAbsoluteTests(): Generator { - return array_merge($this->providePathTests(), [ - // collapse dots - ['css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], - ['css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css'], - ['css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css'], - ['css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css'], - ['./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css'], - - ['css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'], - ['css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], - ['css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], - ['css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css'], - ['.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css'], - - // collapse dots on root - ['./css/style.css', '/', '/css/style.css'], - ['../css/style.css', '/', '/css/style.css'], - ['../css/./style.css', '/', '/css/style.css'], - ['../css/../style.css', '/', '/style.css'], - ['../css/./../style.css', '/', '/style.css'], - ['../css/.././style.css', '/', '/style.css'], - - ['.\\css\\style.css', '\\', '/css/style.css'], - ['..\\css\\style.css', '\\', '/css/style.css'], - ['..\\css\\.\\style.css', '\\', '/css/style.css'], - ['..\\css\\..\\style.css', '\\', '/style.css'], - ['..\\css\\.\\..\\style.css', '\\', '/style.css'], - ['..\\css\\..\\.\\style.css', '\\', '/style.css'], - - ['./css/style.css', 'C:/', 'C:/css/style.css'], - ['../css/style.css', 'C:/', 'C:/css/style.css'], - ['../css/./style.css', 'C:/', 'C:/css/style.css'], - ['../css/../style.css', 'C:/', 'C:/style.css'], - ['../css/./../style.css', 'C:/', 'C:/style.css'], - ['../css/.././style.css', 'C:/', 'C:/style.css'], - - ['.\\css\\style.css', 'C:\\', 'C:/css/style.css'], - ['..\\css\\style.css', 'C:\\', 'C:/css/style.css'], - ['..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css'], - ['..\\css\\..\\style.css', 'C:\\', 'C:/style.css'], - ['..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css'], - ['..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css'], - - ['./css/style.css', 'phar:///', 'phar:///css/style.css'], - ['../css/style.css', 'phar:///', 'phar:///css/style.css'], - ['../css/./style.css', 'phar:///', 'phar:///css/style.css'], - ['../css/../style.css', 'phar:///', 'phar:///style.css'], - ['../css/./../style.css', 'phar:///', 'phar:///style.css'], - ['../css/.././style.css', 'phar:///', 'phar:///style.css'], - - ['./css/style.css', 'phar://C:/', 'phar://C:/css/style.css'], - ['../css/style.css', 'phar://C:/', 'phar://C:/css/style.css'], - ['../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css'], - ['../css/../style.css', 'phar://C:/', 'phar://C:/style.css'], - ['../css/./../style.css', 'phar://C:/', 'phar://C:/style.css'], - ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css'], - - // absolute paths - ['/css/style.css', '/webmozart/puli', '/css/style.css'], - ['\\css\\style.css', '/webmozart/puli', '/css/style.css'], - ['C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css'], - ['D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css'], - ]); + foreach ($this->providePathTests() as $set) { + yield $set; + } + + // collapse dots + yield ['css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; + yield ['css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css']; + yield ['css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css']; + yield ['css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css']; + yield ['./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; + + yield ['css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css']; + yield ['css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; + yield ['css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; + yield ['css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; + yield ['.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css']; + + // collapse dots on root + yield ['./css/style.css', '/', '/css/style.css']; + yield ['../css/style.css', '/', '/css/style.css']; + yield ['../css/./style.css', '/', '/css/style.css']; + yield ['../css/../style.css', '/', '/style.css']; + yield ['../css/./../style.css', '/', '/style.css']; + yield ['../css/.././style.css', '/', '/style.css']; + + yield ['.\\css\\style.css', '\\', '/css/style.css']; + yield ['..\\css\\style.css', '\\', '/css/style.css']; + yield ['..\\css\\.\\style.css', '\\', '/css/style.css']; + yield ['..\\css\\..\\style.css', '\\', '/style.css']; + yield ['..\\css\\.\\..\\style.css', '\\', '/style.css']; + yield ['..\\css\\..\\.\\style.css', '\\', '/style.css']; + + yield ['./css/style.css', 'C:/', 'C:/css/style.css']; + yield ['../css/style.css', 'C:/', 'C:/css/style.css']; + yield ['../css/./style.css', 'C:/', 'C:/css/style.css']; + yield ['../css/../style.css', 'C:/', 'C:/style.css']; + yield ['../css/./../style.css', 'C:/', 'C:/style.css']; + yield ['../css/.././style.css', 'C:/', 'C:/style.css']; + + yield ['.\\css\\style.css', 'C:\\', 'C:/css/style.css']; + yield ['..\\css\\style.css', 'C:\\', 'C:/css/style.css']; + yield ['..\\css\\.\\style.css', 'C:\\', 'C:/css/style.css']; + yield ['..\\css\\..\\style.css', 'C:\\', 'C:/style.css']; + yield ['..\\css\\.\\..\\style.css', 'C:\\', 'C:/style.css']; + yield ['..\\css\\..\\.\\style.css', 'C:\\', 'C:/style.css']; + + yield ['./css/style.css', 'phar:///', 'phar:///css/style.css']; + yield ['../css/style.css', 'phar:///', 'phar:///css/style.css']; + yield ['../css/./style.css', 'phar:///', 'phar:///css/style.css']; + yield ['../css/../style.css', 'phar:///', 'phar:///style.css']; + yield ['../css/./../style.css', 'phar:///', 'phar:///style.css']; + yield ['../css/.././style.css', 'phar:///', 'phar:///style.css']; + + yield ['./css/style.css', 'phar://C:/', 'phar://C:/css/style.css']; + yield ['../css/style.css', 'phar://C:/', 'phar://C:/css/style.css']; + yield ['../css/./style.css', 'phar://C:/', 'phar://C:/css/style.css']; + yield ['../css/../style.css', 'phar://C:/', 'phar://C:/style.css']; + yield ['../css/./../style.css', 'phar://C:/', 'phar://C:/style.css']; + yield ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css']; + + // absolute paths + yield ['/css/style.css', '/webmozart/puli', '/css/style.css']; + yield ['\\css\\style.css', '/webmozart/puli', '/css/style.css']; + yield ['C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css']; + yield ['D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css']; } /** * @dataProvider provideMakeAbsoluteTests */ - public function testMakeAbsolute($relativePath, $basePath, $absolutePath) + public function testMakeAbsolute(string $relativePath, string $basePath, string $absolutePath): void { $this->assertSame($absolutePath, Path::makeAbsolute($relativePath, $basePath)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testMakeAbsoluteFailsIfInvalidPath() - { - Path::makeAbsolute([], '/webmozart/puli'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a non-empty string. Got: array - */ - public function testMakeAbsoluteFailsIfInvalidBasePath() + public function testMakeAbsoluteFailsIfBasePathNotAbsolute(): void { - Path::makeAbsolute('css/style.css', []); - } + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The base path "webmozart/puli" is not an absolute path.'); - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path "webmozart/puli" is not an absolute path. - */ - public function testMakeAbsoluteFailsIfBasePathNotAbsolute() - { Path::makeAbsolute('css/style.css', 'webmozart/puli'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a non-empty string. Got: "" - */ - public function testMakeAbsoluteFailsIfBasePathEmpty() + public function testMakeAbsoluteFailsIfBasePathEmpty(): void { + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The base path must be a non-empty string. Got: ""'); + Path::makeAbsolute('css/style.css', ''); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a non-empty string. Got: NULL - */ - public function testMakeAbsoluteFailsIfBasePathNull() + public function provideAbsolutePathsWithDifferentRoots(): Generator { - Path::makeAbsolute('css/style.css', null); - } + yield ['C:/css/style.css', '/webmozart/puli']; + yield ['C:/css/style.css', '\\webmozart\\puli']; + yield ['C:\\css\\style.css', '/webmozart/puli']; + yield ['C:\\css\\style.css', '\\webmozart\\puli']; - public function provideAbsolutePathsWithDifferentRoots() - { - return [ - ['C:/css/style.css', '/webmozart/puli'], - ['C:/css/style.css', '\\webmozart\\puli'], - ['C:\\css\\style.css', '/webmozart/puli'], - ['C:\\css\\style.css', '\\webmozart\\puli'], - - ['/css/style.css', 'C:/webmozart/puli'], - ['/css/style.css', 'C:\\webmozart\\puli'], - ['\\css\\style.css', 'C:/webmozart/puli'], - ['\\css\\style.css', 'C:\\webmozart\\puli'], - - ['D:/css/style.css', 'C:/webmozart/puli'], - ['D:/css/style.css', 'C:\\webmozart\\puli'], - ['D:\\css\\style.css', 'C:/webmozart/puli'], - ['D:\\css\\style.css', 'C:\\webmozart\\puli'], - - ['phar:///css/style.css', '/webmozart/puli'], - ['/css/style.css', 'phar:///webmozart/puli'], - - ['phar://C:/css/style.css', 'C:/webmozart/puli'], - ['phar://C:/css/style.css', 'C:\\webmozart\\puli'], - ['phar://C:\\css\\style.css', 'C:/webmozart/puli'], - ['phar://C:\\css\\style.css', 'C:\\webmozart\\puli'], - ]; + yield ['/css/style.css', 'C:/webmozart/puli']; + yield ['/css/style.css', 'C:\\webmozart\\puli']; + yield ['\\css\\style.css', 'C:/webmozart/puli']; + yield ['\\css\\style.css', 'C:\\webmozart\\puli']; + + yield ['D:/css/style.css', 'C:/webmozart/puli']; + yield ['D:/css/style.css', 'C:\\webmozart\\puli']; + yield ['D:\\css\\style.css', 'C:/webmozart/puli']; + yield ['D:\\css\\style.css', 'C:\\webmozart\\puli']; + + yield ['phar:///css/style.css', '/webmozart/puli']; + yield ['/css/style.css', 'phar:///webmozart/puli']; + + yield ['phar://C:/css/style.css', 'C:/webmozart/puli']; + yield ['phar://C:/css/style.css', 'C:\\webmozart\\puli']; + yield ['phar://C:\\css\\style.css', 'C:/webmozart/puli']; + yield ['phar://C:\\css\\style.css', 'C:\\webmozart\\puli']; } /** * @dataProvider provideAbsolutePathsWithDifferentRoots */ - public function testMakeAbsoluteDoesNotFailIfDifferentRoot($basePath, $absolutePath) + public function testMakeAbsoluteDoesNotFailIfDifferentRoot(string $basePath, string $absolutePath): void { // If a path in partition D: is passed, but $basePath is in partition // C:, the path should be returned unchanged $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath)); } - public function provideMakeRelativeTests() + public function provideMakeRelativeTests(): Generator { - $paths = array_map(function (array $arguments) { - return [$arguments[2], $arguments[1], $arguments[0]]; - }, $this->providePathTests()); - - return array_merge($paths, [ - ['/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css'], - ['/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css'], - ['/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css'], - ['/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css'], - ['/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css'], - ['/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css'], - ['/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css'], - ['/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css'], - ['/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css'], - ['/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css'], - - // first argument shorter than second - ['/css', '/webmozart/puli', '../../css'], - - // second argument shorter than first - ['/webmozart/puli', '/css', '../webmozart/puli'], - - ['\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css'], - ['\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css'], - ['\\css\\style.css', '\\webmozart\\puli', '../../css/style.css'], - - ['C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css'], - ['C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css'], - ['C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css'], - - ['C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css'], - ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css'], - ['C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css'], - - ['phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css'], - ['phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css'], - ['phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css'], - - ['phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css'], - ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css'], - ['phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css'], - - // already relative + already in root basepath - ['../style.css', '/', 'style.css'], - ['./style.css', '/', 'style.css'], - ['../../style.css', '/', 'style.css'], - ['..\\style.css', 'C:\\', 'style.css'], - ['.\\style.css', 'C:\\', 'style.css'], - ['..\\..\\style.css', 'C:\\', 'style.css'], - ['../style.css', 'C:/', 'style.css'], - ['./style.css', 'C:/', 'style.css'], - ['../../style.css', 'C:/', 'style.css'], - ['..\\style.css', '\\', 'style.css'], - ['.\\style.css', '\\', 'style.css'], - ['..\\..\\style.css', '\\', 'style.css'], - ['../style.css', 'phar:///', 'style.css'], - ['./style.css', 'phar:///', 'style.css'], - ['../../style.css', 'phar:///', 'style.css'], - ['..\\style.css', 'phar://C:\\', 'style.css'], - ['.\\style.css', 'phar://C:\\', 'style.css'], - ['..\\..\\style.css', 'phar://C:\\', 'style.css'], - - ['css/../style.css', '/', 'style.css'], - ['css/./style.css', '/', 'css/style.css'], - ['css\\..\\style.css', 'C:\\', 'style.css'], - ['css\\.\\style.css', 'C:\\', 'css/style.css'], - ['css/../style.css', 'C:/', 'style.css'], - ['css/./style.css', 'C:/', 'css/style.css'], - ['css\\..\\style.css', '\\', 'style.css'], - ['css\\.\\style.css', '\\', 'css/style.css'], - ['css/../style.css', 'phar:///', 'style.css'], - ['css/./style.css', 'phar:///', 'css/style.css'], - ['css\\..\\style.css', 'phar://C:\\', 'style.css'], - ['css\\.\\style.css', 'phar://C:\\', 'css/style.css'], - - // already relative - ['css/style.css', '/webmozart/puli', 'css/style.css'], - ['css\\style.css', '\\webmozart\\puli', 'css/style.css'], - - // both relative - ['css/style.css', 'webmozart/puli', '../../css/style.css'], - ['css\\style.css', 'webmozart\\puli', '../../css/style.css'], - - // relative to empty - ['css/style.css', '', 'css/style.css'], - ['css\\style.css', '', 'css/style.css'], - - // different slashes in path and base path - ['/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css'], - ['\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css'], - ]); + foreach ($this->providePathTests() as $set) { + yield [$set[2], $set[1], $set[0]]; + } + + yield ['/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css']; + yield ['/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css']; + yield ['/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css']; + yield ['/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css']; + yield ['/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css']; + yield ['/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css']; + yield ['/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css']; + yield ['/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css']; + yield ['/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css']; + yield ['/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css']; + + // first argument shorter than second + yield ['/css', '/webmozart/puli', '../../css']; + + // second argument shorter than first + yield ['/webmozart/puli', '/css', '../webmozart/puli']; + + yield ['\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css']; + yield ['\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css']; + yield ['\\css\\style.css', '\\webmozart\\puli', '../../css/style.css']; + + yield ['C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css']; + yield ['C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css']; + yield ['C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css']; + + yield ['C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css']; + yield ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css']; + yield ['C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css']; + + yield ['phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css']; + yield ['phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css']; + yield ['phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css']; + + yield ['phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css']; + yield ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css']; + yield ['phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css']; + + // already relative + already in root basepath + yield ['../style.css', '/', 'style.css']; + yield ['./style.css', '/', 'style.css']; + yield ['../../style.css', '/', 'style.css']; + yield ['..\\style.css', 'C:\\', 'style.css']; + yield ['.\\style.css', 'C:\\', 'style.css']; + yield ['..\\..\\style.css', 'C:\\', 'style.css']; + yield ['../style.css', 'C:/', 'style.css']; + yield ['./style.css', 'C:/', 'style.css']; + yield ['../../style.css', 'C:/', 'style.css']; + yield ['..\\style.css', '\\', 'style.css']; + yield ['.\\style.css', '\\', 'style.css']; + yield ['..\\..\\style.css', '\\', 'style.css']; + yield ['../style.css', 'phar:///', 'style.css']; + yield ['./style.css', 'phar:///', 'style.css']; + yield ['../../style.css', 'phar:///', 'style.css']; + yield ['..\\style.css', 'phar://C:\\', 'style.css']; + yield ['.\\style.css', 'phar://C:\\', 'style.css']; + yield ['..\\..\\style.css', 'phar://C:\\', 'style.css']; + + yield ['css/../style.css', '/', 'style.css']; + yield ['css/./style.css', '/', 'css/style.css']; + yield ['css\\..\\style.css', 'C:\\', 'style.css']; + yield ['css\\.\\style.css', 'C:\\', 'css/style.css']; + yield ['css/../style.css', 'C:/', 'style.css']; + yield ['css/./style.css', 'C:/', 'css/style.css']; + yield ['css\\..\\style.css', '\\', 'style.css']; + yield ['css\\.\\style.css', '\\', 'css/style.css']; + yield ['css/../style.css', 'phar:///', 'style.css']; + yield ['css/./style.css', 'phar:///', 'css/style.css']; + yield ['css\\..\\style.css', 'phar://C:\\', 'style.css']; + yield ['css\\.\\style.css', 'phar://C:\\', 'css/style.css']; + + // already relative + yield ['css/style.css', '/webmozart/puli', 'css/style.css']; + yield ['css\\style.css', '\\webmozart\\puli', 'css/style.css']; + + // both relative + yield ['css/style.css', 'webmozart/puli', '../../css/style.css']; + yield ['css\\style.css', 'webmozart\\puli', '../../css/style.css']; + + // relative to empty + yield ['css/style.css', '', 'css/style.css']; + yield ['css\\style.css', '', 'css/style.css']; + + // different slashes in path and base path + yield ['/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css']; + yield ['\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css']; } /** * @dataProvider provideMakeRelativeTests */ - public function testMakeRelative($absolutePath, $basePath, $relativePath) + public function testMakeRelative(string $absolutePath, string $basePath, string $relativePath): void { $this->assertSame($relativePath, Path::makeRelative($absolutePath, $basePath)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testMakeRelativeFailsIfInvalidPath() + public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute(): void { - Path::makeRelative([], '/webmozart/puli'); - } + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "webmozart/puli". You should provide an absolute base path instead.'); - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a string. Got: array - */ - public function testMakeRelativeFailsIfInvalidBasePath() - { - Path::makeRelative('/webmozart/puli/css/style.css', []); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "webmozart/puli". You should provide an absolute base path instead. - */ - public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute() - { Path::makeRelative('/webmozart/puli/css/style.css', 'webmozart/puli'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead. - */ - public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty() + public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty(): void { - Path::makeRelative('/webmozart/puli/css/style.css', ''); - } + + $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.'); - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a string. Got: NULL - */ - public function testMakeRelativeFailsIfBasePathNull() - { - Path::makeRelative('/webmozart/puli/css/style.css', null); + Path::makeRelative('/webmozart/puli/css/style.css', ''); } /** * @dataProvider provideAbsolutePathsWithDifferentRoots - * @expectedException \InvalidArgumentException */ - public function testMakeRelativeFailsIfDifferentRoot($absolutePath, $basePath) + public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, string $basePath): void { + $this->expectException(\InvalidArgumentException::class); + Path::makeRelative($absolutePath, $basePath); } - public function provideIsLocalTests() + public function provideIsLocalTests(): Generator { - return [ - ['/bg.png', true], - ['bg.png', true], - ['http://example.com/bg.png', false], - ['http://example.com', false], - ['', false], - ]; + yield ['/bg.png', true]; + yield ['bg.png', true]; + yield ['http://example.com/bg.png', false]; + yield ['http://example.com', false]; + yield ['', false]; } /** * @dataProvider provideIsLocalTests */ - public function testIsLocal($path, $isLocal) + public function testIsLocal(string $path, bool $isLocal): void { $this->assertSame($isLocal, Path::isLocal($path)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testIsLocalFailsIfInvalidPath() - { - Path::isLocal([]); - } - - public function provideGetLongestCommonBasePathTests() - { - return [ - // same paths - [['/base/path', '/base/path'], '/base/path'], - [['C:/base/path', 'C:/base/path'], 'C:/base/path'], - [['C:\\base\\path', 'C:\\base\\path'], 'C:/base/path'], - [['C:/base/path', 'C:\\base\\path'], 'C:/base/path'], - [['phar:///base/path', 'phar:///base/path'], 'phar:///base/path'], - [['phar://C:/base/path', 'phar://C:/base/path'], 'phar://C:/base/path'], - - // trailing slash - [['/base/path/', '/base/path'], '/base/path'], - [['C:/base/path/', 'C:/base/path'], 'C:/base/path'], - [['C:\\base\\path\\', 'C:\\base\\path'], 'C:/base/path'], - [['C:/base/path/', 'C:\\base\\path'], 'C:/base/path'], - [['phar:///base/path/', 'phar:///base/path'], 'phar:///base/path'], - [['phar://C:/base/path/', 'phar://C:/base/path'], 'phar://C:/base/path'], - - [['/base/path', '/base/path/'], '/base/path'], - [['C:/base/path', 'C:/base/path/'], 'C:/base/path'], - [['C:\\base\\path', 'C:\\base\\path\\'], 'C:/base/path'], - [['C:/base/path', 'C:\\base\\path\\'], 'C:/base/path'], - [['phar:///base/path', 'phar:///base/path/'], 'phar:///base/path'], - [['phar://C:/base/path', 'phar://C:/base/path/'], 'phar://C:/base/path'], - - // first in second - [['/base/path/sub', '/base/path'], '/base/path'], - [['C:/base/path/sub', 'C:/base/path'], 'C:/base/path'], - [['C:\\base\\path\\sub', 'C:\\base\\path'], 'C:/base/path'], - [['C:/base/path/sub', 'C:\\base\\path'], 'C:/base/path'], - [['phar:///base/path/sub', 'phar:///base/path'], 'phar:///base/path'], - [['phar://C:/base/path/sub', 'phar://C:/base/path'], 'phar://C:/base/path'], - - // second in first - [['/base/path', '/base/path/sub'], '/base/path'], - [['C:/base/path', 'C:/base/path/sub'], 'C:/base/path'], - [['C:\\base\\path', 'C:\\base\\path\\sub'], 'C:/base/path'], - [['C:/base/path', 'C:\\base\\path\\sub'], 'C:/base/path'], - [['phar:///base/path', 'phar:///base/path/sub'], 'phar:///base/path'], - [['phar://C:/base/path', 'phar://C:/base/path/sub'], 'phar://C:/base/path'], - - // first is prefix - [['/base/path/di', '/base/path/dir'], '/base/path'], - [['C:/base/path/di', 'C:/base/path/dir'], 'C:/base/path'], - [['C:\\base\\path\\di', 'C:\\base\\path\\dir'], 'C:/base/path'], - [['C:/base/path/di', 'C:\\base\\path\\dir'], 'C:/base/path'], - [['phar:///base/path/di', 'phar:///base/path/dir'], 'phar:///base/path'], - [['phar://C:/base/path/di', 'phar://C:/base/path/dir'], 'phar://C:/base/path'], - - // second is prefix - [['/base/path/dir', '/base/path/di'], '/base/path'], - [['C:/base/path/dir', 'C:/base/path/di'], 'C:/base/path'], - [['C:\\base\\path\\dir', 'C:\\base\\path\\di'], 'C:/base/path'], - [['C:/base/path/dir', 'C:\\base\\path\\di'], 'C:/base/path'], - [['phar:///base/path/dir', 'phar:///base/path/di'], 'phar:///base/path'], - [['phar://C:/base/path/dir', 'phar://C:/base/path/di'], 'phar://C:/base/path'], - - // root is common base path - [['/first', '/second'], '/'], - [['C:/first', 'C:/second'], 'C:/'], - [['C:\\first', 'C:\\second'], 'C:/'], - [['C:/first', 'C:\\second'], 'C:/'], - [['phar:///first', 'phar:///second'], 'phar:///'], - [['phar://C:/first', 'phar://C:/second'], 'phar://C:/'], - - // windows vs unix - [['/base/path', 'C:/base/path'], null], - [['C:/base/path', '/base/path'], null], - [['/base/path', 'C:\\base\\path'], null], - [['phar:///base/path', 'phar://C:/base/path'], null], - - // different partitions - [['C:/base/path', 'D:/base/path'], null], - [['C:/base/path', 'D:\\base\\path'], null], - [['C:\\base\\path', 'D:\\base\\path'], null], - [['phar://C:/base/path', 'phar://D:/base/path'], null], - - // three paths - [['/base/path/foo', '/base/path', '/base/path/bar'], '/base/path'], - [['C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'], 'C:/base/path'], - [['C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'], 'C:/base/path'], - [['C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'], 'C:/base/path'], - [['phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'], 'phar:///base/path'], - [['phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'], 'phar://C:/base/path'], - - // three paths with root - [['/base/path/foo', '/', '/base/path/bar'], '/'], - [['C:/base/path/foo', 'C:/', 'C:/base/path/bar'], 'C:/'], - [['C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'], 'C:/'], - [['C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'], 'C:/'], - [['phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'], 'phar:///'], - [['phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'], 'phar://C:/'], - - // three paths, different roots - [['/base/path/foo', 'C:/base/path', '/base/path/bar'], null], - [['/base/path/foo', 'C:\\base\\path', '/base/path/bar'], null], - [['C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'], null], - [['C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'], null], - [['C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'], null], - [['phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'], null], - [['phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'], null], - - // only one path - [['/base/path'], '/base/path'], - [['C:/base/path'], 'C:/base/path'], - [['C:\\base\\path'], 'C:/base/path'], - [['phar:///base/path'], 'phar:///base/path'], - [['phar://C:/base/path'], 'phar://C:/base/path'], - ]; + public function provideGetLongestCommonBasePathTests(): Generator + { + // same paths + yield [['/base/path', '/base/path'], '/base/path']; + yield [['C:/base/path', 'C:/base/path'], 'C:/base/path']; + yield [['C:\\base\\path', 'C:\\base\\path'], 'C:/base/path']; + yield [['C:/base/path', 'C:\\base\\path'], 'C:/base/path']; + yield [['phar:///base/path', 'phar:///base/path'], 'phar:///base/path']; + yield [['phar://C:/base/path', 'phar://C:/base/path'], 'phar://C:/base/path']; + + // trailing slash + yield [['/base/path/', '/base/path'], '/base/path']; + yield [['C:/base/path/', 'C:/base/path'], 'C:/base/path']; + yield [['C:\\base\\path\\', 'C:\\base\\path'], 'C:/base/path']; + yield [['C:/base/path/', 'C:\\base\\path'], 'C:/base/path']; + yield [['phar:///base/path/', 'phar:///base/path'], 'phar:///base/path']; + yield [['phar://C:/base/path/', 'phar://C:/base/path'], 'phar://C:/base/path']; + + yield [['/base/path', '/base/path/'], '/base/path']; + yield [['C:/base/path', 'C:/base/path/'], 'C:/base/path']; + yield [['C:\\base\\path', 'C:\\base\\path\\'], 'C:/base/path']; + yield [['C:/base/path', 'C:\\base\\path\\'], 'C:/base/path']; + yield [['phar:///base/path', 'phar:///base/path/'], 'phar:///base/path']; + yield [['phar://C:/base/path', 'phar://C:/base/path/'], 'phar://C:/base/path']; + + // first in second + yield [['/base/path/sub', '/base/path'], '/base/path']; + yield [['C:/base/path/sub', 'C:/base/path'], 'C:/base/path']; + yield [['C:\\base\\path\\sub', 'C:\\base\\path'], 'C:/base/path']; + yield [['C:/base/path/sub', 'C:\\base\\path'], 'C:/base/path']; + yield [['phar:///base/path/sub', 'phar:///base/path'], 'phar:///base/path']; + yield [['phar://C:/base/path/sub', 'phar://C:/base/path'], 'phar://C:/base/path']; + + // second in first + yield [['/base/path', '/base/path/sub'], '/base/path']; + yield [['C:/base/path', 'C:/base/path/sub'], 'C:/base/path']; + yield [['C:\\base\\path', 'C:\\base\\path\\sub'], 'C:/base/path']; + yield [['C:/base/path', 'C:\\base\\path\\sub'], 'C:/base/path']; + yield [['phar:///base/path', 'phar:///base/path/sub'], 'phar:///base/path']; + yield [['phar://C:/base/path', 'phar://C:/base/path/sub'], 'phar://C:/base/path']; + + // first is prefix + yield [['/base/path/di', '/base/path/dir'], '/base/path']; + yield [['C:/base/path/di', 'C:/base/path/dir'], 'C:/base/path']; + yield [['C:\\base\\path\\di', 'C:\\base\\path\\dir'], 'C:/base/path']; + yield [['C:/base/path/di', 'C:\\base\\path\\dir'], 'C:/base/path']; + yield [['phar:///base/path/di', 'phar:///base/path/dir'], 'phar:///base/path']; + yield [['phar://C:/base/path/di', 'phar://C:/base/path/dir'], 'phar://C:/base/path']; + + // second is prefix + yield [['/base/path/dir', '/base/path/di'], '/base/path']; + yield [['C:/base/path/dir', 'C:/base/path/di'], 'C:/base/path']; + yield [['C:\\base\\path\\dir', 'C:\\base\\path\\di'], 'C:/base/path']; + yield [['C:/base/path/dir', 'C:\\base\\path\\di'], 'C:/base/path']; + yield [['phar:///base/path/dir', 'phar:///base/path/di'], 'phar:///base/path']; + yield [['phar://C:/base/path/dir', 'phar://C:/base/path/di'], 'phar://C:/base/path']; + + // root is common base path + yield [['/first', '/second'], '/']; + yield [['C:/first', 'C:/second'], 'C:/']; + yield [['C:\\first', 'C:\\second'], 'C:/']; + yield [['C:/first', 'C:\\second'], 'C:/']; + yield [['phar:///first', 'phar:///second'], 'phar:///']; + yield [['phar://C:/first', 'phar://C:/second'], 'phar://C:/']; + + // windows vs unix + yield [['/base/path', 'C:/base/path'], null]; + yield [['C:/base/path', '/base/path'], null]; + yield [['/base/path', 'C:\\base\\path'], null]; + yield [['phar:///base/path', 'phar://C:/base/path'], null]; + + // different partitions + yield [['C:/base/path', 'D:/base/path'], null]; + yield [['C:/base/path', 'D:\\base\\path'], null]; + yield [['C:\\base\\path', 'D:\\base\\path'], null]; + yield [['phar://C:/base/path', 'phar://D:/base/path'], null]; + + // three paths + yield [['/base/path/foo', '/base/path', '/base/path/bar'], '/base/path']; + yield [['C:/base/path/foo', 'C:/base/path', 'C:/base/path/bar'], 'C:/base/path']; + yield [['C:\\base\\path\\foo', 'C:\\base\\path', 'C:\\base\\path\\bar'], 'C:/base/path']; + yield [['C:/base/path//foo', 'C:/base/path', 'C:\\base\\path\\bar'], 'C:/base/path']; + yield [['phar:///base/path/foo', 'phar:///base/path', 'phar:///base/path/bar'], 'phar:///base/path']; + yield [['phar://C:/base/path/foo', 'phar://C:/base/path', 'phar://C:/base/path/bar'], 'phar://C:/base/path']; + + // three paths with root + yield [['/base/path/foo', '/', '/base/path/bar'], '/']; + yield [['C:/base/path/foo', 'C:/', 'C:/base/path/bar'], 'C:/']; + yield [['C:\\base\\path\\foo', 'C:\\', 'C:\\base\\path\\bar'], 'C:/']; + yield [['C:/base/path//foo', 'C:/', 'C:\\base\\path\\bar'], 'C:/']; + yield [['phar:///base/path/foo', 'phar:///', 'phar:///base/path/bar'], 'phar:///']; + yield [['phar://C:/base/path/foo', 'phar://C:/', 'phar://C:/base/path/bar'], 'phar://C:/']; + + // three paths, different roots + yield [['/base/path/foo', 'C:/base/path', '/base/path/bar'], null]; + yield [['/base/path/foo', 'C:\\base\\path', '/base/path/bar'], null]; + yield [['C:/base/path/foo', 'D:/base/path', 'C:/base/path/bar'], null]; + yield [['C:\\base\\path\\foo', 'D:\\base\\path', 'C:\\base\\path\\bar'], null]; + yield [['C:/base/path//foo', 'D:/base/path', 'C:\\base\\path\\bar'], null]; + yield [['phar:///base/path/foo', 'phar://C:/base/path', 'phar:///base/path/bar'], null]; + yield [['phar://C:/base/path/foo', 'phar://D:/base/path', 'phar://C:/base/path/bar'], null]; + + // only one path + yield [['/base/path'], '/base/path']; + yield [['C:/base/path'], 'C:/base/path']; + yield [['C:\\base\\path'], 'C:/base/path']; + yield [['phar:///base/path'], 'phar:///base/path']; + yield [['phar://C:/base/path'], 'phar://C:/base/path']; } /** * @dataProvider provideGetLongestCommonBasePathTests + * + * @param string[] $paths */ - public function testGetLongestCommonBasePath(array $paths, $basePath) + public function testGetLongestCommonBasePath(array $paths, ?string $basePath): void { $this->assertSame($basePath, Path::getLongestCommonBasePath($paths)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The paths must be strings. Got: array - */ - public function testGetLongestCommonBasePathFailsIfInvalidPath() - { - Path::getLongestCommonBasePath([[]]); - } - - public function provideIsBasePathTests() - { - return [ - // same paths - ['/base/path', '/base/path', true], - ['C:/base/path', 'C:/base/path', true], - ['C:\\base\\path', 'C:\\base\\path', true], - ['C:/base/path', 'C:\\base\\path', true], - ['phar:///base/path', 'phar:///base/path', true], - ['phar://C:/base/path', 'phar://C:/base/path', true], - - // trailing slash - ['/base/path/', '/base/path', true], - ['C:/base/path/', 'C:/base/path', true], - ['C:\\base\\path\\', 'C:\\base\\path', true], - ['C:/base/path/', 'C:\\base\\path', true], - ['phar:///base/path/', 'phar:///base/path', true], - ['phar://C:/base/path/', 'phar://C:/base/path', true], - - ['/base/path', '/base/path/', true], - ['C:/base/path', 'C:/base/path/', true], - ['C:\\base\\path', 'C:\\base\\path\\', true], - ['C:/base/path', 'C:\\base\\path\\', true], - ['phar:///base/path', 'phar:///base/path/', true], - ['phar://C:/base/path', 'phar://C:/base/path/', true], - - // first in second - ['/base/path/sub', '/base/path', false], - ['C:/base/path/sub', 'C:/base/path', false], - ['C:\\base\\path\\sub', 'C:\\base\\path', false], - ['C:/base/path/sub', 'C:\\base\\path', false], - ['phar:///base/path/sub', 'phar:///base/path', false], - ['phar://C:/base/path/sub', 'phar://C:/base/path', false], - - // second in first - ['/base/path', '/base/path/sub', true], - ['C:/base/path', 'C:/base/path/sub', true], - ['C:\\base\\path', 'C:\\base\\path\\sub', true], - ['C:/base/path', 'C:\\base\\path\\sub', true], - ['phar:///base/path', 'phar:///base/path/sub', true], - ['phar://C:/base/path', 'phar://C:/base/path/sub', true], - - // first is prefix - ['/base/path/di', '/base/path/dir', false], - ['C:/base/path/di', 'C:/base/path/dir', false], - ['C:\\base\\path\\di', 'C:\\base\\path\\dir', false], - ['C:/base/path/di', 'C:\\base\\path\\dir', false], - ['phar:///base/path/di', 'phar:///base/path/dir', false], - ['phar://C:/base/path/di', 'phar://C:/base/path/dir', false], - - // second is prefix - ['/base/path/dir', '/base/path/di', false], - ['C:/base/path/dir', 'C:/base/path/di', false], - ['C:\\base\\path\\dir', 'C:\\base\\path\\di', false], - ['C:/base/path/dir', 'C:\\base\\path\\di', false], - ['phar:///base/path/dir', 'phar:///base/path/di', false], - ['phar://C:/base/path/dir', 'phar://C:/base/path/di', false], - - // root - ['/', '/second', true], - ['C:/', 'C:/second', true], - ['C:', 'C:/second', true], - ['C:\\', 'C:\\second', true], - ['C:/', 'C:\\second', true], - ['phar:///', 'phar:///second', true], - ['phar://C:/', 'phar://C:/second', true], - - // windows vs unix - ['/base/path', 'C:/base/path', false], - ['C:/base/path', '/base/path', false], - ['/base/path', 'C:\\base\\path', false], - ['/base/path', 'phar:///base/path', false], - ['phar:///base/path', 'phar://C:/base/path', false], - - // different partitions - ['C:/base/path', 'D:/base/path', false], - ['C:/base/path', 'D:\\base\\path', false], - ['C:\\base\\path', 'D:\\base\\path', false], - ['C:/base/path', 'phar://C:/base/path', false], - ['phar://C:/base/path', 'phar://D:/base/path', false], - ]; + public function provideIsBasePathTests(): Generator + { + // same paths + yield ['/base/path', '/base/path', true]; + yield ['C:/base/path', 'C:/base/path', true]; + yield ['C:\\base\\path', 'C:\\base\\path', true]; + yield ['C:/base/path', 'C:\\base\\path', true]; + yield ['phar:///base/path', 'phar:///base/path', true]; + yield ['phar://C:/base/path', 'phar://C:/base/path', true]; + + // trailing slash + yield ['/base/path/', '/base/path', true]; + yield ['C:/base/path/', 'C:/base/path', true]; + yield ['C:\\base\\path\\', 'C:\\base\\path', true]; + yield ['C:/base/path/', 'C:\\base\\path', true]; + yield ['phar:///base/path/', 'phar:///base/path', true]; + yield ['phar://C:/base/path/', 'phar://C:/base/path', true]; + + yield ['/base/path', '/base/path/', true]; + yield ['C:/base/path', 'C:/base/path/', true]; + yield ['C:\\base\\path', 'C:\\base\\path\\', true]; + yield ['C:/base/path', 'C:\\base\\path\\', true]; + yield ['phar:///base/path', 'phar:///base/path/', true]; + yield ['phar://C:/base/path', 'phar://C:/base/path/', true]; + + // first in second + yield ['/base/path/sub', '/base/path', false]; + yield ['C:/base/path/sub', 'C:/base/path', false]; + yield ['C:\\base\\path\\sub', 'C:\\base\\path', false]; + yield ['C:/base/path/sub', 'C:\\base\\path', false]; + yield ['phar:///base/path/sub', 'phar:///base/path', false]; + yield ['phar://C:/base/path/sub', 'phar://C:/base/path', false]; + + // second in first + yield ['/base/path', '/base/path/sub', true]; + yield ['C:/base/path', 'C:/base/path/sub', true]; + yield ['C:\\base\\path', 'C:\\base\\path\\sub', true]; + yield ['C:/base/path', 'C:\\base\\path\\sub', true]; + yield ['phar:///base/path', 'phar:///base/path/sub', true]; + yield ['phar://C:/base/path', 'phar://C:/base/path/sub', true]; + + // first is prefix + yield ['/base/path/di', '/base/path/dir', false]; + yield ['C:/base/path/di', 'C:/base/path/dir', false]; + yield ['C:\\base\\path\\di', 'C:\\base\\path\\dir', false]; + yield ['C:/base/path/di', 'C:\\base\\path\\dir', false]; + yield ['phar:///base/path/di', 'phar:///base/path/dir', false]; + yield ['phar://C:/base/path/di', 'phar://C:/base/path/dir', false]; + + // second is prefix + yield ['/base/path/dir', '/base/path/di', false]; + yield ['C:/base/path/dir', 'C:/base/path/di', false]; + yield ['C:\\base\\path\\dir', 'C:\\base\\path\\di', false]; + yield ['C:/base/path/dir', 'C:\\base\\path\\di', false]; + yield ['phar:///base/path/dir', 'phar:///base/path/di', false]; + yield ['phar://C:/base/path/dir', 'phar://C:/base/path/di', false]; + + // root + yield ['/', '/second', true]; + yield ['C:/', 'C:/second', true]; + yield ['C:', 'C:/second', true]; + yield ['C:\\', 'C:\\second', true]; + yield ['C:/', 'C:\\second', true]; + yield ['phar:///', 'phar:///second', true]; + yield ['phar://C:/', 'phar://C:/second', true]; + + // windows vs unix + yield ['/base/path', 'C:/base/path', false]; + yield ['C:/base/path', '/base/path', false]; + yield ['/base/path', 'C:\\base\\path', false]; + yield ['/base/path', 'phar:///base/path', false]; + yield ['phar:///base/path', 'phar://C:/base/path', false]; + + // different partitions + yield ['C:/base/path', 'D:/base/path', false]; + yield ['C:/base/path', 'D:\\base\\path', false]; + yield ['C:\\base\\path', 'D:\\base\\path', false]; + yield ['C:/base/path', 'phar://C:/base/path', false]; + yield ['phar://C:/base/path', 'phar://D:/base/path', false]; } /** * @dataProvider provideIsBasePathTests */ - public function testIsBasePath($path, $ofPath, $result) + public function testIsBasePath(string $path, string $ofPath, bool $result): void { $this->assertSame($result, Path::isBasePath($path, $ofPath)); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The base path must be a string. Got: array - */ - public function testIsBasePathFailsIfInvalidBasePath() - { - Path::isBasePath([], '/base/path'); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The path must be a string. Got: array - */ - public function testIsBasePathFailsIfInvalidPath() - { - Path::isBasePath('/base/path', []); - } - - public function provideJoinTests() - { - return [ - ['', '', ''], - ['/path/to/test', '', '/path/to/test'], - ['/path/to//test', '', '/path/to/test'], - ['', '/path/to/test', '/path/to/test'], - ['', '/path/to//test', '/path/to/test'], - - ['/path/to/test', 'subdir', '/path/to/test/subdir'], - ['/path/to/test/', 'subdir', '/path/to/test/subdir'], - ['/path/to/test', '/subdir', '/path/to/test/subdir'], - ['/path/to/test/', '/subdir', '/path/to/test/subdir'], - ['/path/to/test', './subdir', '/path/to/test/subdir'], - ['/path/to/test/', './subdir', '/path/to/test/subdir'], - ['/path/to/test/', '../parentdir', '/path/to/parentdir'], - ['/path/to/test', '../parentdir', '/path/to/parentdir'], - ['path/to/test/', '/subdir', 'path/to/test/subdir'], - ['path/to/test', '/subdir', 'path/to/test/subdir'], - ['../path/to/test', '/subdir', '../path/to/test/subdir'], - ['path', '../../subdir', '../subdir'], - ['/path', '../../subdir', '/subdir'], - ['../path', '../../subdir', '../../subdir'], - - [['/path/to/test', 'subdir'], '', '/path/to/test/subdir'], - [['/path/to/test', '/subdir'], '', '/path/to/test/subdir'], - [['/path/to/test/', 'subdir'], '', '/path/to/test/subdir'], - [['/path/to/test/', '/subdir'], '', '/path/to/test/subdir'], - - [['/path'], '', '/path'], - [['/path', 'to', '/test'], '', '/path/to/test'], - [['/path', '', '/test'], '', '/path/test'], - [['path', 'to', 'test'], '', 'path/to/test'], - [[], '', ''], - - ['base/path', 'to/test', 'base/path/to/test'], - - ['C:\\path\\to\\test', 'subdir', 'C:/path/to/test/subdir'], - ['C:\\path\\to\\test\\', 'subdir', 'C:/path/to/test/subdir'], - ['C:\\path\\to\\test', '/subdir', 'C:/path/to/test/subdir'], - ['C:\\path\\to\\test\\', '/subdir', 'C:/path/to/test/subdir'], - - ['/', 'subdir', '/subdir'], - ['/', '/subdir', '/subdir'], - ['C:/', 'subdir', 'C:/subdir'], - ['C:/', '/subdir', 'C:/subdir'], - ['C:\\', 'subdir', 'C:/subdir'], - ['C:\\', '/subdir', 'C:/subdir'], - ['C:', 'subdir', 'C:/subdir'], - ['C:', '/subdir', 'C:/subdir'], - - ['phar://', '/path/to/test', 'phar:///path/to/test'], - ['phar:///', '/path/to/test', 'phar:///path/to/test'], - ['phar:///path/to/test', 'subdir', 'phar:///path/to/test/subdir'], - ['phar:///path/to/test', 'subdir/', 'phar:///path/to/test/subdir'], - ['phar:///path/to/test', '/subdir', 'phar:///path/to/test/subdir'], - ['phar:///path/to/test/', 'subdir', 'phar:///path/to/test/subdir'], - ['phar:///path/to/test/', '/subdir', 'phar:///path/to/test/subdir'], - - ['phar://', 'C:/path/to/test', 'phar://C:/path/to/test'], - ['phar://', 'C:\\path\\to\\test', 'phar://C:/path/to/test'], - ['phar://C:/path/to/test', 'subdir', 'phar://C:/path/to/test/subdir'], - ['phar://C:/path/to/test', 'subdir/', 'phar://C:/path/to/test/subdir'], - ['phar://C:/path/to/test', '/subdir', 'phar://C:/path/to/test/subdir'], - ['phar://C:/path/to/test/', 'subdir', 'phar://C:/path/to/test/subdir'], - ['phar://C:/path/to/test/', '/subdir', 'phar://C:/path/to/test/subdir'], - ['phar://C:', 'path/to/test', 'phar://C:/path/to/test'], - ['phar://C:', '/path/to/test', 'phar://C:/path/to/test'], - ['phar://C:/', 'path/to/test', 'phar://C:/path/to/test'], - ['phar://C:/', '/path/to/test', 'phar://C:/path/to/test'], - ]; + public function provideJoinTests(): Generator + { + yield [['', ''], '']; + yield [['/path/to/test', ''], '/path/to/test']; + yield [['/path/to//test', ''], '/path/to/test']; + yield [['', '/path/to/test'], '/path/to/test']; + yield [['', '/path/to//test'], '/path/to/test']; + + yield [['/path/to/test', 'subdir'], '/path/to/test/subdir']; + yield [['/path/to/test/', 'subdir'], '/path/to/test/subdir']; + yield [['/path/to/test', '/subdir'], '/path/to/test/subdir']; + yield [['/path/to/test/', '/subdir'], '/path/to/test/subdir']; + yield [['/path/to/test', './subdir'], '/path/to/test/subdir']; + yield [['/path/to/test/', './subdir'], '/path/to/test/subdir']; + yield [['/path/to/test/', '../parentdir'], '/path/to/parentdir']; + yield [['/path/to/test', '../parentdir'], '/path/to/parentdir']; + yield [['path/to/test/', '/subdir'], 'path/to/test/subdir']; + yield [['path/to/test', '/subdir'], 'path/to/test/subdir']; + yield [['../path/to/test', '/subdir'], '../path/to/test/subdir']; + yield [['path', '../../subdir'], '../subdir']; + yield [['/path', '../../subdir'], '/subdir']; + yield [['../path', '../../subdir'], '../../subdir']; + + yield [['/path/to/test', 'subdir', ''], '/path/to/test/subdir']; + yield [['/path/to/test', '/subdir', ''], '/path/to/test/subdir']; + yield [['/path/to/test/', 'subdir', ''], '/path/to/test/subdir']; + yield [['/path/to/test/', '/subdir', ''], '/path/to/test/subdir']; + + yield [['/path', ''], '/path']; + yield [['/path', 'to', '/test', ''], '/path/to/test']; + yield [['/path', '', '/test', ''], '/path/test']; + yield [['path', 'to', 'test', ''], 'path/to/test']; + yield [[], '']; + + yield [['base/path', 'to/test'], 'base/path/to/test']; + + yield [['C:\\path\\to\\test', 'subdir'], 'C:/path/to/test/subdir']; + yield [['C:\\path\\to\\test\\', 'subdir'], 'C:/path/to/test/subdir']; + yield [['C:\\path\\to\\test', '/subdir'], 'C:/path/to/test/subdir']; + yield [['C:\\path\\to\\test\\', '/subdir'], 'C:/path/to/test/subdir']; + + yield [['/', 'subdir'], '/subdir']; + yield [['/', '/subdir'], '/subdir']; + yield [['C:/', 'subdir'], 'C:/subdir']; + yield [['C:/', '/subdir'], 'C:/subdir']; + yield [['C:\\', 'subdir'], 'C:/subdir']; + yield [['C:\\', '/subdir'], 'C:/subdir']; + yield [['C:', 'subdir'], 'C:/subdir']; + yield [['C:', '/subdir'], 'C:/subdir']; + + yield [['phar://', '/path/to/test'], 'phar:///path/to/test']; + yield [['phar:///', '/path/to/test'], 'phar:///path/to/test']; + yield [['phar:///path/to/test', 'subdir'], 'phar:///path/to/test/subdir']; + yield [['phar:///path/to/test', 'subdir/'], 'phar:///path/to/test/subdir']; + yield [['phar:///path/to/test', '/subdir'], 'phar:///path/to/test/subdir']; + yield [['phar:///path/to/test/', 'subdir'], 'phar:///path/to/test/subdir']; + yield [['phar:///path/to/test/', '/subdir'], 'phar:///path/to/test/subdir']; + + yield [['phar://', 'C:/path/to/test'], 'phar://C:/path/to/test']; + yield [['phar://', 'C:\\path\\to\\test'], 'phar://C:/path/to/test']; + yield [['phar://C:/path/to/test', 'subdir'], 'phar://C:/path/to/test/subdir']; + yield [['phar://C:/path/to/test', 'subdir/'], 'phar://C:/path/to/test/subdir']; + yield [['phar://C:/path/to/test', '/subdir'], 'phar://C:/path/to/test/subdir']; + yield [['phar://C:/path/to/test/', 'subdir'], 'phar://C:/path/to/test/subdir']; + yield [['phar://C:/path/to/test/', '/subdir'], 'phar://C:/path/to/test/subdir']; + yield [['phar://C:', 'path/to/test'], 'phar://C:/path/to/test']; + yield [['phar://C:', '/path/to/test'], 'phar://C:/path/to/test']; + yield [['phar://C:/', 'path/to/test'], 'phar://C:/path/to/test']; + yield [['phar://C:/', '/path/to/test'], 'phar://C:/path/to/test']; } /** * @dataProvider provideJoinTests */ - public function testJoin($path1, $path2, $result) + public function testJoin(array $paths, $result): void { - $this->assertSame($result, Path::join($path1, $path2)); + $this->assertSame($result, Path::join(...$paths)); } - public function testJoinVarArgs() + public function testJoinVarArgs(): void { $this->assertSame('/path', Path::join('/path')); $this->assertSame('/path/to', Path::join('/path', 'to')); @@ -1292,32 +1053,22 @@ public function testJoinVarArgs() $this->assertSame('/path/to/test/subdir', Path::join('/path', 'to', '/test', 'subdir/')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The paths must be strings. Got: array - */ - public function testJoinFailsIfInvalidPath() + public function testGetHomeDirectoryFailsIfNotSupportedOperationSystem(): void { - Path::join('/path', []); - } + $this->expectException(\RuntimeException::class); + $this->expectExceptionMessage('Your environment or operation system isn\'t supported'); - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Your environment or operation system isn't supported - */ - public function testGetHomeDirectoryFailsIfNotSupportedOperationSystem() - { putenv('HOME='); Path::getHomeDirectory(); } - public function testGetHomeDirectoryForUnix() + public function testGetHomeDirectoryForUnix(): void { $this->assertEquals('/home/webmozart', Path::getHomeDirectory()); } - public function testGetHomeDirectoryForWindows() + public function testGetHomeDirectoryForWindows(): void { putenv('HOME='); putenv('HOMEDRIVE=C:'); @@ -1326,16 +1077,8 @@ public function testGetHomeDirectoryForWindows() $this->assertEquals('C:/users/webmozart', Path::getHomeDirectory()); } - public function testNormalize() + public function testNormalize(): void { $this->assertSame('C:/Foo/Bar/test', Path::normalize('C:\\Foo\\Bar/test')); } - - /** - * @expectedException \InvalidArgumentException - */ - public function testNormalizeFailsIfNoString() - { - Path::normalize(true); - } } From 0b86ef76178964e00496a48d7f8af8a63330af8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 11:43:21 +0200 Subject: [PATCH 04/21] Fix CS --- src/Symfony/Component/Filesystem/Path.php | 152 ++++++++---------- .../Component/Filesystem/Tests/PathTest.php | 37 ++--- 2 files changed, 84 insertions(+), 105 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 0afd9790bd519..10d06cd6a5218 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -11,24 +11,6 @@ namespace Symfony\Component\Filesystem; -use function array_pop; -use function basename; -use function ctype_alpha; -use function explode; -use function getenv; -use function implode; -use InvalidArgumentException; -use function is_string; -use function ltrim; -use function mb_strtolower; -use function pathinfo; -use function rtrim; -use RuntimeException; -use function sprintf; -use function str_replace; -use function strpos; -use function substr; - /** * Contains utility methods for handling path strings. * @@ -101,14 +83,14 @@ public static function canonicalize(string $path): string // Replace "~" with user's home directory. if ('~' === $path[0]) { - $path = static::getHomeDirectory().substr($path, 1); + $path = static::getHomeDirectory().\substr($path, 1); } - $path = str_replace('\\', '/', $path); + $path = \str_replace('\\', '/', $path); [$root, $pathWithoutRoot] = self::split($path); - $parts = explode('/', $pathWithoutRoot); + $parts = \explode('/', $pathWithoutRoot); $canonicalParts = []; // Collapse "." and "..", if possible @@ -122,7 +104,7 @@ public static function canonicalize(string $path): string if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1] ) { - array_pop($canonicalParts); + \array_pop($canonicalParts); continue; } @@ -134,7 +116,7 @@ public static function canonicalize(string $path): string } // Add the root directory again - self::$buffer[$path] = $canonicalPath = $root.implode('/', $canonicalParts); + self::$buffer[$path] = $canonicalPath = $root.\implode('/', $canonicalParts); ++self::$bufferSize; // Clean up regularly to prevent memory leaks @@ -163,7 +145,7 @@ public static function canonicalize(string $path): string */ public static function normalize(string $path): string { - return str_replace('\\', '/', $path); + return \str_replace('\\', '/', $path); } /** @@ -200,9 +182,9 @@ public static function getDirectory(string $path): string $path = static::canonicalize($path); // Maintain scheme - if (false !== ($pos = strpos($path, '://'))) { - $scheme = substr($path, 0, $pos + 3); - $path = substr($path, $pos + 3); + if (false !== ($pos = \strpos($path, '://'))) { + $scheme = \substr($path, 0, $pos + 3); + $path = \substr($path, $pos + 3); } else { $scheme = ''; } @@ -214,11 +196,11 @@ public static function getDirectory(string $path): string } // Directory equals Windows root "C:/" - if (2 === $pos && ctype_alpha($path[0]) && ':' === $path[1]) { - return $scheme.substr($path, 0, 3); + if (2 === $pos && \ctype_alpha($path[0]) && ':' === $path[1]) { + return $scheme.\substr($path, 0, 3); } - return $scheme.substr($path, 0, $pos); + return $scheme.\substr($path, 0, $pos); } return ''; @@ -238,21 +220,21 @@ public static function getDirectory(string $path): string * * @return string The canonical home directory * - * @throws RuntimeException If your operation system or environment isn't supported + * @throws \RuntimeException If your operation system or environment isn't supported */ public static function getHomeDirectory(): string { // For UNIX support - if (getenv('HOME')) { - return static::canonicalize(getenv('HOME')); + if (\getenv('HOME')) { + return static::canonicalize(\getenv('HOME')); } // For >= Windows8 support - if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { - return static::canonicalize(getenv('HOMEDRIVE').getenv('HOMEPATH')); + if (\getenv('HOMEDRIVE') && \getenv('HOMEPATH')) { + return static::canonicalize(\getenv('HOMEDRIVE').\getenv('HOMEPATH')); } - throw new RuntimeException("Your environment or operation system isn't supported"); + throw new \RuntimeException("Your environment or operation system isn't supported"); } /** @@ -272,9 +254,9 @@ public static function getRoot(string $path): string } // Maintain scheme - if (false !== ($pos = strpos($path, '://'))) { - $scheme = substr($path, 0, $pos + 3); - $path = substr($path, $pos + 3); + if (false !== ($pos = \strpos($path, '://'))) { + $scheme = \substr($path, 0, $pos + 3); + $path = \substr($path, $pos + 3); } else { $scheme = ''; } @@ -287,7 +269,7 @@ public static function getRoot(string $path): string $length = \strlen($path); // Windows root - if ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + if ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === $length) { return $scheme.$path.'/'; @@ -315,7 +297,7 @@ public static function getFilename(string $path): string return ''; } - return basename($path); + return \basename($path); } /** @@ -335,10 +317,10 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens if (null !== $extension) { // remove extension and trailing dot - return rtrim(basename($path, $extension), '.'); + return \rtrim(\basename($path, $extension), '.'); } - return pathinfo($path, PATHINFO_FILENAME); + return \pathinfo($path, PATHINFO_FILENAME); } /** @@ -357,7 +339,7 @@ public static function getExtension(string $path, bool $forceLowerCase = false): return ''; } - $extension = pathinfo($path, PATHINFO_EXTENSION); + $extension = \pathinfo($path, PATHINFO_EXTENSION); if ($forceLowerCase) { $extension = self::toLower($extension); @@ -396,7 +378,7 @@ public static function hasExtension(string $path, $extensions = null, bool $igno return '' !== $actualExtension; } - if (is_string($extensions)) { + if (\is_string($extensions)) { $extensions = [$extensions]; } @@ -406,7 +388,7 @@ public static function hasExtension(string $path, $extensions = null, bool $igno } // remove leading '.' in extensions array - $extensions[$key] = ltrim($extension, '.'); + $extensions[$key] = \ltrim($extension, '.'); } return \in_array($actualExtension, $extensions, true); @@ -427,19 +409,19 @@ public static function changeExtension(string $path, string $extension): string } $actualExtension = self::getExtension($path); - $extension = ltrim($extension, '.'); + $extension = \ltrim($extension, '.'); // No extension for paths - if ('/' === substr($path, -1)) { + if ('/' === \substr($path, -1)) { return $path; } // No actual extension in path if (empty($actualExtension)) { - return $path.('.' === substr($path, -1) ? '' : '.').$extension; + return $path.('.' === \substr($path, -1) ? '' : '.').$extension; } - return substr($path, 0, -\strlen($actualExtension)).$extension; + return \substr($path, 0, -\strlen($actualExtension)).$extension; } /** @@ -457,8 +439,8 @@ public static function isAbsolute(string $path): bool } // Strip scheme - if (false !== ($pos = strpos($path, '://'))) { - $path = substr($path, $pos + 3); + if (false !== ($pos = \strpos($path, '://'))) { + $path = \substr($path, $pos + 3); } // UNIX root "/" or "\" (Windows style) @@ -467,7 +449,7 @@ public static function isAbsolute(string $path): bool } // Windows root - if (\strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + if (\strlen($path) > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === \strlen($path)) { return true; @@ -519,7 +501,7 @@ public static function isRelative(string $path): bool * // => C:/style.css * * Path::makeAbsolute("C:/style.css", "/webmozart/puli/css"); - * // InvalidArgumentException + * // \InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. @@ -531,18 +513,18 @@ public static function isRelative(string $path): bool * * @return string an absolute path in canonical form * - * @throws InvalidArgumentException if the base path is not absolute or if + * @throws \InvalidArgumentException if the base path is not absolute or if * the given path is an absolute path with * a different root than the base path */ public static function makeAbsolute(string $path, string $basePath): string { if ('' === $basePath) { - throw new \InvalidArgumentException(sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); + throw new \InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); } if (!static::isAbsolute($basePath)) { - throw new InvalidArgumentException(sprintf( + throw new \InvalidArgumentException(\sprintf( 'The base path "%s" is not an absolute path.', $basePath )); @@ -552,14 +534,14 @@ public static function makeAbsolute(string $path, string $basePath): string return static::canonicalize($path); } - if (false !== ($pos = strpos($basePath, '://'))) { - $scheme = substr($basePath, 0, $pos + 3); - $basePath = substr($basePath, $pos + 3); + if (false !== ($pos = \strpos($basePath, '://'))) { + $scheme = \substr($basePath, 0, $pos + 3); + $basePath = \substr($basePath, $pos + 3); } else { $scheme = ''; } - return $scheme.self::canonicalize(rtrim($basePath, '/\\').'/'.$path); + return $scheme.self::canonicalize(\rtrim($basePath, '/\\').'/'.$path); } /** @@ -593,7 +575,7 @@ public static function makeAbsolute(string $path, string $basePath): string * * ```php * Path::makeRelative("C:/webmozart/style.css", "/webmozart/puli"); - * // InvalidArgumentException + * // \InvalidArgumentException * ``` * * If the passed path is absolute, but the base path is not, an exception @@ -601,7 +583,7 @@ public static function makeAbsolute(string $path, string $basePath): string * * ```php * Path::makeRelative("/webmozart/style.css", "webmozart/puli"); - * // InvalidArgumentException + * // \InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. @@ -613,7 +595,7 @@ public static function makeAbsolute(string $path, string $basePath): string * * @return string a relative path in canonical form * - * @throws InvalidArgumentException if the base path is not absolute or if + * @throws \InvalidArgumentException if the base path is not absolute or if * the given path has a different root * than the base path */ @@ -631,7 +613,7 @@ public static function makeRelative(string $path, string $basePath): string if ('' === $root && '' !== $baseRoot) { // If base path is already in its root if ('' === $relativeBasePath) { - $relativePath = ltrim($relativePath, './\\'); + $relativePath = \ltrim($relativePath, './\\'); } return $relativePath; @@ -640,7 +622,7 @@ public static function makeRelative(string $path, string $basePath): string // If the passed path is absolute, but the base path is not, we // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { - throw new InvalidArgumentException(sprintf( + throw new \InvalidArgumentException(\sprintf( 'The absolute path "%s" cannot be made relative to the '. 'relative path "%s". You should provide an absolute base '. 'path instead.', @@ -651,7 +633,7 @@ public static function makeRelative(string $path, string $basePath): string // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { - throw new InvalidArgumentException(sprintf( + throw new \InvalidArgumentException(\sprintf( 'The path "%s" cannot be made relative to "%s", because they '. 'have different roots ("%s" and "%s").', $path, @@ -666,8 +648,8 @@ public static function makeRelative(string $path, string $basePath): string } // Build a "../../" prefix with as many "../" parts as necessary - $parts = explode('/', $relativePath); - $baseParts = explode('/', $relativeBasePath); + $parts = \explode('/', $relativePath); + $baseParts = \explode('/', $relativeBasePath); $dotDotPrefix = ''; // Once we found a non-matching part in the prefix, we need to add @@ -685,7 +667,7 @@ public static function makeRelative(string $path, string $basePath): string $dotDotPrefix .= '../'; } - return rtrim($dotDotPrefix.implode('/', $parts), '/'); + return \rtrim($dotDotPrefix.\implode('/', $parts), '/'); } /** @@ -697,7 +679,7 @@ public static function makeRelative(string $path, string $basePath): string */ public static function isLocal(string $path): bool { - return '' !== $path && false === strpos($path, '://'); + return '' !== $path && false === \strpos($path, '://'); } /** @@ -766,7 +748,7 @@ public static function getLongestCommonBasePath(array $paths): ?string // Prevent false positives for common prefixes // see isBasePath() - if (0 === strpos($path.'/', $basePath.'/')) { + if (0 === \strpos($path.'/', $basePath.'/')) { // Next path continue 2; } @@ -800,17 +782,17 @@ public static function join(string ...$paths): string if (null === $finalPath) { // For first part we keep slashes, like '/top', 'C:\' or 'phar://' $finalPath = $path; - $wasScheme = (false !== strpos($path, '://')); + $wasScheme = (false !== \strpos($path, '://')); continue; } // Only add slash if previous part didn't end with '/' or '\' - if (!\in_array(substr($finalPath, -1), ['/', '\\'])) { + if (!\in_array(\substr($finalPath, -1), ['/', '\\'])) { $finalPath .= '/'; } // If first part included a scheme like 'phar://' we allow current part to start with '/', otherwise trim - $finalPath .= $wasScheme ? $path : ltrim($path, '/'); + $finalPath .= $wasScheme ? $path : \ltrim($path, '/'); $wasScheme = false; } @@ -856,7 +838,7 @@ public static function isBasePath(string $basePath, string $ofPath): bool // Don't append a slash for the root "/", because then that root // won't be discovered as common prefix ("//" is not a prefix of // "/foobar/"). - return 0 === strpos($ofPath.'/', rtrim($basePath, '/').'/'); + return 0 === \strpos($ofPath.'/', \rtrim($basePath, '/').'/'); } /** @@ -886,9 +868,9 @@ private static function split(string $path): array } // Remember scheme as part of the root, if any - if (false !== ($pos = strpos($path, '://'))) { - $root = substr($path, 0, $pos + 3); - $path = substr($path, $pos + 3); + if (false !== ($pos = \strpos($path, '://'))) { + $root = \substr($path, 0, $pos + 3); + $path = \substr($path, $pos + 3); } else { $root = ''; } @@ -896,18 +878,18 @@ private static function split(string $path): array $length = \strlen($path); // Remove and remember root directory - if (0 === strpos($path, '/')) { + if (0 === \strpos($path, '/')) { $root .= '/'; - $path = $length > 1 ? substr($path, 1) : ''; - } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { + $path = $length > 1 ? \substr($path, 1) : ''; + } elseif ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { if (2 === $length) { // Windows special case: "C:" $root .= $path.'/'; $path = ''; } elseif ('/' === $path[2]) { // Windows normal case: "C:/".. - $root .= substr($path, 0, 3); - $path = $length > 3 ? substr($path, 3) : ''; + $root .= \substr($path, 0, 3); + $path = $length > 3 ? \substr($path, 3) : ''; } } @@ -924,7 +906,7 @@ private static function split(string $path): array private static function toLower(string $str): string { if (\function_exists('mb_strtolower')) { - return mb_strtolower($str, mb_detect_encoding($str)); + return \mb_strtolower($str, mb_detect_encoding($str)); } return strtolower($str); diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index b7dad1bd33178..9f9b1da6d13b3 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -11,13 +11,10 @@ namespace Symfony\Component\Filesystem\Tests; -use Generator; use PHPUnit\Framework\TestCase; use Symfony\Component\Filesystem\Path; /** - * @since 1.0 - * * @author Bernhard Schussek * @author Thomas Schulz */ @@ -43,7 +40,7 @@ public function tearDown(): void putenv('HOMEPATH='.$this->storedEnv['HOMEPATH']); } - public function provideCanonicalizationTests(): Generator + public function provideCanonicalizationTests(): \Generator { // relative paths (forward slash) yield ['css/./style.css', 'css/style.css']; @@ -174,7 +171,7 @@ public function testCanonicalize(string $path, string $canonicalized): void $this->assertSame($canonicalized, Path::canonicalize($path)); } - public function provideGetDirectoryTests(): Generator + public function provideGetDirectoryTests(): \Generator { yield ['/webmozart/puli/style.css', '/webmozart/puli']; yield ['/webmozart/puli', '/webmozart']; @@ -235,7 +232,7 @@ public function testGetDirectory(string $path, string $directory): void $this->assertSame($directory, Path::getDirectory($path)); } - public function provideGetFilenameTests(): Generator + public function provideGetFilenameTests(): \Generator { yield ['/webmozart/puli/style.css', 'style.css']; yield ['/webmozart/puli/STYLE.CSS', 'STYLE.CSS']; @@ -254,7 +251,7 @@ public function testGetFilename(string $path, string $filename): void $this->assertSame($filename, Path::getFilename($path)); } - public function provideGetFilenameWithoutExtensionTests(): Generator + public function provideGetFilenameWithoutExtensionTests(): \Generator { yield ['/webmozart/puli/style.css.twig', null, 'style.css']; yield ['/webmozart/puli/style.css.', null, 'style.css']; @@ -285,7 +282,7 @@ public function testGetFilenameWithoutExtension(string $path, ?string $extension $this->assertSame($filename, Path::getFilenameWithoutExtension($path, $extension)); } - public function provideGetExtensionTests(): Generator + public function provideGetExtensionTests(): \Generator { yield ['/webmozart/puli/style.css.twig', false, 'twig']; yield ['/webmozart/puli/style.css', false, 'css']; @@ -313,7 +310,7 @@ public function testGetExtension(string $path, bool $forceLowerCase, string $ext $this->assertSame($extension, Path::getExtension($path, $forceLowerCase)); } - public function provideHasExtensionTests(): Generator + public function provideHasExtensionTests(): \Generator { yield [true, '/webmozart/puli/style.css.twig', null, false]; yield [true, '/webmozart/puli/style.css', null, false]; @@ -362,7 +359,7 @@ public function testHasExtension(bool $hasExtension, string $path, $extension, b $this->assertSame($hasExtension, Path::hasExtension($path, $extension, $ignoreCase)); } - public function provideChangeExtensionTests(): Generator + public function provideChangeExtensionTests(): \Generator { yield ['/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html']; yield ['/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass']; @@ -388,7 +385,7 @@ public function testChangeExtension(string $path, string $extension, string $pat ++$call; } - public function provideIsAbsolutePathTests(): Generator + public function provideIsAbsolutePathTests(): \Generator { yield ['/css/style.css', true]; yield ['/', true]; @@ -431,7 +428,7 @@ public function testIsRelative(string $path, bool $isAbsolute): void $this->assertSame(!$isAbsolute, Path::isRelative($path)); } - public function provideGetRootTests(): Generator + public function provideGetRootTests(): \Generator { yield ['/css/style.css', '/']; yield ['/', '/']; @@ -465,7 +462,7 @@ public function testGetRoot(string $path, string $root): void $this->assertSame($root, Path::getRoot($path)); } - public function providePathTests(): Generator + public function providePathTests(): \Generator { // relative to absolute path yield ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; @@ -484,7 +481,7 @@ public function providePathTests(): Generator yield ['..', '/webmozart/puli', '/webmozart']; } - public function provideMakeAbsoluteTests(): Generator + public function provideMakeAbsoluteTests(): \Generator { foreach ($this->providePathTests() as $set) { yield $set; @@ -577,7 +574,7 @@ public function testMakeAbsoluteFailsIfBasePathEmpty(): void Path::makeAbsolute('css/style.css', ''); } - public function provideAbsolutePathsWithDifferentRoots(): Generator + public function provideAbsolutePathsWithDifferentRoots(): \Generator { yield ['C:/css/style.css', '/webmozart/puli']; yield ['C:/css/style.css', '\\webmozart\\puli']; @@ -613,7 +610,7 @@ public function testMakeAbsoluteDoesNotFailIfDifferentRoot(string $basePath, str $this->assertSame(Path::canonicalize($absolutePath), Path::makeAbsolute($absolutePath, $basePath)); } - public function provideMakeRelativeTests(): Generator + public function provideMakeRelativeTests(): \Generator { foreach ($this->providePathTests() as $set) { yield [$set[2], $set[1], $set[0]]; @@ -740,7 +737,7 @@ public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, strin Path::makeRelative($absolutePath, $basePath); } - public function provideIsLocalTests(): Generator + public function provideIsLocalTests(): \Generator { yield ['/bg.png', true]; yield ['bg.png', true]; @@ -757,7 +754,7 @@ public function testIsLocal(string $path, bool $isLocal): void $this->assertSame($isLocal, Path::isLocal($path)); } - public function provideGetLongestCommonBasePathTests(): Generator + public function provideGetLongestCommonBasePathTests(): \Generator { // same paths yield [['/base/path', '/base/path'], '/base/path']; @@ -877,7 +874,7 @@ public function testGetLongestCommonBasePath(array $paths, ?string $basePath): v $this->assertSame($basePath, Path::getLongestCommonBasePath($paths)); } - public function provideIsBasePathTests(): Generator + public function provideIsBasePathTests(): \Generator { // same paths yield ['/base/path', '/base/path', true]; @@ -966,7 +963,7 @@ public function testIsBasePath(string $path, string $ofPath, bool $result): void $this->assertSame($result, Path::isBasePath($path, $ofPath)); } - public function provideJoinTests(): Generator + public function provideJoinTests(): \Generator { yield [['', ''], '']; yield [['/path/to/test', ''], '/path/to/test']; From c522164c7f3b7f6062e87c65617302eaec17310e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 11:54:13 +0200 Subject: [PATCH 05/21] Address various comments --- src/Symfony/Component/Filesystem/Path.php | 107 +----- .../Component/Filesystem/Tests/PathTest.php | 336 +++++++++--------- 2 files changed, 187 insertions(+), 256 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 10d06cd6a5218..130810faaebc5 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -63,10 +63,6 @@ final class Path * ``` * * This method is able to deal with both UNIX and Windows paths. - * - * @param string $path a path string - * - * @return string the canonical path */ public static function canonicalize(string $path): string { @@ -138,10 +134,6 @@ public static function canonicalize(string $path): string * path. * * This method is able to deal with both UNIX and Windows paths. - * - * @param string $path a path string - * - * @return string the normalized path */ public static function normalize(string $path): string { @@ -166,8 +158,6 @@ public static function normalize(string $path): string * * The result is a canonical path. * - * @param string $path a path string - * * @return string The canonical directory part. Returns the root directory * if the root directory is passed. Returns an empty string * if a relative path is passed that contains no slashes. @@ -218,8 +208,6 @@ public static function getDirectory(string $path): string * * The result is a canonical path. * - * @return string The canonical home directory - * * @throws \RuntimeException If your operation system or environment isn't supported */ public static function getHomeDirectory(): string @@ -234,7 +222,7 @@ public static function getHomeDirectory(): string return static::canonicalize(\getenv('HOMEDRIVE').\getenv('HOMEPATH')); } - throw new \RuntimeException("Your environment or operation system isn't supported"); + throw new \RuntimeException("Cannot find the home directory path: Your environment or operation system isn't supported"); } /** @@ -242,8 +230,6 @@ public static function getHomeDirectory(): string * * The result is a canonical path. * - * @param string $path a path string - * * @return string The canonical root directory. Returns an empty string if * the given path is relative or empty. */ @@ -286,10 +272,6 @@ public static function getRoot(string $path): string /** * Returns the file name from a file path. - * - * @param string $path the path string - * - * @return string the file name */ public static function getFilename(string $path): string { @@ -303,11 +285,8 @@ public static function getFilename(string $path): string /** * Returns the file name without the extension from a file path. * - * @param string $path the path string * @param string|null $extension if specified, only that extension is cut * off (may contain leading dot) - * - * @return string the file name without extension */ public static function getFilenameWithoutExtension(string $path, ?string $extension = null) { @@ -324,14 +303,11 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens } /** - * Returns the extension from a file path. + * Returns the extension from a file path (without leading dot). * - * @param string $path the path string * @param bool $forceLowerCase forces the extension to be lower-case * (requires mbstring extension for correct * multi-byte character handling in extension) - * - * @return string the extension of the file path (without leading dot) */ public static function getExtension(string $path, bool $forceLowerCase = false): string { @@ -349,7 +325,7 @@ public static function getExtension(string $path, bool $forceLowerCase = false): } /** - * Returns whether the path has an extension. + * Returns whether the path has an (or the specified) extension. * * @param string $path the path string * @param string|string[]|null $extensions if null or not provided, checks if @@ -361,9 +337,6 @@ public static function getExtension(string $path, bool $forceLowerCase = false): * (requires mbstring extension for * correct multi-byte character * handling in the extension) - * - * @return bool returns `true` if the path has an (or the specified) - * extension and `false` otherwise */ public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool { @@ -426,11 +399,6 @@ public static function changeExtension(string $path, string $extension): string /** * Returns whether a path is absolute. - * - * @param string $path a path string - * - * @return bool returns true if the path is absolute, false if it is - * relative or empty */ public static function isAbsolute(string $path): bool { @@ -465,12 +433,7 @@ public static function isAbsolute(string $path): bool } /** - * Returns whether a path is relative. - * - * @param string $path a path string - * - * @return bool returns true if the path is relative or empty, false if - * it is absolute + * Returns whether or not a path is relative. */ public static function isRelative(string $path): bool { @@ -478,7 +441,7 @@ public static function isRelative(string $path): bool } /** - * Turns a relative path into an absolute path. + * Turns a relative path into an absolute path in canonical form. * * Usually, the relative path is appended to the given base path. Dot * segments ("." and "..") are removed/collapsed and all slashes turned @@ -508,11 +471,8 @@ public static function isRelative(string $path): bool * * The result is a canonical path. * - * @param string $path a path to make absolute * @param string $basePath an absolute base path * - * @return string an absolute path in canonical form - * * @throws \InvalidArgumentException if the base path is not absolute or if * the given path is an absolute path with * a different root than the base path @@ -590,11 +550,6 @@ public static function makeAbsolute(string $path, string $basePath): string * * The result is a canonical path. * - * @param string $path a path to make relative - * @param string $basePath a base path - * - * @return string a relative path in canonical form - * * @throws \InvalidArgumentException if the base path is not absolute or if * the given path has a different root * than the base path @@ -672,10 +627,6 @@ public static function makeRelative(string $path, string $basePath): string /** * Returns whether the given path is on the local filesystem. - * - * @param string $path a path string - * - * @return bool returns true if the path is local, false for a URL */ public static function isLocal(string $path): bool { @@ -683,26 +634,27 @@ public static function isLocal(string $path): bool } /** - * Returns the longest common base path of a set of paths. + * Returns the longest common base path in canonical form of a set of paths or + * `null` if the paths are on different Windows partitions. * * Dot segments ("." and "..") are removed/collapsed and all slashes turned * into forward slashes. * * ```php - * $basePath = Path::getLongestCommonBasePath(array( + * $basePath = Path::getLongestCommonBasePath([ * '/webmozart/css/style.css', * '/webmozart/css/..' - * )); + * ]); * // => /webmozart * ``` * * The root is returned if no common base path can be found: * * ```php - * $basePath = Path::getLongestCommonBasePath(array( + * $basePath = Path::getLongestCommonBasePath([ * '/webmozart/css/style.css', * '/puli/css/..' - * )); + * ]); * // => / * ``` * @@ -710,20 +662,14 @@ public static function isLocal(string $path): bool * returned. * * ```php - * $basePath = Path::getLongestCommonBasePath(array( + * $basePath = Path::getLongestCommonBasePath([ * 'C:/webmozart/css/style.css', * 'D:/webmozart/css/..' - * )); + * ]); * // => null * ``` - * - * @param string[] $paths a list of paths - * - * @return string|null the longest common base path in canonical form or - * `null` if the paths are on different Windows - * partitions */ - public static function getLongestCommonBasePath(array $paths): ?string + public static function getLongestCommonBasePath(string ...$paths): ?string { [$bpRoot, $basePath] = self::split(self::canonicalize(reset($paths))); @@ -761,11 +707,7 @@ public static function getLongestCommonBasePath(array $paths): ?string } /** - * Joins two or more path strings. - * - * The result is a canonical path. - * - * @return string the joint path + * Joins two or more path strings into a canonical path. */ public static function join(string ...$paths): string { @@ -822,11 +764,6 @@ public static function join(string ...$paths): string * Path::isBasePath('/webmozart', '/puli'); * // => false * ``` - * - * @param string $basePath the base path to test - * @param string $ofPath the other path - * - * @return bool whether the base path is a base path of the other path */ public static function isBasePath(string $basePath, string $ofPath): bool { @@ -842,7 +779,7 @@ public static function isBasePath(string $basePath, string $ofPath): bool } /** - * Splits a part into its root directory and the remainder. + * Splits a canonical path into its root directory and the remainder. * * If the path has no root directory, an empty root directory will be * returned. @@ -851,12 +788,10 @@ public static function isBasePath(string $basePath, string $ofPath): bool * will always contain a trailing slash. * * list ($root, $path) = Path::split("C:/webmozart") - * // => array("C:/", "webmozart") + * // => ["C:/", "webmozart"] * * list ($root, $path) = Path::split("C:") - * // => array("C:/", "") - * - * @param string $path the canonical path to split + * // => ["C:/", ""] * * @return string[] an array with the root directory and the remaining * relative path @@ -897,11 +832,7 @@ private static function split(string $path): array } /** - * Converts string to lower-case (multi-byte safe if mbstring is installed). - * - * @param string $str The string - * - * @return string Lower case string + * Converts string to lower-case. */ private static function toLower(string $str): string { diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 9f9b1da6d13b3..8876499ea36db 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -173,51 +173,51 @@ public function testCanonicalize(string $path, string $canonicalized): void public function provideGetDirectoryTests(): \Generator { - yield ['/webmozart/puli/style.css', '/webmozart/puli']; - yield ['/webmozart/puli', '/webmozart']; + yield ['/webmozart/symfony/style.css', '/webmozart/symfony']; + yield ['/webmozart/symfony', '/webmozart']; yield ['/webmozart', '/']; yield ['/', '/']; yield ['', '']; - yield ['\\webmozart\\puli\\style.css', '/webmozart/puli']; - yield ['\\webmozart\\puli', '/webmozart']; + yield ['\\webmozart\\symfony\\style.css', '/webmozart/symfony']; + yield ['\\webmozart\\symfony', '/webmozart']; yield ['\\webmozart', '/']; yield ['\\', '/']; - yield ['C:/webmozart/puli/style.css', 'C:/webmozart/puli']; - yield ['C:/webmozart/puli', 'C:/webmozart']; + yield ['C:/webmozart/symfony/style.css', 'C:/webmozart/symfony']; + yield ['C:/webmozart/symfony', 'C:/webmozart']; yield ['C:/webmozart', 'C:/']; yield ['C:/', 'C:/']; yield ['C:', 'C:/']; - yield ['C:\\webmozart\\puli\\style.css', 'C:/webmozart/puli']; - yield ['C:\\webmozart\\puli', 'C:/webmozart']; + yield ['C:\\webmozart\\symfony\\style.css', 'C:/webmozart/symfony']; + yield ['C:\\webmozart\\symfony', 'C:/webmozart']; yield ['C:\\webmozart', 'C:/']; yield ['C:\\', 'C:/']; - yield ['phar:///webmozart/puli/style.css', 'phar:///webmozart/puli']; - yield ['phar:///webmozart/puli', 'phar:///webmozart']; + yield ['phar:///webmozart/symfony/style.css', 'phar:///webmozart/symfony']; + yield ['phar:///webmozart/symfony', 'phar:///webmozart']; yield ['phar:///webmozart', 'phar:///']; yield ['phar:///', 'phar:///']; - yield ['phar://C:/webmozart/puli/style.css', 'phar://C:/webmozart/puli']; - yield ['phar://C:/webmozart/puli', 'phar://C:/webmozart']; + yield ['phar://C:/webmozart/symfony/style.css', 'phar://C:/webmozart/symfony']; + yield ['phar://C:/webmozart/symfony', 'phar://C:/webmozart']; yield ['phar://C:/webmozart', 'phar://C:/']; yield ['phar://C:/', 'phar://C:/']; - yield ['webmozart/puli/style.css', 'webmozart/puli']; - yield ['webmozart/puli', 'webmozart']; + yield ['webmozart/symfony/style.css', 'webmozart/symfony']; + yield ['webmozart/symfony', 'webmozart']; yield ['webmozart', '']; - yield ['webmozart\\puli\\style.css', 'webmozart/puli']; - yield ['webmozart\\puli', 'webmozart']; + yield ['webmozart\\symfony\\style.css', 'webmozart/symfony']; + yield ['webmozart\\symfony', 'webmozart']; yield ['webmozart', '']; - yield ['/webmozart/./puli/style.css', '/webmozart/puli']; - yield ['/webmozart/../puli/style.css', '/puli']; - yield ['/webmozart/./../puli/style.css', '/puli']; - yield ['/webmozart/.././puli/style.css', '/puli']; - yield ['/webmozart/../../puli/style.css', '/puli']; + yield ['/webmozart/./symfony/style.css', '/webmozart/symfony']; + yield ['/webmozart/../symfony/style.css', '/symfony']; + yield ['/webmozart/./../symfony/style.css', '/symfony']; + yield ['/webmozart/.././symfony/style.css', '/symfony']; + yield ['/webmozart/../../symfony/style.css', '/symfony']; yield ['/.', '/']; yield ['/..', '/']; @@ -234,11 +234,11 @@ public function testGetDirectory(string $path, string $directory): void public function provideGetFilenameTests(): \Generator { - yield ['/webmozart/puli/style.css', 'style.css']; - yield ['/webmozart/puli/STYLE.CSS', 'STYLE.CSS']; - yield ['/webmozart/puli/style.css/', 'style.css']; - yield ['/webmozart/puli/', 'puli']; - yield ['/webmozart/puli', 'puli']; + yield ['/webmozart/symfony/style.css', 'style.css']; + yield ['/webmozart/symfony/STYLE.CSS', 'STYLE.CSS']; + yield ['/webmozart/symfony/style.css/', 'style.css']; + yield ['/webmozart/symfony/', 'symfony']; + yield ['/webmozart/symfony', 'symfony']; yield ['/', '']; yield ['', '']; } @@ -253,25 +253,25 @@ public function testGetFilename(string $path, string $filename): void public function provideGetFilenameWithoutExtensionTests(): \Generator { - yield ['/webmozart/puli/style.css.twig', null, 'style.css']; - yield ['/webmozart/puli/style.css.', null, 'style.css']; - yield ['/webmozart/puli/style.css', null, 'style']; - yield ['/webmozart/puli/.style.css', null, '.style']; - yield ['/webmozart/puli/', null, 'puli']; - yield ['/webmozart/puli', null, 'puli']; + yield ['/webmozart/symfony/style.css.twig', null, 'style.css']; + yield ['/webmozart/symfony/style.css.', null, 'style.css']; + yield ['/webmozart/symfony/style.css', null, 'style']; + yield ['/webmozart/symfony/.style.css', null, '.style']; + yield ['/webmozart/symfony/', null, 'symfony']; + yield ['/webmozart/symfony', null, 'symfony']; yield ['/', null, '']; yield ['', null, '']; - yield ['/webmozart/puli/style.css', 'css', 'style']; - yield ['/webmozart/puli/style.css', '.css', 'style']; - yield ['/webmozart/puli/style.css', 'twig', 'style.css']; - yield ['/webmozart/puli/style.css', '.twig', 'style.css']; - yield ['/webmozart/puli/style.css', '', 'style.css']; - yield ['/webmozart/puli/style.css.', '', 'style.css']; - yield ['/webmozart/puli/style.css.', '.', 'style.css']; - yield ['/webmozart/puli/style.css.', '.css', 'style.css']; - yield ['/webmozart/puli/.style.css', 'css', '.style']; - yield ['/webmozart/puli/.style.css', '.css', '.style']; + yield ['/webmozart/symfony/style.css', 'css', 'style']; + yield ['/webmozart/symfony/style.css', '.css', 'style']; + yield ['/webmozart/symfony/style.css', 'twig', 'style.css']; + yield ['/webmozart/symfony/style.css', '.twig', 'style.css']; + yield ['/webmozart/symfony/style.css', '', 'style.css']; + yield ['/webmozart/symfony/style.css.', '', 'style.css']; + yield ['/webmozart/symfony/style.css.', '.', 'style.css']; + yield ['/webmozart/symfony/style.css.', '.css', 'style.css']; + yield ['/webmozart/symfony/.style.css', 'css', '.style']; + yield ['/webmozart/symfony/.style.css', '.css', '.style']; } /** @@ -284,21 +284,21 @@ public function testGetFilenameWithoutExtension(string $path, ?string $extension public function provideGetExtensionTests(): \Generator { - yield ['/webmozart/puli/style.css.twig', false, 'twig']; - yield ['/webmozart/puli/style.css', false, 'css']; - yield ['/webmozart/puli/style.css.', false, '']; - yield ['/webmozart/puli/', false, '']; - yield ['/webmozart/puli', false, '']; + yield ['/webmozart/symfony/style.css.twig', false, 'twig']; + yield ['/webmozart/symfony/style.css', false, 'css']; + yield ['/webmozart/symfony/style.css.', false, '']; + yield ['/webmozart/symfony/', false, '']; + yield ['/webmozart/symfony', false, '']; yield ['/', false, '']; yield ['', false, '']; - yield ['/webmozart/puli/style.CSS', false, 'CSS']; - yield ['/webmozart/puli/style.CSS', true, 'css']; - yield ['/webmozart/puli/style.ÄÖÜ', false, 'ÄÖÜ']; + yield ['/webmozart/symfony/style.CSS', false, 'CSS']; + yield ['/webmozart/symfony/style.CSS', true, 'css']; + yield ['/webmozart/symfony/style.ÄÖÜ', false, 'ÄÖÜ']; if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - yield ['/webmozart/puli/style.ÄÖÜ', true, 'äöü']; + yield ['/webmozart/symfony/style.ÄÖÜ', true, 'äöü']; } } @@ -312,40 +312,40 @@ public function testGetExtension(string $path, bool $forceLowerCase, string $ext public function provideHasExtensionTests(): \Generator { - yield [true, '/webmozart/puli/style.css.twig', null, false]; - yield [true, '/webmozart/puli/style.css', null, false]; - yield [false, '/webmozart/puli/style.css.', null, false]; - yield [false, '/webmozart/puli/', null, false]; - yield [false, '/webmozart/puli', null, false]; + yield [true, '/webmozart/symfony/style.css.twig', null, false]; + yield [true, '/webmozart/symfony/style.css', null, false]; + yield [false, '/webmozart/symfony/style.css.', null, false]; + yield [false, '/webmozart/symfony/', null, false]; + yield [false, '/webmozart/symfony', null, false]; yield [false, '/', null, false]; yield [false, '', null, false]; - yield [true, '/webmozart/puli/style.css.twig', 'twig', false]; - yield [false, '/webmozart/puli/style.css.twig', 'css', false]; - yield [true, '/webmozart/puli/style.css', 'css', false]; - yield [true, '/webmozart/puli/style.css', '.css', false]; - yield [true, '/webmozart/puli/style.css.', '', false]; - yield [false, '/webmozart/puli/', 'ext', false]; - yield [false, '/webmozart/puli', 'ext', false]; + yield [true, '/webmozart/symfony/style.css.twig', 'twig', false]; + yield [false, '/webmozart/symfony/style.css.twig', 'css', false]; + yield [true, '/webmozart/symfony/style.css', 'css', false]; + yield [true, '/webmozart/symfony/style.css', '.css', false]; + yield [true, '/webmozart/symfony/style.css.', '', false]; + yield [false, '/webmozart/symfony/', 'ext', false]; + yield [false, '/webmozart/symfony', 'ext', false]; yield [false, '/', 'ext', false]; yield [false, '', 'ext', false]; - yield [false, '/webmozart/puli/style.css', 'CSS', false]; - yield [true, '/webmozart/puli/style.css', 'CSS', true]; - yield [false, '/webmozart/puli/style.CSS', 'css', false]; - yield [true, '/webmozart/puli/style.CSS', 'css', true]; - yield [true, '/webmozart/puli/style.ÄÖÜ', 'ÄÖÜ', false]; + yield [false, '/webmozart/symfony/style.css', 'CSS', false]; + yield [true, '/webmozart/symfony/style.css', 'CSS', true]; + yield [false, '/webmozart/symfony/style.CSS', 'css', false]; + yield [true, '/webmozart/symfony/style.CSS', 'css', true]; + yield [true, '/webmozart/symfony/style.ÄÖÜ', 'ÄÖÜ', false]; - yield [true, '/webmozart/puli/style.css', ['ext', 'css'], false]; - yield [true, '/webmozart/puli/style.css', ['.ext', '.css'], false]; - yield [true, '/webmozart/puli/style.css.', ['ext', ''], false]; - yield [false, '/webmozart/puli/style.css', ['foo', 'bar', ''], false]; - yield [false, '/webmozart/puli/style.css', ['.foo', '.bar', ''], false]; + yield [true, '/webmozart/symfony/style.css', ['ext', 'css'], false]; + yield [true, '/webmozart/symfony/style.css', ['.ext', '.css'], false]; + yield [true, '/webmozart/symfony/style.css.', ['ext', ''], false]; + yield [false, '/webmozart/symfony/style.css', ['foo', 'bar', ''], false]; + yield [false, '/webmozart/symfony/style.css', ['.foo', '.bar', ''], false]; if (\extension_loaded('mbstring')) { // This can only be tested, when mbstring is installed - yield [true, '/webmozart/puli/style.ÄÖÜ', 'äöü', true]; - yield [true, '/webmozart/puli/style.ÄÖÜ', ['äöü'], true]; + yield [true, '/webmozart/symfony/style.ÄÖÜ', 'äöü', true]; + yield [true, '/webmozart/symfony/style.ÄÖÜ', ['äöü'], true]; } } @@ -361,16 +361,16 @@ public function testHasExtension(bool $hasExtension, string $path, $extension, b public function provideChangeExtensionTests(): \Generator { - yield ['/webmozart/puli/style.css.twig', 'html', '/webmozart/puli/style.css.html']; - yield ['/webmozart/puli/style.css', 'sass', '/webmozart/puli/style.sass']; - yield ['/webmozart/puli/style.css', '.sass', '/webmozart/puli/style.sass']; - yield ['/webmozart/puli/style.css', '', '/webmozart/puli/style.']; - yield ['/webmozart/puli/style.css.', 'twig', '/webmozart/puli/style.css.twig']; - yield ['/webmozart/puli/style.css.', '', '/webmozart/puli/style.css.']; - yield ['/webmozart/puli/style.css', 'äöü', '/webmozart/puli/style.äöü']; - yield ['/webmozart/puli/style.äöü', 'css', '/webmozart/puli/style.css']; - yield ['/webmozart/puli/', 'css', '/webmozart/puli/']; - yield ['/webmozart/puli', 'css', '/webmozart/puli.css']; + yield ['/webmozart/symfony/style.css.twig', 'html', '/webmozart/symfony/style.css.html']; + yield ['/webmozart/symfony/style.css', 'sass', '/webmozart/symfony/style.sass']; + yield ['/webmozart/symfony/style.css', '.sass', '/webmozart/symfony/style.sass']; + yield ['/webmozart/symfony/style.css', '', '/webmozart/symfony/style.']; + yield ['/webmozart/symfony/style.css.', 'twig', '/webmozart/symfony/style.css.twig']; + yield ['/webmozart/symfony/style.css.', '', '/webmozart/symfony/style.css.']; + yield ['/webmozart/symfony/style.css', 'äöü', '/webmozart/symfony/style.äöü']; + yield ['/webmozart/symfony/style.äöü', 'css', '/webmozart/symfony/style.css']; + yield ['/webmozart/symfony/', 'css', '/webmozart/symfony/']; + yield ['/webmozart/symfony', 'css', '/webmozart/symfony.css']; yield ['/', 'css', '/']; yield ['', 'css', '']; } @@ -465,9 +465,9 @@ public function testGetRoot(string $path, string $root): void public function providePathTests(): \Generator { // relative to absolute path - yield ['css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; - yield ['../css/style.css', '/webmozart/puli', '/webmozart/css/style.css']; - yield ['../../css/style.css', '/webmozart/puli', '/css/style.css']; + yield ['css/style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css']; + yield ['../css/style.css', '/webmozart/symfony', '/webmozart/css/style.css']; + yield ['../../css/style.css', '/webmozart/symfony', '/css/style.css']; // relative to root yield ['css/style.css', '/', '/css/style.css']; @@ -475,10 +475,10 @@ public function providePathTests(): \Generator yield ['css/style.css', 'C:/', 'C:/css/style.css']; // same sub directories in different base directories - yield ['../../puli/css/style.css', '/webmozart/css', '/puli/css/style.css']; + yield ['../../symfony/css/style.css', '/webmozart/css', '/symfony/css/style.css']; - yield ['', '/webmozart/puli', '/webmozart/puli']; - yield ['..', '/webmozart/puli', '/webmozart']; + yield ['', '/webmozart/symfony', '/webmozart/symfony']; + yield ['..', '/webmozart/symfony', '/webmozart']; } public function provideMakeAbsoluteTests(): \Generator @@ -488,17 +488,17 @@ public function provideMakeAbsoluteTests(): \Generator } // collapse dots - yield ['css/./style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; - yield ['css/../style.css', '/webmozart/puli', '/webmozart/puli/style.css']; - yield ['css/./../style.css', '/webmozart/puli', '/webmozart/puli/style.css']; - yield ['css/.././style.css', '/webmozart/puli', '/webmozart/puli/style.css']; - yield ['./css/style.css', '/webmozart/puli', '/webmozart/puli/css/style.css']; - - yield ['css\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css']; - yield ['css\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; - yield ['css\\.\\..\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; - yield ['css\\..\\.\\style.css', '\\webmozart\\puli', '/webmozart/puli/style.css']; - yield ['.\\css\\style.css', '\\webmozart\\puli', '/webmozart/puli/css/style.css']; + yield ['css/./style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css']; + yield ['css/../style.css', '/webmozart/symfony', '/webmozart/symfony/style.css']; + yield ['css/./../style.css', '/webmozart/symfony', '/webmozart/symfony/style.css']; + yield ['css/.././style.css', '/webmozart/symfony', '/webmozart/symfony/style.css']; + yield ['./css/style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css']; + + yield ['css\\.\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/css/style.css']; + yield ['css\\..\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css']; + yield ['css\\.\\..\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css']; + yield ['css\\..\\.\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/style.css']; + yield ['.\\css\\style.css', '\\webmozart\\symfony', '/webmozart/symfony/css/style.css']; // collapse dots on root yield ['./css/style.css', '/', '/css/style.css']; @@ -544,10 +544,10 @@ public function provideMakeAbsoluteTests(): \Generator yield ['../css/.././style.css', 'phar://C:/', 'phar://C:/style.css']; // absolute paths - yield ['/css/style.css', '/webmozart/puli', '/css/style.css']; - yield ['\\css\\style.css', '/webmozart/puli', '/css/style.css']; - yield ['C:/css/style.css', 'C:/webmozart/puli', 'C:/css/style.css']; - yield ['D:\\css\\style.css', 'D:/webmozart/puli', 'D:/css/style.css']; + yield ['/css/style.css', '/webmozart/symfony', '/css/style.css']; + yield ['\\css\\style.css', '/webmozart/symfony', '/css/style.css']; + yield ['C:/css/style.css', 'C:/webmozart/symfony', 'C:/css/style.css']; + yield ['D:\\css\\style.css', 'D:/webmozart/symfony', 'D:/css/style.css']; } /** @@ -561,9 +561,9 @@ public function testMakeAbsolute(string $relativePath, string $basePath, string public function testMakeAbsoluteFailsIfBasePathNotAbsolute(): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The base path "webmozart/puli" is not an absolute path.'); + $this->expectExceptionMessage('The base path "webmozart/symfony" is not an absolute path.'); - Path::makeAbsolute('css/style.css', 'webmozart/puli'); + Path::makeAbsolute('css/style.css', 'webmozart/symfony'); } public function testMakeAbsoluteFailsIfBasePathEmpty(): void @@ -576,28 +576,28 @@ public function testMakeAbsoluteFailsIfBasePathEmpty(): void public function provideAbsolutePathsWithDifferentRoots(): \Generator { - yield ['C:/css/style.css', '/webmozart/puli']; - yield ['C:/css/style.css', '\\webmozart\\puli']; - yield ['C:\\css\\style.css', '/webmozart/puli']; - yield ['C:\\css\\style.css', '\\webmozart\\puli']; - - yield ['/css/style.css', 'C:/webmozart/puli']; - yield ['/css/style.css', 'C:\\webmozart\\puli']; - yield ['\\css\\style.css', 'C:/webmozart/puli']; - yield ['\\css\\style.css', 'C:\\webmozart\\puli']; - - yield ['D:/css/style.css', 'C:/webmozart/puli']; - yield ['D:/css/style.css', 'C:\\webmozart\\puli']; - yield ['D:\\css\\style.css', 'C:/webmozart/puli']; - yield ['D:\\css\\style.css', 'C:\\webmozart\\puli']; - - yield ['phar:///css/style.css', '/webmozart/puli']; - yield ['/css/style.css', 'phar:///webmozart/puli']; - - yield ['phar://C:/css/style.css', 'C:/webmozart/puli']; - yield ['phar://C:/css/style.css', 'C:\\webmozart\\puli']; - yield ['phar://C:\\css\\style.css', 'C:/webmozart/puli']; - yield ['phar://C:\\css\\style.css', 'C:\\webmozart\\puli']; + yield ['C:/css/style.css', '/webmozart/symfony']; + yield ['C:/css/style.css', '\\webmozart\\symfony']; + yield ['C:\\css\\style.css', '/webmozart/symfony']; + yield ['C:\\css\\style.css', '\\webmozart\\symfony']; + + yield ['/css/style.css', 'C:/webmozart/symfony']; + yield ['/css/style.css', 'C:\\webmozart\\symfony']; + yield ['\\css\\style.css', 'C:/webmozart/symfony']; + yield ['\\css\\style.css', 'C:\\webmozart\\symfony']; + + yield ['D:/css/style.css', 'C:/webmozart/symfony']; + yield ['D:/css/style.css', 'C:\\webmozart\\symfony']; + yield ['D:\\css\\style.css', 'C:/webmozart/symfony']; + yield ['D:\\css\\style.css', 'C:\\webmozart\\symfony']; + + yield ['phar:///css/style.css', '/webmozart/symfony']; + yield ['/css/style.css', 'phar:///webmozart/symfony']; + + yield ['phar://C:/css/style.css', 'C:/webmozart/symfony']; + yield ['phar://C:/css/style.css', 'C:\\webmozart\\symfony']; + yield ['phar://C:\\css\\style.css', 'C:/webmozart/symfony']; + yield ['phar://C:\\css\\style.css', 'C:\\webmozart\\symfony']; } /** @@ -616,42 +616,42 @@ public function provideMakeRelativeTests(): \Generator yield [$set[2], $set[1], $set[0]]; } - yield ['/webmozart/puli/./css/style.css', '/webmozart/puli', 'css/style.css']; - yield ['/webmozart/puli/../css/style.css', '/webmozart/puli', '../css/style.css']; - yield ['/webmozart/puli/.././css/style.css', '/webmozart/puli', '../css/style.css']; - yield ['/webmozart/puli/./../css/style.css', '/webmozart/puli', '../css/style.css']; - yield ['/webmozart/puli/../../css/style.css', '/webmozart/puli', '../../css/style.css']; - yield ['/webmozart/puli/css/style.css', '/webmozart/./puli', 'css/style.css']; - yield ['/webmozart/puli/css/style.css', '/webmozart/../puli', '../webmozart/puli/css/style.css']; - yield ['/webmozart/puli/css/style.css', '/webmozart/./../puli', '../webmozart/puli/css/style.css']; - yield ['/webmozart/puli/css/style.css', '/webmozart/.././puli', '../webmozart/puli/css/style.css']; - yield ['/webmozart/puli/css/style.css', '/webmozart/../../puli', '../webmozart/puli/css/style.css']; + yield ['/webmozart/symfony/./css/style.css', '/webmozart/symfony', 'css/style.css']; + yield ['/webmozart/symfony/../css/style.css', '/webmozart/symfony', '../css/style.css']; + yield ['/webmozart/symfony/.././css/style.css', '/webmozart/symfony', '../css/style.css']; + yield ['/webmozart/symfony/./../css/style.css', '/webmozart/symfony', '../css/style.css']; + yield ['/webmozart/symfony/../../css/style.css', '/webmozart/symfony', '../../css/style.css']; + yield ['/webmozart/symfony/css/style.css', '/webmozart/./symfony', 'css/style.css']; + yield ['/webmozart/symfony/css/style.css', '/webmozart/../symfony', '../webmozart/symfony/css/style.css']; + yield ['/webmozart/symfony/css/style.css', '/webmozart/./../symfony', '../webmozart/symfony/css/style.css']; + yield ['/webmozart/symfony/css/style.css', '/webmozart/.././symfony', '../webmozart/symfony/css/style.css']; + yield ['/webmozart/symfony/css/style.css', '/webmozart/../../symfony', '../webmozart/symfony/css/style.css']; // first argument shorter than second - yield ['/css', '/webmozart/puli', '../../css']; + yield ['/css', '/webmozart/symfony', '../../css']; // second argument shorter than first - yield ['/webmozart/puli', '/css', '../webmozart/puli']; + yield ['/webmozart/symfony', '/css', '../webmozart/symfony']; - yield ['\\webmozart\\puli\\css\\style.css', '\\webmozart\\puli', 'css/style.css']; - yield ['\\webmozart\\css\\style.css', '\\webmozart\\puli', '../css/style.css']; - yield ['\\css\\style.css', '\\webmozart\\puli', '../../css/style.css']; + yield ['\\webmozart\\symfony\\css\\style.css', '\\webmozart\\symfony', 'css/style.css']; + yield ['\\webmozart\\css\\style.css', '\\webmozart\\symfony', '../css/style.css']; + yield ['\\css\\style.css', '\\webmozart\\symfony', '../../css/style.css']; - yield ['C:/webmozart/puli/css/style.css', 'C:/webmozart/puli', 'css/style.css']; - yield ['C:/webmozart/css/style.css', 'C:/webmozart/puli', '../css/style.css']; - yield ['C:/css/style.css', 'C:/webmozart/puli', '../../css/style.css']; + yield ['C:/webmozart/symfony/css/style.css', 'C:/webmozart/symfony', 'css/style.css']; + yield ['C:/webmozart/css/style.css', 'C:/webmozart/symfony', '../css/style.css']; + yield ['C:/css/style.css', 'C:/webmozart/symfony', '../../css/style.css']; - yield ['C:\\webmozart\\puli\\css\\style.css', 'C:\\webmozart\\puli', 'css/style.css']; - yield ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\puli', '../css/style.css']; - yield ['C:\\css\\style.css', 'C:\\webmozart\\puli', '../../css/style.css']; + yield ['C:\\webmozart\\symfony\\css\\style.css', 'C:\\webmozart\\symfony', 'css/style.css']; + yield ['C:\\webmozart\\css\\style.css', 'C:\\webmozart\\symfony', '../css/style.css']; + yield ['C:\\css\\style.css', 'C:\\webmozart\\symfony', '../../css/style.css']; - yield ['phar:///webmozart/puli/css/style.css', 'phar:///webmozart/puli', 'css/style.css']; - yield ['phar:///webmozart/css/style.css', 'phar:///webmozart/puli', '../css/style.css']; - yield ['phar:///css/style.css', 'phar:///webmozart/puli', '../../css/style.css']; + yield ['phar:///webmozart/symfony/css/style.css', 'phar:///webmozart/symfony', 'css/style.css']; + yield ['phar:///webmozart/css/style.css', 'phar:///webmozart/symfony', '../css/style.css']; + yield ['phar:///css/style.css', 'phar:///webmozart/symfony', '../../css/style.css']; - yield ['phar://C:/webmozart/puli/css/style.css', 'phar://C:/webmozart/puli', 'css/style.css']; - yield ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/puli', '../css/style.css']; - yield ['phar://C:/css/style.css', 'phar://C:/webmozart/puli', '../../css/style.css']; + yield ['phar://C:/webmozart/symfony/css/style.css', 'phar://C:/webmozart/symfony', 'css/style.css']; + yield ['phar://C:/webmozart/css/style.css', 'phar://C:/webmozart/symfony', '../css/style.css']; + yield ['phar://C:/css/style.css', 'phar://C:/webmozart/symfony', '../../css/style.css']; // already relative + already in root basepath yield ['../style.css', '/', 'style.css']; @@ -687,20 +687,20 @@ public function provideMakeRelativeTests(): \Generator yield ['css\\.\\style.css', 'phar://C:\\', 'css/style.css']; // already relative - yield ['css/style.css', '/webmozart/puli', 'css/style.css']; - yield ['css\\style.css', '\\webmozart\\puli', 'css/style.css']; + yield ['css/style.css', '/webmozart/symfony', 'css/style.css']; + yield ['css\\style.css', '\\webmozart\\symfony', 'css/style.css']; // both relative - yield ['css/style.css', 'webmozart/puli', '../../css/style.css']; - yield ['css\\style.css', 'webmozart\\puli', '../../css/style.css']; + yield ['css/style.css', 'webmozart/symfony', '../../css/style.css']; + yield ['css\\style.css', 'webmozart\\symfony', '../../css/style.css']; // relative to empty yield ['css/style.css', '', 'css/style.css']; yield ['css\\style.css', '', 'css/style.css']; // different slashes in path and base path - yield ['/webmozart/puli/css/style.css', '\\webmozart\\puli', 'css/style.css']; - yield ['\\webmozart\\puli\\css\\style.css', '/webmozart/puli', 'css/style.css']; + yield ['/webmozart/symfony/css/style.css', '\\webmozart\\symfony', 'css/style.css']; + yield ['\\webmozart\\symfony\\css\\style.css', '/webmozart/symfony', 'css/style.css']; } /** @@ -714,17 +714,17 @@ public function testMakeRelative(string $absolutePath, string $basePath, string public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute(): void { $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "webmozart/puli". You should provide an absolute base path instead.'); + $this->expectExceptionMessage('The absolute path "/webmozart/symfony/css/style.css" cannot be made relative to the relative path "webmozart/symfony". You should provide an absolute base path instead.'); - Path::makeRelative('/webmozart/puli/css/style.css', 'webmozart/puli'); + Path::makeRelative('/webmozart/symfony/css/style.css', 'webmozart/symfony'); } public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty(): void { - $this->expectExceptionMessage('The absolute path "/webmozart/puli/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.'); + $this->expectExceptionMessage('The absolute path "/webmozart/symfony/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.'); - Path::makeRelative('/webmozart/puli/css/style.css', ''); + Path::makeRelative('/webmozart/symfony/css/style.css', ''); } /** @@ -871,7 +871,7 @@ public function provideGetLongestCommonBasePathTests(): \Generator */ public function testGetLongestCommonBasePath(array $paths, ?string $basePath): void { - $this->assertSame($basePath, Path::getLongestCommonBasePath($paths)); + $this->assertSame($basePath, Path::getLongestCommonBasePath(...$paths)); } public function provideIsBasePathTests(): \Generator From 1f5bd75a65e0a8cee3b7e0f493da69f434456da5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 11:54:53 +0200 Subject: [PATCH 06/21] Replace static usages by self --- src/Symfony/Component/Filesystem/Path.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 130810faaebc5..3ef962d30029c 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -79,7 +79,7 @@ public static function canonicalize(string $path): string // Replace "~" with user's home directory. if ('~' === $path[0]) { - $path = static::getHomeDirectory().\substr($path, 1); + $path = self::getHomeDirectory().\substr($path, 1); } $path = \str_replace('\\', '/', $path); @@ -169,7 +169,7 @@ public static function getDirectory(string $path): string return ''; } - $path = static::canonicalize($path); + $path = self::canonicalize($path); // Maintain scheme if (false !== ($pos = \strpos($path, '://'))) { @@ -214,12 +214,12 @@ public static function getHomeDirectory(): string { // For UNIX support if (\getenv('HOME')) { - return static::canonicalize(\getenv('HOME')); + return self::canonicalize(\getenv('HOME')); } // For >= Windows8 support if (\getenv('HOMEDRIVE') && \getenv('HOMEPATH')) { - return static::canonicalize(\getenv('HOMEDRIVE').\getenv('HOMEPATH')); + return self::canonicalize(\getenv('HOMEDRIVE').\getenv('HOMEPATH')); } throw new \RuntimeException("Cannot find the home directory path: Your environment or operation system isn't supported"); @@ -437,7 +437,7 @@ public static function isAbsolute(string $path): bool */ public static function isRelative(string $path): bool { - return !static::isAbsolute($path); + return !self::isAbsolute($path); } /** @@ -483,15 +483,15 @@ public static function makeAbsolute(string $path, string $basePath): string throw new \InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); } - if (!static::isAbsolute($basePath)) { + if (!self::isAbsolute($basePath)) { throw new \InvalidArgumentException(\sprintf( 'The base path "%s" is not an absolute path.', $basePath )); } - if (static::isAbsolute($path)) { - return static::canonicalize($path); + if (self::isAbsolute($path)) { + return self::canonicalize($path); } if (false !== ($pos = \strpos($basePath, '://'))) { @@ -556,8 +556,8 @@ public static function makeAbsolute(string $path, string $basePath): string */ public static function makeRelative(string $path, string $basePath): string { - $path = static::canonicalize($path); - $basePath = static::canonicalize($basePath); + $path = self::canonicalize($path); + $basePath = self::canonicalize($basePath); [$root, $relativePath] = self::split($path); [$baseRoot, $relativeBasePath] = self::split($basePath); From 90007138f082dac33303b094655b6acdf7572eff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 12:02:56 +0200 Subject: [PATCH 07/21] Add the mbstring polyfill --- src/Symfony/Component/Filesystem/Path.php | 18 +++--------------- .../Component/Filesystem/Tests/PathTest.php | 13 ++++--------- src/Symfony/Component/Filesystem/composer.json | 3 ++- 3 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 3ef962d30029c..31e21effdbfb9 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -306,8 +306,6 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens * Returns the extension from a file path (without leading dot). * * @param bool $forceLowerCase forces the extension to be lower-case - * (requires mbstring extension for correct - * multi-byte character handling in extension) */ public static function getExtension(string $path, bool $forceLowerCase = false): string { @@ -334,9 +332,6 @@ public static function getExtension(string $path, bool $forceLowerCase = false): * or array of extensions (with or * without leading dot) * @param bool $ignoreCase whether to ignore case-sensitivity - * (requires mbstring extension for - * correct multi-byte character - * handling in the extension) */ public static function hasExtension(string $path, $extensions = null, bool $ignoreCase = false): bool { @@ -578,9 +573,7 @@ public static function makeRelative(string $path, string $basePath): string // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { throw new \InvalidArgumentException(\sprintf( - 'The absolute path "%s" cannot be made relative to the '. - 'relative path "%s". You should provide an absolute base '. - 'path instead.', + 'The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath )); @@ -589,8 +582,7 @@ public static function makeRelative(string $path, string $basePath): string // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { throw new \InvalidArgumentException(\sprintf( - 'The path "%s" cannot be made relative to "%s", because they '. - 'have different roots ("%s" and "%s").', + 'The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, @@ -836,11 +828,7 @@ private static function split(string $path): array */ private static function toLower(string $str): string { - if (\function_exists('mb_strtolower')) { - return \mb_strtolower($str, mb_detect_encoding($str)); - } - - return strtolower($str); + return \mb_strtolower($str, mb_detect_encoding($str)); } private function __construct() diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 8876499ea36db..c875d5954488a 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -296,10 +296,7 @@ public function provideGetExtensionTests(): \Generator yield ['/webmozart/symfony/style.CSS', true, 'css']; yield ['/webmozart/symfony/style.ÄÖÜ', false, 'ÄÖÜ']; - if (\extension_loaded('mbstring')) { - // This can only be tested, when mbstring is installed - yield ['/webmozart/symfony/style.ÄÖÜ', true, 'äöü']; - } + yield ['/webmozart/symfony/style.ÄÖÜ', true, 'äöü']; } /** @@ -342,11 +339,9 @@ public function provideHasExtensionTests(): \Generator yield [false, '/webmozart/symfony/style.css', ['foo', 'bar', ''], false]; yield [false, '/webmozart/symfony/style.css', ['.foo', '.bar', ''], false]; - if (\extension_loaded('mbstring')) { - // This can only be tested, when mbstring is installed - yield [true, '/webmozart/symfony/style.ÄÖÜ', 'äöü', true]; - yield [true, '/webmozart/symfony/style.ÄÖÜ', ['äöü'], true]; - } + // This can only be tested, when mbstring is installed + yield [true, '/webmozart/symfony/style.ÄÖÜ', 'äöü', true]; + yield [true, '/webmozart/symfony/style.ÄÖÜ', ['äöü'], true]; } /** diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 0f0117f3f8561..450a5863fb10f 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": "^7.2.9", - "symfony/polyfill-ctype": "~1.8" + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, From 8838334c3165e647944d539b7eb16bcd58c9338b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 12:04:27 +0200 Subject: [PATCH 08/21] Remove unnused variable --- src/Symfony/Component/Filesystem/Tests/PathTest.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index c875d5954488a..684ccf8d7fdd9 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -375,9 +375,7 @@ public function provideChangeExtensionTests(): \Generator */ public function testChangeExtension(string $path, string $extension, string $pathExpected): void { - static $call = 0; $this->assertSame($pathExpected, Path::changeExtension($path, $extension)); - ++$call; } public function provideIsAbsolutePathTests(): \Generator From ea660f246ef498e29bd80ca3e020d3bc8473ad86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 11 Apr 2019 12:13:35 +0200 Subject: [PATCH 09/21] Fix CS --- src/Symfony/Component/Filesystem/Path.php | 10 +- .../Component/Filesystem/Tests/PathTest.php | 205 +++++++++--------- 2 files changed, 107 insertions(+), 108 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 31e21effdbfb9..9e723e616d02a 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -305,7 +305,7 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens /** * Returns the extension from a file path (without leading dot). * - * @param bool $forceLowerCase forces the extension to be lower-case + * @param bool $forceLowerCase forces the extension to be lower-case */ public static function getExtension(string $path, bool $forceLowerCase = false): string { @@ -469,8 +469,8 @@ public static function isRelative(string $path): bool * @param string $basePath an absolute base path * * @throws \InvalidArgumentException if the base path is not absolute or if - * the given path is an absolute path with - * a different root than the base path + * the given path is an absolute path with + * a different root than the base path */ public static function makeAbsolute(string $path, string $basePath): string { @@ -546,8 +546,8 @@ public static function makeAbsolute(string $path, string $basePath): string * The result is a canonical path. * * @throws \InvalidArgumentException if the base path is not absolute or if - * the given path has a different root - * than the base path + * the given path has a different root + * than the base path */ public static function makeRelative(string $path, string $basePath): string { diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 684ccf8d7fdd9..46db5e542d4ff 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -43,124 +43,124 @@ public function tearDown(): void public function provideCanonicalizationTests(): \Generator { // relative paths (forward slash) - yield ['css/./style.css', 'css/style.css']; - yield ['css/../style.css', 'style.css']; - yield ['css/./../style.css', 'style.css']; - yield ['css/.././style.css', 'style.css']; - yield ['css/../../style.css', '../style.css']; - yield ['./css/style.css', 'css/style.css']; - yield ['../css/style.css', '../css/style.css']; - yield ['./../css/style.css', '../css/style.css']; - yield ['.././css/style.css', '../css/style.css']; - yield ['../../css/style.css', '../../css/style.css']; - yield ['', '']; - yield ['.', '']; - yield ['..', '..']; - yield ['./..', '..']; - yield ['../.', '..']; - yield ['../..', '../..']; + yield ['css/./style.css', 'css/style.css']; + yield ['css/../style.css', 'style.css']; + yield ['css/./../style.css', 'style.css']; + yield ['css/.././style.css', 'style.css']; + yield ['css/../../style.css', '../style.css']; + yield ['./css/style.css', 'css/style.css']; + yield ['../css/style.css', '../css/style.css']; + yield ['./../css/style.css', '../css/style.css']; + yield ['.././css/style.css', '../css/style.css']; + yield ['../../css/style.css', '../../css/style.css']; + yield ['', '']; + yield ['.', '']; + yield ['..', '..']; + yield ['./..', '..']; + yield ['../.', '..']; + yield ['../..', '../..']; // relative paths (backslash) - yield ['css\\.\\style.css', 'css/style.css']; - yield ['css\\..\\style.css', 'style.css']; - yield ['css\\.\\..\\style.css', 'style.css']; - yield ['css\\..\\.\\style.css', 'style.css']; - yield ['css\\..\\..\\style.css', '../style.css']; - yield ['.\\css\\style.css', 'css/style.css']; - yield ['..\\css\\style.css', '../css/style.css']; - yield ['.\\..\\css\\style.css', '../css/style.css']; - yield ['..\\.\\css\\style.css', '../css/style.css']; - yield ['..\\..\\css\\style.css', '../../css/style.css']; + yield ['css\\.\\style.css', 'css/style.css']; + yield ['css\\..\\style.css', 'style.css']; + yield ['css\\.\\..\\style.css', 'style.css']; + yield ['css\\..\\.\\style.css', 'style.css']; + yield ['css\\..\\..\\style.css', '../style.css']; + yield ['.\\css\\style.css', 'css/style.css']; + yield ['..\\css\\style.css', '../css/style.css']; + yield ['.\\..\\css\\style.css', '../css/style.css']; + yield ['..\\.\\css\\style.css', '../css/style.css']; + yield ['..\\..\\css\\style.css', '../../css/style.css']; // absolute paths (forward slash, UNIX) - yield ['/css/style.css', '/css/style.css']; - yield ['/css/./style.css', '/css/style.css']; - yield ['/css/../style.css', '/style.css']; - yield ['/css/./../style.css', '/style.css']; - yield ['/css/.././style.css', '/style.css']; - yield ['/./css/style.css', '/css/style.css']; - yield ['/../css/style.css', '/css/style.css']; - yield ['/./../css/style.css', '/css/style.css']; - yield ['/.././css/style.css', '/css/style.css']; - yield ['/../../css/style.css', '/css/style.css']; + yield ['/css/style.css', '/css/style.css']; + yield ['/css/./style.css', '/css/style.css']; + yield ['/css/../style.css', '/style.css']; + yield ['/css/./../style.css', '/style.css']; + yield ['/css/.././style.css', '/style.css']; + yield ['/./css/style.css', '/css/style.css']; + yield ['/../css/style.css', '/css/style.css']; + yield ['/./../css/style.css', '/css/style.css']; + yield ['/.././css/style.css', '/css/style.css']; + yield ['/../../css/style.css', '/css/style.css']; // absolute paths (backslash, UNIX) - yield ['\\css\\style.css', '/css/style.css']; - yield ['\\css\\.\\style.css', '/css/style.css']; - yield ['\\css\\..\\style.css', '/style.css']; - yield ['\\css\\.\\..\\style.css', '/style.css']; - yield ['\\css\\..\\.\\style.css', '/style.css']; - yield ['\\.\\css\\style.css', '/css/style.css']; - yield ['\\..\\css\\style.css', '/css/style.css']; - yield ['\\.\\..\\css\\style.css', '/css/style.css']; - yield ['\\..\\.\\css\\style.css', '/css/style.css']; - yield ['\\..\\..\\css\\style.css', '/css/style.css']; + yield ['\\css\\style.css', '/css/style.css']; + yield ['\\css\\.\\style.css', '/css/style.css']; + yield ['\\css\\..\\style.css', '/style.css']; + yield ['\\css\\.\\..\\style.css', '/style.css']; + yield ['\\css\\..\\.\\style.css', '/style.css']; + yield ['\\.\\css\\style.css', '/css/style.css']; + yield ['\\..\\css\\style.css', '/css/style.css']; + yield ['\\.\\..\\css\\style.css', '/css/style.css']; + yield ['\\..\\.\\css\\style.css', '/css/style.css']; + yield ['\\..\\..\\css\\style.css', '/css/style.css']; // absolute paths (forward slash, Windows) - yield ['C:/css/style.css', 'C:/css/style.css']; - yield ['C:/css/./style.css', 'C:/css/style.css']; - yield ['C:/css/../style.css', 'C:/style.css']; - yield ['C:/css/./../style.css', 'C:/style.css']; - yield ['C:/css/.././style.css', 'C:/style.css']; - yield ['C:/./css/style.css', 'C:/css/style.css']; - yield ['C:/../css/style.css', 'C:/css/style.css']; - yield ['C:/./../css/style.css', 'C:/css/style.css']; - yield ['C:/.././css/style.css', 'C:/css/style.css']; - yield ['C:/../../css/style.css', 'C:/css/style.css']; + yield ['C:/css/style.css', 'C:/css/style.css']; + yield ['C:/css/./style.css', 'C:/css/style.css']; + yield ['C:/css/../style.css', 'C:/style.css']; + yield ['C:/css/./../style.css', 'C:/style.css']; + yield ['C:/css/.././style.css', 'C:/style.css']; + yield ['C:/./css/style.css', 'C:/css/style.css']; + yield ['C:/../css/style.css', 'C:/css/style.css']; + yield ['C:/./../css/style.css', 'C:/css/style.css']; + yield ['C:/.././css/style.css', 'C:/css/style.css']; + yield ['C:/../../css/style.css', 'C:/css/style.css']; // absolute paths (backslash, Windows) - yield ['C:\\css\\style.css', 'C:/css/style.css']; - yield ['C:\\css\\.\\style.css', 'C:/css/style.css']; - yield ['C:\\css\\..\\style.css', 'C:/style.css']; - yield ['C:\\css\\.\\..\\style.css', 'C:/style.css']; - yield ['C:\\css\\..\\.\\style.css', 'C:/style.css']; - yield ['C:\\.\\css\\style.css', 'C:/css/style.css']; - yield ['C:\\..\\css\\style.css', 'C:/css/style.css']; - yield ['C:\\.\\..\\css\\style.css', 'C:/css/style.css']; - yield ['C:\\..\\.\\css\\style.css', 'C:/css/style.css']; - yield ['C:\\..\\..\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\css\\.\\style.css', 'C:/css/style.css']; + yield ['C:\\css\\..\\style.css', 'C:/style.css']; + yield ['C:\\css\\.\\..\\style.css', 'C:/style.css']; + yield ['C:\\css\\..\\.\\style.css', 'C:/style.css']; + yield ['C:\\.\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\.\\..\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\.\\css\\style.css', 'C:/css/style.css']; + yield ['C:\\..\\..\\css\\style.css', 'C:/css/style.css']; // Windows special case - yield ['C:', 'C:/']; + yield ['C:', 'C:/']; // Don't change malformed path - yield ['C:css/style.css', 'C:css/style.css']; + yield ['C:css/style.css', 'C:css/style.css']; // absolute paths (stream, UNIX) - yield ['phar:///css/style.css', 'phar:///css/style.css']; - yield ['phar:///css/./style.css', 'phar:///css/style.css']; - yield ['phar:///css/../style.css', 'phar:///style.css']; - yield ['phar:///css/./../style.css', 'phar:///style.css']; - yield ['phar:///css/.././style.css', 'phar:///style.css']; - yield ['phar:///./css/style.css', 'phar:///css/style.css']; - yield ['phar:///../css/style.css', 'phar:///css/style.css']; - yield ['phar:///./../css/style.css', 'phar:///css/style.css']; - yield ['phar:///.././css/style.css', 'phar:///css/style.css']; - yield ['phar:///../../css/style.css', 'phar:///css/style.css']; + yield ['phar:///css/style.css', 'phar:///css/style.css']; + yield ['phar:///css/./style.css', 'phar:///css/style.css']; + yield ['phar:///css/../style.css', 'phar:///style.css']; + yield ['phar:///css/./../style.css', 'phar:///style.css']; + yield ['phar:///css/.././style.css', 'phar:///style.css']; + yield ['phar:///./css/style.css', 'phar:///css/style.css']; + yield ['phar:///../css/style.css', 'phar:///css/style.css']; + yield ['phar:///./../css/style.css', 'phar:///css/style.css']; + yield ['phar:///.././css/style.css', 'phar:///css/style.css']; + yield ['phar:///../../css/style.css', 'phar:///css/style.css']; // absolute paths (stream, Windows) - yield ['phar://C:/css/style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/css/./style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/css/../style.css', 'phar://C:/style.css']; - yield ['phar://C:/css/./../style.css', 'phar://C:/style.css']; - yield ['phar://C:/css/.././style.css', 'phar://C:/style.css']; - yield ['phar://C:/./css/style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/../css/style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/./../css/style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/.././css/style.css', 'phar://C:/css/style.css']; - yield ['phar://C:/../../css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/css/./style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/css/../style.css', 'phar://C:/style.css']; + yield ['phar://C:/css/./../style.css', 'phar://C:/style.css']; + yield ['phar://C:/css/.././style.css', 'phar://C:/style.css']; + yield ['phar://C:/./css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/../css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/./../css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/.././css/style.css', 'phar://C:/css/style.css']; + yield ['phar://C:/../../css/style.css', 'phar://C:/css/style.css']; // paths with "~" UNIX - yield ['~/css/style.css', '/home/webmozart/css/style.css']; - yield ['~/css/./style.css', '/home/webmozart/css/style.css']; - yield ['~/css/../style.css', '/home/webmozart/style.css']; - yield ['~/css/./../style.css', '/home/webmozart/style.css']; - yield ['~/css/.././style.css', '/home/webmozart/style.css']; - yield ['~/./css/style.css', '/home/webmozart/css/style.css']; - yield ['~/../css/style.css', '/home/css/style.css']; - yield ['~/./../css/style.css', '/home/css/style.css']; - yield ['~/.././css/style.css', '/home/css/style.css']; - yield ['~/../../css/style.css', '/css/style.css']; + yield ['~/css/style.css', '/home/webmozart/css/style.css']; + yield ['~/css/./style.css', '/home/webmozart/css/style.css']; + yield ['~/css/../style.css', '/home/webmozart/style.css']; + yield ['~/css/./../style.css', '/home/webmozart/style.css']; + yield ['~/css/.././style.css', '/home/webmozart/style.css']; + yield ['~/./css/style.css', '/home/webmozart/css/style.css']; + yield ['~/../css/style.css', '/home/css/style.css']; + yield ['~/./../css/style.css', '/home/css/style.css']; + yield ['~/.././css/style.css', '/home/css/style.css']; + yield ['~/../../css/style.css', '/css/style.css']; } /** @@ -479,7 +479,7 @@ public function provideMakeAbsoluteTests(): \Generator foreach ($this->providePathTests() as $set) { yield $set; } - + // collapse dots yield ['css/./style.css', '/webmozart/symfony', '/webmozart/symfony/css/style.css']; yield ['css/../style.css', '/webmozart/symfony', '/webmozart/symfony/style.css']; @@ -608,7 +608,7 @@ public function provideMakeRelativeTests(): \Generator foreach ($this->providePathTests() as $set) { yield [$set[2], $set[1], $set[0]]; } - + yield ['/webmozart/symfony/./css/style.css', '/webmozart/symfony', 'css/style.css']; yield ['/webmozart/symfony/../css/style.css', '/webmozart/symfony', '../css/style.css']; yield ['/webmozart/symfony/.././css/style.css', '/webmozart/symfony', '../css/style.css']; @@ -714,7 +714,6 @@ public function testMakeRelativeFailsIfAbsolutePathAndBasePathNotAbsolute(): voi public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty(): void { - $this->expectExceptionMessage('The absolute path "/webmozart/symfony/css/style.css" cannot be made relative to the relative path "". You should provide an absolute base path instead.'); Path::makeRelative('/webmozart/symfony/css/style.css', ''); @@ -726,7 +725,7 @@ public function testMakeRelativeFailsIfAbsolutePathAndBasePathEmpty(): void public function testMakeRelativeFailsIfDifferentRoot(string $absolutePath, string $basePath): void { $this->expectException(\InvalidArgumentException::class); - + Path::makeRelative($absolutePath, $basePath); } @@ -859,7 +858,7 @@ public function provideGetLongestCommonBasePathTests(): \Generator /** * @dataProvider provideGetLongestCommonBasePathTests - * + * * @param string[] $paths */ public function testGetLongestCommonBasePath(array $paths, ?string $basePath): void From b73b2f1066e022c7f3799d926f5b97e55404d205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Sun, 9 Jun 2019 19:53:11 +0200 Subject: [PATCH 10/21] Fix CS --- src/Symfony/Component/Filesystem/Path.php | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 9e723e616d02a..71bd6100c0007 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -479,10 +479,7 @@ public static function makeAbsolute(string $path, string $basePath): string } if (!self::isAbsolute($basePath)) { - throw new \InvalidArgumentException(\sprintf( - 'The base path "%s" is not an absolute path.', - $basePath - )); + throw new \InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath)); } if (self::isAbsolute($path)) { @@ -572,22 +569,12 @@ public static function makeRelative(string $path, string $basePath): string // If the passed path is absolute, but the base path is not, we // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { - throw new \InvalidArgumentException(\sprintf( - 'The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', - $path, - $basePath - )); + throw new \InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); } // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { - throw new \InvalidArgumentException(\sprintf( - 'The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', - $path, - $basePath, - $root, - $baseRoot - )); + throw new \InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); } if ('' === $relativeBasePath) { From 329cf39e04af31acc484930a336671e30284447f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:09:40 +0200 Subject: [PATCH 11/21] Use the Filesystem exceptions instead of the PHP root ones --- .../Exception/RuntimeArgumentException.php | 19 +++++++++++++++++ src/Symfony/Component/Filesystem/Path.php | 21 +++++++++++-------- 2 files changed, 31 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Filesystem/Exception/RuntimeArgumentException.php diff --git a/src/Symfony/Component/Filesystem/Exception/RuntimeArgumentException.php b/src/Symfony/Component/Filesystem/Exception/RuntimeArgumentException.php new file mode 100644 index 0000000000000..0172e460c5334 --- /dev/null +++ b/src/Symfony/Component/Filesystem/Exception/RuntimeArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * @author Théo Fidry + */ +class RuntimeArgumentException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 71bd6100c0007..79b2f0bca7a7c 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Filesystem; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; +use Symfony\Component\Filesystem\ExceptionInvalidArgumentException; + /** * Contains utility methods for handling path strings. * @@ -459,7 +462,7 @@ public static function isRelative(string $path): bool * // => C:/style.css * * Path::makeAbsolute("C:/style.css", "/webmozart/puli/css"); - * // \InvalidArgumentException + * // InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. @@ -468,18 +471,18 @@ public static function isRelative(string $path): bool * * @param string $basePath an absolute base path * - * @throws \InvalidArgumentException if the base path is not absolute or if + * @throws InvalidArgumentException if the base path is not absolute or if * the given path is an absolute path with * a different root than the base path */ public static function makeAbsolute(string $path, string $basePath): string { if ('' === $basePath) { - throw new \InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); + throw new InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); } if (!self::isAbsolute($basePath)) { - throw new \InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath)); + throw new InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath)); } if (self::isAbsolute($path)) { @@ -527,7 +530,7 @@ public static function makeAbsolute(string $path, string $basePath): string * * ```php * Path::makeRelative("C:/webmozart/style.css", "/webmozart/puli"); - * // \InvalidArgumentException + * // InvalidArgumentException * ``` * * If the passed path is absolute, but the base path is not, an exception @@ -535,14 +538,14 @@ public static function makeAbsolute(string $path, string $basePath): string * * ```php * Path::makeRelative("/webmozart/style.css", "webmozart/puli"); - * // \InvalidArgumentException + * // InvalidArgumentException * ``` * * If the base path is not an absolute path, an exception is thrown. * * The result is a canonical path. * - * @throws \InvalidArgumentException if the base path is not absolute or if + * @throws InvalidArgumentException if the base path is not absolute or if * the given path has a different root * than the base path */ @@ -569,12 +572,12 @@ public static function makeRelative(string $path, string $basePath): string // If the passed path is absolute, but the base path is not, we // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { - throw new \InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); + throw new InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); } // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { - throw new \InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); + throw new InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); } if ('' === $relativeBasePath) { From 928a0dffd5b895eb6ea1097f8e72417494f7a5c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:10:12 +0200 Subject: [PATCH 12/21] Add myself as an author --- src/Symfony/Component/Filesystem/Path.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 79b2f0bca7a7c..0bed24c40d8b4 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -23,6 +23,7 @@ * * @author Bernhard Schussek * @author Thomas Schulz + * @author Théo Fidry */ final class Path { From e8f857cd019d25172c9ba8f776a69326ca5785fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:12:29 +0200 Subject: [PATCH 13/21] Remove getFilename() --- src/Symfony/Component/Filesystem/Path.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 0bed24c40d8b4..22bca07bc772b 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -274,18 +274,6 @@ public static function getRoot(string $path): string return ''; } - /** - * Returns the file name from a file path. - */ - public static function getFilename(string $path): string - { - if ('' === $path) { - return ''; - } - - return \basename($path); - } - /** * Returns the file name without the extension from a file path. * From 838727bfa8186ed7afa72fa43954ad1756965d99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:14:09 +0200 Subject: [PATCH 14/21] Use long lines --- src/Symfony/Component/Filesystem/Path.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 22bca07bc772b..981f8c9e1cbd3 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -101,9 +101,7 @@ public static function canonicalize(string $path): string // Collapse ".." with the previous part, if one exists // Don't collapse ".." if the previous part is also ".." - if ('..' === $part && \count($canonicalParts) > 0 - && '..' !== $canonicalParts[\count($canonicalParts) - 1] - ) { + if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) { \array_pop($canonicalParts); continue; @@ -686,7 +684,7 @@ public static function join(string ...$paths): string $wasScheme = false; foreach ($paths as $path) { - $path = (string) $path; + $path = $path; if ('' === $path) { continue; From e9b70350e5473a53b1e0e09ab8b02d68075ca393 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:15:05 +0200 Subject: [PATCH 15/21] Mark Path as experimental --- src/Symfony/Component/Filesystem/Path.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 981f8c9e1cbd3..63a46d0b09980 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -24,6 +24,8 @@ * @author Bernhard Schussek * @author Thomas Schulz * @author Théo Fidry + * + * @experimental in 4.4 */ final class Path { From 42c6d728a98579ea21b9a834fde6b44135b91bd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:16:33 +0200 Subject: [PATCH 16/21] Remove non-useful phpdoc --- src/Symfony/Component/Filesystem/Path.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 63a46d0b09980..286e55c4a1474 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -47,8 +47,6 @@ final class Path private static $buffer = []; /** - * The size of the buffer. - * * @var int */ private static $bufferSize = 0; @@ -384,9 +382,6 @@ public static function changeExtension(string $path, string $extension): string return \substr($path, 0, -\strlen($actualExtension)).$extension; } - /** - * Returns whether a path is absolute. - */ public static function isAbsolute(string $path): bool { if ('' === $path) { @@ -419,9 +414,6 @@ public static function isAbsolute(string $path): bool return false; } - /** - * Returns whether or not a path is relative. - */ public static function isRelative(string $path): bool { return !self::isAbsolute($path); @@ -802,9 +794,6 @@ private static function split(string $path): array return [$root, $path]; } - /** - * Converts string to lower-case. - */ private static function toLower(string $str): string { return \mb_strtolower($str, mb_detect_encoding($str)); From 8113090b731f79372cf2c3d5a4961df24119a5a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:18:42 +0200 Subject: [PATCH 17/21] Fix PathTest --- .../Component/Filesystem/Tests/PathTest.php | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 46db5e542d4ff..04ea2e84ecdf0 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -232,25 +232,6 @@ public function testGetDirectory(string $path, string $directory): void $this->assertSame($directory, Path::getDirectory($path)); } - public function provideGetFilenameTests(): \Generator - { - yield ['/webmozart/symfony/style.css', 'style.css']; - yield ['/webmozart/symfony/STYLE.CSS', 'STYLE.CSS']; - yield ['/webmozart/symfony/style.css/', 'style.css']; - yield ['/webmozart/symfony/', 'symfony']; - yield ['/webmozart/symfony', 'symfony']; - yield ['/', '']; - yield ['', '']; - } - - /** - * @dataProvider provideGetFilenameTests - */ - public function testGetFilename(string $path, string $filename): void - { - $this->assertSame($filename, Path::getFilename($path)); - } - public function provideGetFilenameWithoutExtensionTests(): \Generator { yield ['/webmozart/symfony/style.css.twig', null, 'style.css']; From 4e38d181c06669e715b5573f29d34c722c9c24fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:19:35 +0200 Subject: [PATCH 18/21] Add myself to PathTest --- src/Symfony/Component/Filesystem/Tests/PathTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Filesystem/Tests/PathTest.php b/src/Symfony/Component/Filesystem/Tests/PathTest.php index 04ea2e84ecdf0..8a418418d6049 100644 --- a/src/Symfony/Component/Filesystem/Tests/PathTest.php +++ b/src/Symfony/Component/Filesystem/Tests/PathTest.php @@ -17,6 +17,7 @@ /** * @author Bernhard Schussek * @author Thomas Schulz + * @author Théo Fidry */ class PathTest extends TestCase { From 26887453a5014e9a0a3963128d9eb728bd5904d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Tue, 23 Jul 2019 10:21:54 +0200 Subject: [PATCH 19/21] Apply path --- src/Symfony/Component/Filesystem/Path.php | 125 +++++++++++----------- 1 file changed, 62 insertions(+), 63 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 286e55c4a1474..25f8d324a5330 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Filesystem; use Symfony\Component\Filesystem\Exception\InvalidArgumentException; -use Symfony\Component\Filesystem\ExceptionInvalidArgumentException; /** * Contains utility methods for handling path strings. @@ -83,14 +82,14 @@ public static function canonicalize(string $path): string // Replace "~" with user's home directory. if ('~' === $path[0]) { - $path = self::getHomeDirectory().\substr($path, 1); + $path = self::getHomeDirectory().substr($path, 1); } - $path = \str_replace('\\', '/', $path); + $path = str_replace('\\', '/', $path); [$root, $pathWithoutRoot] = self::split($path); - $parts = \explode('/', $pathWithoutRoot); + $parts = explode('/', $pathWithoutRoot); $canonicalParts = []; // Collapse "." and "..", if possible @@ -102,7 +101,7 @@ public static function canonicalize(string $path): string // Collapse ".." with the previous part, if one exists // Don't collapse ".." if the previous part is also ".." if ('..' === $part && \count($canonicalParts) > 0 && '..' !== $canonicalParts[\count($canonicalParts) - 1]) { - \array_pop($canonicalParts); + array_pop($canonicalParts); continue; } @@ -114,7 +113,7 @@ public static function canonicalize(string $path): string } // Add the root directory again - self::$buffer[$path] = $canonicalPath = $root.\implode('/', $canonicalParts); + self::$buffer[$path] = $canonicalPath = $root.implode('/', $canonicalParts); ++self::$bufferSize; // Clean up regularly to prevent memory leaks @@ -139,7 +138,7 @@ public static function canonicalize(string $path): string */ public static function normalize(string $path): string { - return \str_replace('\\', '/', $path); + return str_replace('\\', '/', $path); } /** @@ -174,9 +173,9 @@ public static function getDirectory(string $path): string $path = self::canonicalize($path); // Maintain scheme - if (false !== ($pos = \strpos($path, '://'))) { - $scheme = \substr($path, 0, $pos + 3); - $path = \substr($path, $pos + 3); + if (false !== ($pos = strpos($path, '://'))) { + $scheme = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); } else { $scheme = ''; } @@ -188,11 +187,11 @@ public static function getDirectory(string $path): string } // Directory equals Windows root "C:/" - if (2 === $pos && \ctype_alpha($path[0]) && ':' === $path[1]) { - return $scheme.\substr($path, 0, 3); + if (2 === $pos && ctype_alpha($path[0]) && ':' === $path[1]) { + return $scheme.substr($path, 0, 3); } - return $scheme.\substr($path, 0, $pos); + return $scheme.substr($path, 0, $pos); } return ''; @@ -215,13 +214,13 @@ public static function getDirectory(string $path): string public static function getHomeDirectory(): string { // For UNIX support - if (\getenv('HOME')) { - return self::canonicalize(\getenv('HOME')); + if (getenv('HOME')) { + return self::canonicalize(getenv('HOME')); } // For >= Windows8 support - if (\getenv('HOMEDRIVE') && \getenv('HOMEPATH')) { - return self::canonicalize(\getenv('HOMEDRIVE').\getenv('HOMEPATH')); + if (getenv('HOMEDRIVE') && getenv('HOMEPATH')) { + return self::canonicalize(getenv('HOMEDRIVE').getenv('HOMEPATH')); } throw new \RuntimeException("Cannot find the home directory path: Your environment or operation system isn't supported"); @@ -242,9 +241,9 @@ public static function getRoot(string $path): string } // Maintain scheme - if (false !== ($pos = \strpos($path, '://'))) { - $scheme = \substr($path, 0, $pos + 3); - $path = \substr($path, $pos + 3); + if (false !== ($pos = strpos($path, '://'))) { + $scheme = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); } else { $scheme = ''; } @@ -257,7 +256,7 @@ public static function getRoot(string $path): string $length = \strlen($path); // Windows root - if ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { + if ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === $length) { return $scheme.$path.'/'; @@ -286,10 +285,10 @@ public static function getFilenameWithoutExtension(string $path, ?string $extens if (null !== $extension) { // remove extension and trailing dot - return \rtrim(\basename($path, $extension), '.'); + return rtrim(basename($path, $extension), '.'); } - return \pathinfo($path, PATHINFO_FILENAME); + return pathinfo($path, PATHINFO_FILENAME); } /** @@ -303,7 +302,7 @@ public static function getExtension(string $path, bool $forceLowerCase = false): return ''; } - $extension = \pathinfo($path, PATHINFO_EXTENSION); + $extension = pathinfo($path, PATHINFO_EXTENSION); if ($forceLowerCase) { $extension = self::toLower($extension); @@ -346,7 +345,7 @@ public static function hasExtension(string $path, $extensions = null, bool $igno } // remove leading '.' in extensions array - $extensions[$key] = \ltrim($extension, '.'); + $extensions[$key] = ltrim($extension, '.'); } return \in_array($actualExtension, $extensions, true); @@ -367,19 +366,19 @@ public static function changeExtension(string $path, string $extension): string } $actualExtension = self::getExtension($path); - $extension = \ltrim($extension, '.'); + $extension = ltrim($extension, '.'); // No extension for paths - if ('/' === \substr($path, -1)) { + if ('/' === substr($path, -1)) { return $path; } // No actual extension in path if (empty($actualExtension)) { - return $path.('.' === \substr($path, -1) ? '' : '.').$extension; + return $path.('.' === substr($path, -1) ? '' : '.').$extension; } - return \substr($path, 0, -\strlen($actualExtension)).$extension; + return substr($path, 0, -\strlen($actualExtension)).$extension; } public static function isAbsolute(string $path): bool @@ -389,8 +388,8 @@ public static function isAbsolute(string $path): bool } // Strip scheme - if (false !== ($pos = \strpos($path, '://'))) { - $path = \substr($path, $pos + 3); + if (false !== ($pos = strpos($path, '://'))) { + $path = substr($path, $pos + 3); } // UNIX root "/" or "\" (Windows style) @@ -399,7 +398,7 @@ public static function isAbsolute(string $path): bool } // Windows root - if (\strlen($path) > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { + if (\strlen($path) > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { // Special case: "C:" if (2 === \strlen($path)) { return true; @@ -453,31 +452,31 @@ public static function isRelative(string $path): bool * @param string $basePath an absolute base path * * @throws InvalidArgumentException if the base path is not absolute or if - * the given path is an absolute path with - * a different root than the base path + * the given path is an absolute path with + * a different root than the base path */ public static function makeAbsolute(string $path, string $basePath): string { if ('' === $basePath) { - throw new InvalidArgumentException(\sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); + throw new InvalidArgumentException(sprintf('The base path must be a non-empty string. Got: "%s"', $basePath)); } if (!self::isAbsolute($basePath)) { - throw new InvalidArgumentException(\sprintf('The base path "%s" is not an absolute path.', $basePath)); + throw new InvalidArgumentException(sprintf('The base path "%s" is not an absolute path.', $basePath)); } if (self::isAbsolute($path)) { return self::canonicalize($path); } - if (false !== ($pos = \strpos($basePath, '://'))) { - $scheme = \substr($basePath, 0, $pos + 3); - $basePath = \substr($basePath, $pos + 3); + if (false !== ($pos = strpos($basePath, '://'))) { + $scheme = substr($basePath, 0, $pos + 3); + $basePath = substr($basePath, $pos + 3); } else { $scheme = ''; } - return $scheme.self::canonicalize(\rtrim($basePath, '/\\').'/'.$path); + return $scheme.self::canonicalize(rtrim($basePath, '/\\').'/'.$path); } /** @@ -527,8 +526,8 @@ public static function makeAbsolute(string $path, string $basePath): string * The result is a canonical path. * * @throws InvalidArgumentException if the base path is not absolute or if - * the given path has a different root - * than the base path + * the given path has a different root + * than the base path */ public static function makeRelative(string $path, string $basePath): string { @@ -544,7 +543,7 @@ public static function makeRelative(string $path, string $basePath): string if ('' === $root && '' !== $baseRoot) { // If base path is already in its root if ('' === $relativeBasePath) { - $relativePath = \ltrim($relativePath, './\\'); + $relativePath = ltrim($relativePath, './\\'); } return $relativePath; @@ -553,12 +552,12 @@ public static function makeRelative(string $path, string $basePath): string // If the passed path is absolute, but the base path is not, we // cannot generate a relative path if ('' !== $root && '' === $baseRoot) { - throw new InvalidArgumentException(\sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); + throw new InvalidArgumentException(sprintf('The absolute path "%s" cannot be made relative to the relative path "%s". You should provide an absolute base path instead.', $path, $basePath)); } // Fail if the roots of the two paths are different if ($baseRoot && $root !== $baseRoot) { - throw new InvalidArgumentException(\sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); + throw new InvalidArgumentException(sprintf('The path "%s" cannot be made relative to "%s", because they have different roots ("%s" and "%s").', $path, $basePath, $root, $baseRoot)); } if ('' === $relativeBasePath) { @@ -566,8 +565,8 @@ public static function makeRelative(string $path, string $basePath): string } // Build a "../../" prefix with as many "../" parts as necessary - $parts = \explode('/', $relativePath); - $baseParts = \explode('/', $relativeBasePath); + $parts = explode('/', $relativePath); + $baseParts = explode('/', $relativeBasePath); $dotDotPrefix = ''; // Once we found a non-matching part in the prefix, we need to add @@ -585,7 +584,7 @@ public static function makeRelative(string $path, string $basePath): string $dotDotPrefix .= '../'; } - return \rtrim($dotDotPrefix.\implode('/', $parts), '/'); + return rtrim($dotDotPrefix.implode('/', $parts), '/'); } /** @@ -593,7 +592,7 @@ public static function makeRelative(string $path, string $basePath): string */ public static function isLocal(string $path): bool { - return '' !== $path && false === \strpos($path, '://'); + return '' !== $path && false === strpos($path, '://'); } /** @@ -657,7 +656,7 @@ public static function getLongestCommonBasePath(string ...$paths): ?string // Prevent false positives for common prefixes // see isBasePath() - if (0 === \strpos($path.'/', $basePath.'/')) { + if (0 === strpos($path.'/', $basePath.'/')) { // Next path continue 2; } @@ -687,17 +686,17 @@ public static function join(string ...$paths): string if (null === $finalPath) { // For first part we keep slashes, like '/top', 'C:\' or 'phar://' $finalPath = $path; - $wasScheme = (false !== \strpos($path, '://')); + $wasScheme = (false !== strpos($path, '://')); continue; } // Only add slash if previous part didn't end with '/' or '\' - if (!\in_array(\substr($finalPath, -1), ['/', '\\'])) { + if (!\in_array(substr($finalPath, -1), ['/', '\\'])) { $finalPath .= '/'; } // If first part included a scheme like 'phar://' we allow current part to start with '/', otherwise trim - $finalPath .= $wasScheme ? $path : \ltrim($path, '/'); + $finalPath .= $wasScheme ? $path : ltrim($path, '/'); $wasScheme = false; } @@ -738,7 +737,7 @@ public static function isBasePath(string $basePath, string $ofPath): bool // Don't append a slash for the root "/", because then that root // won't be discovered as common prefix ("//" is not a prefix of // "/foobar/"). - return 0 === \strpos($ofPath.'/', \rtrim($basePath, '/').'/'); + return 0 === strpos($ofPath.'/', rtrim($basePath, '/').'/'); } /** @@ -766,9 +765,9 @@ private static function split(string $path): array } // Remember scheme as part of the root, if any - if (false !== ($pos = \strpos($path, '://'))) { - $root = \substr($path, 0, $pos + 3); - $path = \substr($path, $pos + 3); + if (false !== ($pos = strpos($path, '://'))) { + $root = substr($path, 0, $pos + 3); + $path = substr($path, $pos + 3); } else { $root = ''; } @@ -776,18 +775,18 @@ private static function split(string $path): array $length = \strlen($path); // Remove and remember root directory - if (0 === \strpos($path, '/')) { + if (0 === strpos($path, '/')) { $root .= '/'; - $path = $length > 1 ? \substr($path, 1) : ''; - } elseif ($length > 1 && \ctype_alpha($path[0]) && ':' === $path[1]) { + $path = $length > 1 ? substr($path, 1) : ''; + } elseif ($length > 1 && ctype_alpha($path[0]) && ':' === $path[1]) { if (2 === $length) { // Windows special case: "C:" $root .= $path.'/'; $path = ''; } elseif ('/' === $path[2]) { // Windows normal case: "C:/".. - $root .= \substr($path, 0, 3); - $path = $length > 3 ? \substr($path, 3) : ''; + $root .= substr($path, 0, 3); + $path = $length > 3 ? substr($path, 3) : ''; } } @@ -796,7 +795,7 @@ private static function split(string $path): array private static function toLower(string $str): string { - return \mb_strtolower($str, mb_detect_encoding($str)); + return mb_strtolower($str, mb_detect_encoding($str)); } private function __construct() From 96774e942ad8343e9cdf96835ac3163841c46557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 26 Sep 2019 21:25:50 +0200 Subject: [PATCH 20/21] Fix the experimental tag --- phpunit | 18 ------------------ src/Symfony/Component/Filesystem/Path.php | 2 +- 2 files changed, 1 insertion(+), 19 deletions(-) delete mode 100755 phpunit diff --git a/phpunit b/phpunit deleted file mode 100755 index b885570d65b7f..0000000000000 --- a/phpunit +++ /dev/null @@ -1,18 +0,0 @@ -#!/usr/bin/env php -= 70200) { - putenv('SYMFONY_PHPUNIT_VERSION=8.3'); - } elseif (\PHP_VERSION_ID >= 70000) { - putenv('SYMFONY_PHPUNIT_VERSION=6.5'); - } -} -putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit'); -require __DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit'; diff --git a/src/Symfony/Component/Filesystem/Path.php b/src/Symfony/Component/Filesystem/Path.php index 25f8d324a5330..888939717680b 100644 --- a/src/Symfony/Component/Filesystem/Path.php +++ b/src/Symfony/Component/Filesystem/Path.php @@ -24,7 +24,7 @@ * @author Thomas Schulz * @author Théo Fidry * - * @experimental in 4.4 + * @experimental in 5.0 */ final class Path { From b28cf081a5050ecdd665bf6460522be82eb68414 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9o=20FIDRY?= Date: Thu, 26 Sep 2019 21:26:28 +0200 Subject: [PATCH 21/21] Restore PHPUnit binary --- phpunit | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100755 phpunit diff --git a/phpunit b/phpunit new file mode 100755 index 0000000000000..b885570d65b7f --- /dev/null +++ b/phpunit @@ -0,0 +1,18 @@ +#!/usr/bin/env php += 70200) { + putenv('SYMFONY_PHPUNIT_VERSION=8.3'); + } elseif (\PHP_VERSION_ID >= 70000) { + putenv('SYMFONY_PHPUNIT_VERSION=6.5'); + } +} +putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit'); +require __DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit';