From 24ce1eddbdb4658e1d106a5d982951342f86f4d3 Mon Sep 17 00:00:00 2001 From: Jordi Boggiano Date: Tue, 7 Dec 2021 11:03:51 +0100 Subject: [PATCH] Add composer/pcre dependency and use it everywhere instead of preg_* --- composer.json | 3 +- composer.lock | 73 ++++++++++++- src/Composer/Autoload/AutoloadGenerator.php | 19 ++-- src/Composer/Autoload/ClassMapGenerator.php | 15 +-- src/Composer/Autoload/PhpFileCleaner.php | 10 +- src/Composer/Cache.php | 19 ++-- src/Composer/Command/ConfigCommand.php | 21 ++-- src/Composer/Command/CreateProjectCommand.php | 3 +- src/Composer/Command/DiagnoseCommand.php | 3 +- src/Composer/Command/FundCommand.php | 3 +- src/Composer/Command/GlobalCommand.php | 5 +- src/Composer/Command/InitCommand.php | 23 ++-- src/Composer/Command/ReinstallCommand.php | 3 +- src/Composer/Command/RemoveCommand.php | 5 +- src/Composer/Command/SelfUpdateCommand.php | 19 ++-- src/Composer/Command/ShowCommand.php | 3 +- src/Composer/Command/UpdateCommand.php | 5 +- src/Composer/Compiler.php | 17 +-- src/Composer/Composer.php | 3 +- src/Composer/Config.php | 11 +- src/Composer/Config/JsonConfigSource.php | 5 +- src/Composer/Console/HtmlOutputFormatter.php | 2 + .../DependencyResolver/PoolBuilder.php | 7 +- src/Composer/DependencyResolver/Problem.php | 13 +-- src/Composer/Downloader/DownloadManager.php | 3 +- src/Composer/Downloader/FossilDownloader.php | 3 +- src/Composer/Downloader/GitDownloader.php | 37 +++---- src/Composer/Downloader/SvnDownloader.php | 13 +-- .../EventDispatcher/EventDispatcher.php | 13 +-- .../IgnoreListPlatformRequirementFilter.php | 3 +- src/Composer/IO/BaseIO.php | 3 +- src/Composer/IO/BufferIO.php | 3 +- src/Composer/Installer/BinaryInstaller.php | 5 +- src/Composer/Installer/LibraryInstaller.php | 3 +- .../Installer/SuggestedPackagesReporter.php | 3 +- src/Composer/Json/JsonFile.php | 7 +- src/Composer/Json/JsonFormatter.php | 4 +- src/Composer/Json/JsonManipulator.php | 100 ++++++------------ .../Archiver/ArchivableFilesFinder.php | 3 +- .../Package/Archiver/ArchiveManager.php | 5 +- .../Package/Archiver/BaseExcludeFilter.php | 9 +- .../Package/Archiver/GitExcludeFilter.php | 4 +- src/Composer/Package/Loader/ArrayLoader.php | 5 +- .../Package/Loader/RootPackageLoader.php | 17 +-- .../Package/Loader/ValidatingArrayLoader.php | 19 ++-- src/Composer/Package/Locker.php | 5 +- src/Composer/Package/Package.php | 7 +- .../Package/Version/VersionGuesser.php | 23 ++-- .../Package/Version/VersionParser.php | 5 +- .../Package/Version/VersionSelector.php | 5 +- src/Composer/Platform/Version.php | 8 +- src/Composer/Plugin/PluginManager.php | 7 +- .../Question/StrictConfirmationQuestion.php | 5 +- src/Composer/Repository/ArrayRepository.php | 7 +- .../Repository/ComposerRepository.php | 23 ++-- src/Composer/Repository/FilterRepository.php | 5 +- src/Composer/Repository/PackageRepository.php | 3 +- src/Composer/Repository/PathRepository.php | 5 +- .../Repository/PlatformRepository.php | 75 ++++++------- src/Composer/Repository/RepositoryFactory.php | 3 +- src/Composer/Repository/Vcs/FossilDriver.php | 9 +- .../Repository/Vcs/GitBitbucketDriver.php | 7 +- src/Composer/Repository/Vcs/GitDriver.php | 19 ++-- src/Composer/Repository/Vcs/GitHubDriver.php | 23 ++-- src/Composer/Repository/Vcs/GitLabDriver.php | 13 +-- src/Composer/Repository/Vcs/HgDriver.php | 11 +- .../Repository/Vcs/PerforceDriver.php | 3 +- src/Composer/Repository/Vcs/SvnDriver.php | 19 ++-- src/Composer/Repository/Vcs/VcsDriver.php | 3 +- src/Composer/Repository/VcsRepository.php | 9 +- src/Composer/SelfUpdate/Keys.php | 4 +- src/Composer/Util/AuthHelper.php | 3 +- src/Composer/Util/ComposerMirror.php | 10 +- src/Composer/Util/ConfigValidator.php | 11 +- src/Composer/Util/ErrorHandler.php | 3 +- src/Composer/Util/Filesystem.php | 17 +-- src/Composer/Util/Git.php | 27 ++--- src/Composer/Util/GitHub.php | 3 +- src/Composer/Util/GitLab.php | 3 +- src/Composer/Util/Hg.php | 5 +- src/Composer/Util/Http/CurlDownloader.php | 11 +- src/Composer/Util/Http/Response.php | 5 +- src/Composer/Util/HttpDownloader.php | 5 +- src/Composer/Util/NoProxyPattern.php | 3 +- src/Composer/Util/Perforce.php | 3 +- src/Composer/Util/Platform.php | 6 +- src/Composer/Util/ProcessExecutor.php | 25 ++--- src/Composer/Util/RemoteFilesystem.php | 17 +-- src/Composer/Util/Svn.php | 3 +- src/Composer/Util/TlsHelper.php | 5 +- src/Composer/Util/Url.php | 21 ++-- tests/Composer/Test/AllFunctionalTest.php | 7 +- .../DependencyResolver/PoolBuilderTest.php | 5 +- .../DependencyResolver/PoolOptimizerTest.php | 5 +- .../Test/Downloader/GitDownloaderTest.php | 3 +- tests/Composer/Test/IO/ConsoleIOTest.php | 5 +- tests/Composer/Test/InstallerTest.php | 13 +-- .../Archiver/ArchivableFilesFinderTest.php | 5 +- tests/Composer/Test/TestCase.php | 3 +- 99 files changed, 615 insertions(+), 475 deletions(-) diff --git a/composer.json b/composer.json index fe8751c71..ad67dc3e9 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,8 @@ "symfony/filesystem": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", - "react/promise": "^1.2 || ^2.7" + "react/promise": "^1.2 || ^2.7", + "composer/pcre": "^1.0" }, "require-dev": { "symfony/phpunit-bridge": "^4.2 || ^5.0 || ^6.0", diff --git a/composer.lock b/composer.lock index fcbd58b9f..7a6e5ce5f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "136c1a25e4f757a3dccb43aa967507f4", + "content-hash": "659a81a68363780c2e9fb35a1116808c", "packages": [ { "name": "composer/ca-bundle", @@ -151,6 +151,77 @@ ], "time": "2021-04-07T13:37:33+00:00" }, + { + "name": "composer/pcre", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/composer/pcre.git", + "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/pcre/zipball/3d322d715c43a1ac36c7fe215fa59336265500f2", + "reference": "3d322d715c43a1ac36c7fe215fa59336265500f2", + "shasum": "" + }, + "require": { + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpstan/phpstan": "^1", + "phpstan/phpstan-strict-rules": "^1.1", + "symfony/phpunit-bridge": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\Pcre\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "PCRE wrapping library that offers type-safe preg_* replacements.", + "keywords": [ + "PCRE", + "preg", + "regex", + "regular expression" + ], + "support": { + "issues": "https://github.com/composer/pcre/issues", + "source": "https://github.com/composer/pcre/tree/1.0.0" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2021-12-06T15:17:27+00:00" + }, { "name": "composer/semver", "version": "3.2.6", diff --git a/src/Composer/Autoload/AutoloadGenerator.php b/src/Composer/Autoload/AutoloadGenerator.php index f3f67ee61..efb8c7cef 100644 --- a/src/Composer/Autoload/AutoloadGenerator.php +++ b/src/Composer/Autoload/AutoloadGenerator.php @@ -22,6 +22,7 @@ use Composer\IO\IOInterface; use Composer\Package\AliasPackage; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; +use Composer\Pcre\Preg; use Composer\Repository\InstalledRepositoryInterface; use Composer\Semver\Constraint\Bound; use Composer\Util\Filesystem; @@ -375,7 +376,7 @@ EOF; if (!$suffix) { if (!$config->get('autoloader-suffix') && Filesystem::isReadable($vendorPath.'/autoload.php')) { $content = file_get_contents($vendorPath.'/autoload.php'); - if (preg_match('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) { + if (Preg::isMatch('{ComposerAutoloaderInit([^:\s]+)::}', $content, $match)) { $suffix = $match[1]; } } @@ -447,7 +448,7 @@ EOF; $pathCode = $this->getPathCode($filesystem, $basePath, $vendorPath, $path).",\n"; if (!isset($classMap[$class])) { $classMap[$class] = $pathCode; - } elseif ($this->io && $classMap[$class] !== $pathCode && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { + } elseif ($this->io && $classMap[$class] !== $pathCode && !Preg::isMatch('{/(test|fixture|example|stub)s?/}i', strtr($classMap[$class].' '.$path, '\\', '/'))) { $ambiguousClasses[$class][] = $path; } } @@ -475,7 +476,7 @@ EOF; $dirMatch = preg_quote(strtr(realpath($dir), '\\', '/')); foreach ($excluded as $index => $pattern) { // extract the constant string prefix of the pattern here, until we reach a non-escaped regex special character - $pattern = preg_replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern); + $pattern = Preg::replace('{^(([^.+*?\[^\]$(){}=!<>|:\\\\#-]+|\\\\[.+*?\[^\]$(){}=!<>|:#-])*).*}', '$1', $pattern); // if the pattern is not a subset or superset of $dir, it is unrelated and we skip it if (0 !== strpos($pattern, $dirMatch) && 0 !== strpos($dirMatch, $pattern)) { unset($excluded[$index]); @@ -757,7 +758,7 @@ EOF; foreach ($packageMap as $item) { $package = $item[0]; foreach (array_merge($package->getReplaces(), $package->getProvides()) as $link) { - if (preg_match('{^ext-(.+)$}iD', $link->getTarget(), $match)) { + if (Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) { $extensionProviders[$match[1]][] = $link->getConstraint(); } } @@ -782,7 +783,7 @@ EOF; } } - if ($checkPlatform === true && preg_match('{^ext-(.+)$}iD', $link->getTarget(), $match)) { + if ($checkPlatform === true && Preg::isMatch('{^ext-(.+)$}iD', $link->getTarget(), $match)) { // skip extension checks if they have a valid provider/replacer if (isset($extensionProviders[$match[1]])) { foreach ($extensionProviders[$match[1]] as $provided) { @@ -1204,7 +1205,7 @@ HEADER; $absoluteAppBaseDirPharCode => $appBaseDirPharCode, ) ); - $value = ltrim(preg_replace('/^ */m', ' $0$0', $value)); + $value = ltrim(Preg::replace('/^ */m', ' $0$0', $value)); $file .= sprintf(" public static $%s = %s;\n\n", $prop, $value); if ('files' !== $prop) { @@ -1255,7 +1256,7 @@ INITIALIZER; // remove target-dir from file paths of the root package if ($package === $rootPackage) { $targetDir = str_replace('\\', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '', $package->getTargetDir()))); - $path = ltrim(preg_replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/'); + $path = ltrim(Preg::replace('{^'.$targetDir.'}', '', ltrim($path, '\\/')), '\\/'); } else { // add target-dir from file paths that don't have it $path = $package->getTargetDir() . '/' . $path; @@ -1264,14 +1265,14 @@ INITIALIZER; if ($type === 'exclude-from-classmap') { // first escape user input - $path = preg_replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/'))); + $path = Preg::replace('{/+}', '/', preg_quote(trim(strtr($path, '\\', '/'), '/'))); // add support for wildcards * and ** $path = strtr($path, array('\\*\\*' => '.+?', '\\*' => '[^/]+?')); // add support for up-level relative paths $updir = null; - $path = preg_replace_callback( + $path = Preg::replaceCallback( '{^((?:(?:\\\\\\.){1,2}+/)+)}', function ($matches) use (&$updir) { if (isset($matches[1])) { diff --git a/src/Composer/Autoload/ClassMapGenerator.php b/src/Composer/Autoload/ClassMapGenerator.php index 6910fcb6f..3ac096772 100644 --- a/src/Composer/Autoload/ClassMapGenerator.php +++ b/src/Composer/Autoload/ClassMapGenerator.php @@ -18,6 +18,7 @@ namespace Composer\Autoload; +use Composer\Pcre\Preg; use Symfony\Component\Finder\Finder; use Composer\IO\IOInterface; use Composer\Util\Filesystem; @@ -92,7 +93,7 @@ class ClassMapGenerator $filePath = $cwd . '/' . $filePath; $filePath = $filesystem->normalizePath($filePath); } else { - $filePath = preg_replace('{[\\\\/]{2,}}', '/', $filePath); + $filePath = Preg::replace('{[\\\\/]{2,}}', '/', $filePath); } $realPath = realpath($filePath); @@ -104,11 +105,11 @@ class ClassMapGenerator } // check the realpath of the file against the excluded paths as the path might be a symlink and the excluded path is realpath'd so symlink are resolved - if ($excluded && preg_match($excluded, strtr($realPath, '\\', '/'))) { + if ($excluded && Preg::isMatch($excluded, strtr($realPath, '\\', '/'))) { continue; } // check non-realpath of file for directories symlink in project dir - if ($excluded && preg_match($excluded, strtr($filePath, '\\', '/'))) { + if ($excluded && Preg::isMatch($excluded, strtr($filePath, '\\', '/'))) { continue; } @@ -133,7 +134,7 @@ class ClassMapGenerator if (!isset($map[$class])) { $map[$class] = $filePath; - } elseif ($io && $map[$class] !== $filePath && !preg_match('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) { + } elseif ($io && $map[$class] !== $filePath && !Preg::isMatch('{/(test|fixture|example|stub)s?/}i', strtr($map[$class].' '.$filePath, '\\', '/'))) { $io->writeError( 'Warning: Ambiguous class resolution, "'.$class.'"'. ' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.' @@ -196,7 +197,7 @@ class ClassMapGenerator if (empty($validClasses)) { foreach ($rejectedClasses as $class) { if ($io) { - $io->writeError("Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping."); + $io->writeError("Class $class located in ".Preg::replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping."); } } @@ -239,7 +240,7 @@ class ClassMapGenerator } // return early if there is no chance of matching anything in this file - preg_match_all('{\b(?:class|interface'.$extraTypes.')\s}i', $contents, $matches); + Preg::matchAll('{\b(?:class|interface'.$extraTypes.')\s}i', $contents, $matches); if (!$matches) { return array(); } @@ -248,7 +249,7 @@ class ClassMapGenerator $contents = $p->clean(); unset($p); - preg_match_all('{ + Preg::matchAll('{ (?: \b(?])(?Pclass|interface'.$extraTypes.') \s++ (?P[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+) | \b(?])(?Pnamespace) (?P\s++[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\s*+\\\\\s*+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)*+)? \s*+ [\{;] diff --git a/src/Composer/Autoload/PhpFileCleaner.php b/src/Composer/Autoload/PhpFileCleaner.php index 677f7e978..2564973fc 100644 --- a/src/Composer/Autoload/PhpFileCleaner.php +++ b/src/Composer/Autoload/PhpFileCleaner.php @@ -12,6 +12,8 @@ namespace Composer\Autoload; +use Composer\Pcre\Preg; + /** * @author Jordi Boggiano * @internal @@ -125,7 +127,7 @@ class PhpFileCleaner $type = self::$typeConfig[$char]; if ( \substr($this->contents, $this->index, $type['length']) === $type['name'] - && \preg_match($type['pattern'], $this->contents, $match, 0, $this->index - 1) + && Preg::isMatch($type['pattern'], $this->contents, $match, 0, $this->index - 1) ) { $clean .= $match[0]; @@ -269,10 +271,6 @@ class PhpFileCleaner */ private function match($regex, array &$match = null) { - if (\preg_match($regex, $this->contents, $match, 0, $this->index)) { - return true; - } - - return false; + return Preg::isMatch($regex, $this->contents, $match, 0, $this->index); } } diff --git a/src/Composer/Cache.php b/src/Composer/Cache.php index 6da4cb20a..135665d91 100644 --- a/src/Composer/Cache.php +++ b/src/Composer/Cache.php @@ -13,6 +13,7 @@ namespace Composer; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\Silencer; @@ -85,7 +86,7 @@ class Cache */ public static function isUsable($path) { - return !preg_match('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path); + return !Preg::isMatch('{(^|[\\\\/])(\$null|nul|NUL|/dev/null)([\\\\/]|$)}', $path); } /** @@ -124,7 +125,7 @@ class Cache public function read($file) { if ($this->isEnabled()) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); if (file_exists($this->root . $file)) { $this->io->writeError('Reading '.$this->root . $file.' from cache', true, IOInterface::DEBUG); @@ -144,7 +145,7 @@ class Cache public function write($file, $contents) { if ($this->isEnabled() && !$this->readOnly) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); $this->io->writeError('Writing '.$this->root . $file.' into cache', true, IOInterface::DEBUG); @@ -153,7 +154,7 @@ class Cache return file_put_contents($tempFileName, $contents) !== false && rename($tempFileName, $this->root . $file); } catch (\ErrorException $e) { $this->io->writeError('Failed to write into cache: '.$e->getMessage().'', true, IOInterface::DEBUG); - if (preg_match('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) { + if (Preg::isMatch('{^file_put_contents\(\): Only ([0-9]+) of ([0-9]+) bytes written}', $e->getMessage(), $m)) { // Remove partial file. unlink($tempFileName); @@ -188,7 +189,7 @@ class Cache public function copyFrom($file, $source) { if ($this->isEnabled() && !$this->readOnly) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); $this->filesystem->ensureDirectoryExists(dirname($this->root . $file)); if (!file_exists($source)) { @@ -214,7 +215,7 @@ class Cache public function copyTo($file, $target) { if ($this->isEnabled()) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); if (file_exists($this->root . $file)) { try { touch($this->root . $file, filemtime($this->root . $file), time()); @@ -262,7 +263,7 @@ class Cache public function remove($file) { if ($this->isEnabled()) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); if (file_exists($this->root . $file)) { return $this->filesystem->unlink($this->root . $file); } @@ -329,7 +330,7 @@ class Cache public function sha1($file) { if ($this->isEnabled()) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); if (file_exists($this->root . $file)) { return sha1_file($this->root . $file); } @@ -346,7 +347,7 @@ class Cache public function sha256($file) { if ($this->isEnabled()) { - $file = preg_replace('{[^'.$this->allowlist.']}i', '-', $file); + $file = Preg::replace('{[^'.$this->allowlist.']}i', '-', $file); if (file_exists($this->root . $file)) { return hash_file('sha256', $this->root . $file); } diff --git a/src/Composer/Command/ConfigCommand.php b/src/Composer/Command/ConfigCommand.php index 49479a6ba..503accb14 100644 --- a/src/Composer/Command/ConfigCommand.php +++ b/src/Composer/Command/ConfigCommand.php @@ -12,6 +12,7 @@ namespace Composer\Command; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\Silencer; @@ -261,7 +262,7 @@ EOT $properties = array('name', 'type', 'description', 'homepage', 'version', 'minimum-stability', 'prefer-stable', 'keywords', 'license', 'extra'); $rawData = $this->configFile->read(); $data = $this->config->all(); - if (preg_match('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) { + if (Preg::isMatch('/^repos?(?:itories)?(?:\.(.+))?/', $settingKey, $matches)) { if (!isset($matches[1]) || $matches[1] === '') { $value = isset($data['repositories']) ? $data['repositories'] : array(); } else { @@ -390,7 +391,7 @@ EOT 'cache-files-ttl' => array('is_numeric', 'intval'), 'cache-files-maxsize' => array( function ($val) { - return preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val) > 0; + return Preg::isMatch('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $val); }, function ($val) { return $val; @@ -535,7 +536,7 @@ EOT return 0; } // handle preferred-install per-package config - if (preg_match('/^preferred-install\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^preferred-install\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); @@ -626,7 +627,7 @@ EOT } // handle repositories - if (preg_match('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^repos?(?:itories)?\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeRepository($matches[1]); @@ -662,7 +663,7 @@ EOT } // handle extra - if (preg_match('/^extra\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^extra\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); @@ -689,7 +690,7 @@ EOT } // handle suggest - if (preg_match('/^suggest\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^suggest\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); @@ -709,7 +710,7 @@ EOT } // handle platform - if (preg_match('/^platform\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^platform\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeConfigSetting($settingKey); @@ -729,7 +730,7 @@ EOT } // handle auth - if (preg_match('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|http-basic|bearer)\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->authConfigSource->removeConfigSetting($matches[1].'.'.$matches[2]); $this->configSource->removeConfigSetting($matches[1].'.'.$matches[2]); @@ -764,7 +765,7 @@ EOT } // handle script - if (preg_match('/^scripts\.(.+)/', $settingKey, $matches)) { + if (Preg::isMatch('/^scripts\.(.+)/', $settingKey, $matches)) { if ($input->getOption('unset')) { $this->configSource->removeProperty($settingKey); @@ -857,7 +858,7 @@ EOT $rawVal = isset($rawContents[$key]) ? $rawContents[$key] : null; if (is_array($value) && (!is_numeric(key($value)) || ($key === 'repositories' && null === $k))) { - $k .= preg_replace('{^config\.}', '', $key . '.'); + $k .= Preg::replace('{^config\.}', '', $key . '.'); $this->listConfiguration($value, $rawVal, $output, $k, $showSource); $k = $origK; diff --git a/src/Composer/Command/CreateProjectCommand.php b/src/Composer/Command/CreateProjectCommand.php index 233ed1a2e..d2ff21e9e 100644 --- a/src/Composer/Command/CreateProjectCommand.php +++ b/src/Composer/Command/CreateProjectCommand.php @@ -25,6 +25,7 @@ use Composer\Package\BasePackage; use Composer\DependencyResolver\Operation\InstallOperation; use Composer\Package\Version\VersionSelector; use Composer\Package\AliasPackage; +use Composer\Pcre\Preg; use Composer\Repository\RepositoryFactory; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; @@ -390,7 +391,7 @@ EOT if (null === $stability) { if (null === $packageVersion) { $stability = 'stable'; - } elseif (preg_match('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) { + } elseif (Preg::isMatch('{^[^,\s]*?@('.implode('|', array_keys(BasePackage::$stabilities)).')$}i', $packageVersion, $match)) { $stability = $match[1]; } else { $stability = VersionParser::parseStability($packageVersion); diff --git a/src/Composer/Command/DiagnoseCommand.php b/src/Composer/Command/DiagnoseCommand.php index 80c951833..242c58154 100644 --- a/src/Composer/Command/DiagnoseCommand.php +++ b/src/Composer/Command/DiagnoseCommand.php @@ -16,6 +16,7 @@ use Composer\Composer; use Composer\Factory; use Composer\Config; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; @@ -579,7 +580,7 @@ EOT ob_start(); phpinfo(INFO_GENERAL); $phpinfo = ob_get_clean(); - if (preg_match('{Configure Command(?: *| *=> *)(.*?)(?:|$)}m', $phpinfo, $match)) { + if (Preg::isMatch('{Configure Command(?: *| *=> *)(.*?)(?:|$)}m', $phpinfo, $match)) { $configure = $match[1]; if (false !== strpos($configure, '--enable-sigchild')) { diff --git a/src/Composer/Command/FundCommand.php b/src/Composer/Command/FundCommand.php index d6d9c75bc..96c2c25d8 100644 --- a/src/Composer/Command/FundCommand.php +++ b/src/Composer/Command/FundCommand.php @@ -16,6 +16,7 @@ use Composer\Json\JsonFile; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\CompletePackageInterface; +use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Semver\Constraint\MatchAllConstraint; use Symfony\Component\Console\Input\InputInterface; @@ -144,7 +145,7 @@ class FundCommand extends BaseCommand continue; } $url = $fundingOption['url']; - if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && preg_match('{^https://github.com/([^/]+)$}', $url, $match)) { + if (!empty($fundingOption['type']) && $fundingOption['type'] === 'github' && Preg::isMatch('{^https://github.com/([^/]+)$}', $url, $match)) { $url = 'https://github.com/sponsors/'.$match[1]; } $fundings[$vendor][$url][] = $packageName; diff --git a/src/Composer/Command/GlobalCommand.php b/src/Composer/Command/GlobalCommand.php index fbcb77eeb..ad629de4b 100644 --- a/src/Composer/Command/GlobalCommand.php +++ b/src/Composer/Command/GlobalCommand.php @@ -13,6 +13,7 @@ namespace Composer\Command; use Composer\Factory; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Symfony\Component\Console\Input\InputInterface; @@ -71,7 +72,7 @@ EOT } // extract real command name - $tokens = preg_split('{\s+}', $input->__toString()); + $tokens = Preg::split('{\s+}', $input->__toString()); $args = array(); foreach ($tokens as $token) { if ($token && $token[0] !== '-') { @@ -112,7 +113,7 @@ EOT $this->getIO()->writeError('Changed current directory to '.$home.''); // create new input without "global" command prefix - $input = new StringInput(preg_replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1)); + $input = new StringInput(Preg::replace('{\bg(?:l(?:o(?:b(?:a(?:l)?)?)?)?)?\b}', '', $input->__toString(), 1)); $this->getApplication()->resetComposer(); return $this->getApplication()->run($input, $output); diff --git a/src/Composer/Command/InitCommand.php b/src/Composer/Command/InitCommand.php index 939a3fe38..af276f101 100644 --- a/src/Composer/Command/InitCommand.php +++ b/src/Composer/Command/InitCommand.php @@ -23,6 +23,7 @@ use Composer\Package\Package; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; +use Composer\Pcre\Preg; use Composer\Repository\CompositeRepository; use Composer\Repository\PlatformRepository; use Composer\Repository\RepositoryFactory; @@ -104,7 +105,7 @@ EOT $allowlist = array('name', 'description', 'author', 'type', 'homepage', 'require', 'require-dev', 'stability', 'license', 'autoload'); $options = array_filter(array_intersect_key($input->getOptions(), array_flip($allowlist))); - if (isset($options['name']) && !preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $options['name'])) { + if (isset($options['name']) && !Preg::isMatch('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $options['name'])) { throw new \InvalidArgumentException( 'The package name '.$options['name'].' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+' ); @@ -283,7 +284,7 @@ EOT if (!$name = $input->getOption('name')) { $name = basename($cwd); - $name = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name); + $name = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name); $name = strtolower($name); if (!empty($_SERVER['COMPOSER_DEFAULT_VENDOR'])) { $name = $_SERVER['COMPOSER_DEFAULT_VENDOR'] . '/' . $name; @@ -309,7 +310,7 @@ EOT return $name; } - if (!preg_match('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) { + if (!Preg::isMatch('{^[a-z0-9_.-]+/[a-z0-9_.-]+$}D', $value)) { throw new \InvalidArgumentException( 'The package name '.$value.' is invalid, it should be lowercase and have a vendor name, a forward slash, and a package name, matching: [a-z0-9_.-]+/[a-z0-9_.-]+' ); @@ -452,7 +453,7 @@ EOT $value = $value ?: $autoload; - if (!preg_match('{^[^/][A-Za-z0-9\-_/]+/$}', $value)) { + if (!Preg::isMatch('{^[^/][A-Za-z0-9\-_/]+/$}', $value)) { throw new \InvalidArgumentException(sprintf( 'The src folder name "%s" is invalid. Please add a relative path with tailing forward slash. [A-Za-z0-9_-/]+/', $value @@ -474,7 +475,7 @@ EOT */ public function parseAuthorString($author) { - if (preg_match('/^(?P[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P.+?)>$/u', $author, $match)) { + if (Preg::isMatch('/^(?P[- .,\p{L}\p{N}\p{Mn}\'’"()]+) <(?P.+?)>$/u', $author, $match)) { if ($this->isValidEmail($match['email'])) { return array( 'name' => trim($match['name']), @@ -617,7 +618,7 @@ EOT return $package['name']; } - if (preg_match('{^\s*(?P[\S/]+)(?:\s+(?P\S+))?\s*$}', $selection, $packageMatches)) { + if (Preg::isMatch('{^\s*(?P[\S/]+)(?:\s+(?P\S+))?\s*$}', $selection, $packageMatches)) { if (isset($packageMatches['version'])) { // parsing `acme/example ~2.3` @@ -707,7 +708,7 @@ EOT $namespace = array_map( function ($part) { - $part = preg_replace('/[^a-z0-9]/i', ' ', $part); + $part = Preg::replace('/[^a-z0-9]/i', ' ', $part); $part = ucwords($part); return str_replace(' ', '', $part); @@ -741,9 +742,9 @@ EOT if ($cmd->isSuccessful()) { $this->gitConfig = array(); - preg_match_all('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $this->gitConfig[$match[1]] = $match[2]; + Preg::matchAll('{^([^=]+)=(.*)$}m', $cmd->getOutput(), $matches); + foreach ($matches[1] as $key => $match) { + $this->gitConfig[$match] = $matches[2][$key]; } return $this->gitConfig; @@ -778,7 +779,7 @@ EOT $lines = file($ignoreFile, FILE_IGNORE_NEW_LINES); foreach ($lines as $line) { - if (preg_match($pattern, $line)) { + if (Preg::isMatch($pattern, $line)) { return true; } } diff --git a/src/Composer/Command/ReinstallCommand.php b/src/Composer/Command/ReinstallCommand.php index 6d0122168..55f5a7582 100644 --- a/src/Composer/Command/ReinstallCommand.php +++ b/src/Composer/Command/ReinstallCommand.php @@ -18,6 +18,7 @@ use Composer\DependencyResolver\Transaction; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Package\AliasPackage; use Composer\Package\BasePackage; +use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Symfony\Component\Console\Input\InputInterface; @@ -82,7 +83,7 @@ EOT $patternRegexp = BasePackage::packageNameToRegexp($pattern); $matched = false; foreach ($localRepo->getCanonicalPackages() as $package) { - if (preg_match($patternRegexp, $package->getName())) { + if (Preg::isMatch($patternRegexp, $package->getName())) { $matched = true; $packagesToReinstall[] = $package; $packageNamesToReinstall[] = $package->getName(); diff --git a/src/Composer/Command/RemoveCommand.php b/src/Composer/Command/RemoveCommand.php index 39aa02891..777db98a2 100644 --- a/src/Composer/Command/RemoveCommand.php +++ b/src/Composer/Command/RemoveCommand.php @@ -16,6 +16,7 @@ use Composer\Config\JsonConfigSource; use Composer\DependencyResolver\Request; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Installer; +use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Json\JsonFile; @@ -178,7 +179,7 @@ EOT } } } - } elseif (isset($composer[$type]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) { + } elseif (isset($composer[$type]) && $matches = Preg::grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$type]))) { foreach ($matches as $matchedPackage) { if ($dryRun) { $toRemove[$type][] = $matchedPackage; @@ -186,7 +187,7 @@ EOT $json->removeLink($type, $matchedPackage); } } - } elseif (isset($composer[$altType]) && $matches = preg_grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) { + } elseif (isset($composer[$altType]) && $matches = Preg::grep(BasePackage::packageNameToRegexp($package), array_keys($composer[$altType]))) { foreach ($matches as $matchedPackage) { $io->writeError('' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . ''); if ($io->isInteractive()) { diff --git a/src/Composer/Command/SelfUpdateCommand.php b/src/Composer/Command/SelfUpdateCommand.php index 360442a1c..541636c1e 100644 --- a/src/Composer/Command/SelfUpdateCommand.php +++ b/src/Composer/Command/SelfUpdateCommand.php @@ -15,6 +15,7 @@ namespace Composer\Command; use Composer\Composer; use Composer\Factory; use Composer\Config; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\SelfUpdate\Keys; @@ -157,9 +158,9 @@ EOT } $latestVersion = $latest['version']; $updateVersion = $input->getArgument('version') ?: $latestVersion; - $currentMajorVersion = preg_replace('{^(\d+).*}', '$1', Composer::getVersion()); - $updateMajorVersion = preg_replace('{^(\d+).*}', '$1', $updateVersion); - $previewMajorVersion = preg_replace('{^(\d+).*}', '$1', $latestPreview['version']); + $currentMajorVersion = Preg::replace('{^(\d+).*}', '$1', Composer::getVersion()); + $updateMajorVersion = Preg::replace('{^(\d+).*}', '$1', $updateVersion); + $previewMajorVersion = Preg::replace('{^(\d+).*}', '$1', $latestPreview['version']); if ($versionsUtil->getChannel() === 'stable' && !$input->getArgument('version')) { // if requesting stable channel and no specific version, avoid automatically upgrading to the next major @@ -185,7 +186,7 @@ EOT $io->writeError('Warning: You forced the install of '.$latestVersion.' via --'.$requestedChannel.', but '.$latestStable['version'].' is the latest stable version. Updating to it via composer self-update --stable is recommended.'); } - if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { + if (Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) { $io->writeError('You can not update to a specific SHA-1 as those phars are not available for download'); return 1; @@ -218,11 +219,11 @@ EOT '%s/%s-%s%s', $rollbackDir, strtr(Composer::RELEASE_DATE, ' :', '_-'), - preg_replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION), + Preg::replace('{^([0-9a-f]{7})[0-9a-f]{33}$}', '$1', Composer::VERSION), self::OLD_INSTALL_EXT ); - $updatingToTag = !preg_match('{^[0-9a-f]{40}$}', $updateVersion); + $updatingToTag = !Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion); $io->write(sprintf("Upgrading to version %s (%s channel).", $updateVersion, $channelString)); $remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar'); @@ -351,7 +352,7 @@ TAGSPUBKEY $io->write('Open https://composer.github.io/pubkeys.html to find the latest keys'); $validator = function ($value) { - if (!preg_match('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) { + if (!Preg::isMatch('{^-----BEGIN PUBLIC KEY-----$}', trim($value))) { throw new \UnexpectedValueException('Invalid input'); } @@ -359,7 +360,7 @@ TAGSPUBKEY }; $devKey = ''; - while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) { + while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $devKey, $match)) { $devKey = $io->askAndValidate('Enter Dev / Snapshot Public Key (including lines with -----): ', $validator); while ($line = $io->ask('')) { $devKey .= trim($line)."\n"; @@ -372,7 +373,7 @@ TAGSPUBKEY $io->write('Stored key with fingerprint: ' . Keys::fingerprint($keyPath)); $tagsKey = ''; - while (!preg_match('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) { + while (!Preg::isMatch('{(-----BEGIN PUBLIC KEY-----.+?-----END PUBLIC KEY-----)}s', $tagsKey, $match)) { $tagsKey = $io->askAndValidate('Enter Tags Public Key (including lines with -----): ', $validator); while ($line = $io->ask('')) { $tagsKey .= trim($line)."\n"; diff --git a/src/Composer/Command/ShowCommand.php b/src/Composer/Command/ShowCommand.php index 321bcc41d..f1f52f90b 100644 --- a/src/Composer/Command/ShowCommand.php +++ b/src/Composer/Command/ShowCommand.php @@ -24,6 +24,7 @@ use Composer\Package\Package; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\VersionSelector; +use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Repository\InstalledArrayRepository; @@ -364,7 +365,7 @@ EOT while ($package instanceof AliasPackage) { $package = $package->getAliasOf(); } - if (!$packageFilterRegex || preg_match($packageFilterRegex, $package->getName())) { + if (!$packageFilterRegex || Preg::isMatch($packageFilterRegex, $package->getName())) { if (!$packageListFilter || in_array($package->getName(), $packageListFilter, true)) { $packages[$type][$package->getName()] = $package; } diff --git a/src/Composer/Command/UpdateCommand.php b/src/Composer/Command/UpdateCommand.php index 8cdeba4d8..276a9198d 100644 --- a/src/Composer/Command/UpdateCommand.php +++ b/src/Composer/Command/UpdateCommand.php @@ -18,6 +18,7 @@ use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\Loader\RootPackageLoader; +use Composer\Pcre\Preg; use Composer\Plugin\CommandEvent; use Composer\Plugin\PluginEvents; use Composer\Package\Version\VersionParser; @@ -136,7 +137,7 @@ EOT // extract --with shorthands from the allowlist if ($packages) { $allowlistPackagesWithRequirements = array_filter($packages, function ($pkg) { - return preg_match('{\S+[ =:]\S+}', $pkg) > 0; + return Preg::isMatch('{\S+[ =:]\S+}', $pkg); }); foreach ($this->formatRequirements($allowlistPackagesWithRequirements) as $package => $constraint) { $reqs[$package] = $constraint; @@ -144,7 +145,7 @@ EOT // replace the foo/bar:req by foo/bar in the allowlist foreach ($allowlistPackagesWithRequirements as $package) { - $packageName = preg_replace('{^([^ =:]+)[ =:].*$}', '$1', $package); + $packageName = Preg::replace('{^([^ =:]+)[ =:].*$}', '$1', $package); $index = array_search($package, $packages); $packages[$index] = $packageName; } diff --git a/src/Composer/Compiler.php b/src/Composer/Compiler.php index cd27a5f72..622965076 100644 --- a/src/Composer/Compiler.php +++ b/src/Composer/Compiler.php @@ -14,6 +14,7 @@ namespace Composer; use Composer\Json\JsonFile; use Composer\CaBundle\CaBundle; +use Composer\Pcre\Preg; use Symfony\Component\Finder\Finder; use Symfony\Component\Process\Process; use Seld\PharUtils\Timestamps; @@ -161,11 +162,11 @@ class Compiler foreach ($finder as $file) { if (in_array(realpath($file), $extraFiles, true)) { unset($extraFiles[array_search(realpath($file), $extraFiles, true)]); - } elseif (!preg_match('{([/\\\\]LICENSE|\.php)$}', $file)) { + } elseif (!Preg::isMatch('{([/\\\\]LICENSE|\.php)$}', $file)) { $unexpectedFiles[] = (string) $file; } - if (preg_match('{\.php[\d.]*$}', $file)) { + if (Preg::isMatch('{\.php[\d.]*$}', $file)) { $this->addFile($phar, $file); } else { $this->addFile($phar, $file, false); @@ -241,7 +242,7 @@ class Compiler '@release_date@' => $this->versionDate->format('Y-m-d H:i:s'), ) ); - $content = preg_replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content); + $content = Preg::replace('{SOURCE_VERSION = \'[^\']+\';}', 'SOURCE_VERSION = \'\';', $content); } $phar->addFromString($path, $content); @@ -253,7 +254,7 @@ class Compiler private function addComposerBin(\Phar $phar) { $content = file_get_contents(__DIR__.'/../../bin/composer'); - $content = preg_replace('{^#!/usr/bin/env php\s*}', '', $content); + $content = Preg::replace('{^#!/usr/bin/env php\s*}', '', $content); $phar->addFromString('bin/composer', $content); } @@ -277,11 +278,11 @@ class Compiler $output .= str_repeat("\n", substr_count($token[1], "\n")); } elseif (T_WHITESPACE === $token[0]) { // reduce wide spaces - $whitespace = preg_replace('{[ \t]+}', ' ', $token[1]); + $whitespace = Preg::replace('{[ \t]+}', ' ', $token[1]); // normalize newlines to \n - $whitespace = preg_replace('{(?:\r\n|\r|\n)}', "\n", $whitespace); + $whitespace = Preg::replace('{(?:\r\n|\r|\n)}', "\n", $whitespace); // trim leading spaces - $whitespace = preg_replace('{\n +}', "\n", $whitespace); + $whitespace = Preg::replace('{\n +}', "\n", $whitespace); $output .= $whitespace; } else { $output .= $token[1]; @@ -329,7 +330,7 @@ Phar::mapPhar('composer.phar'); EOF; // add warning once the phar is older than 60 days - if (preg_match('{^[a-f0-9]+$}', $this->version)) { + if (Preg::isMatch('{^[a-f0-9]+$}', $this->version)) { $warningTime = ((int) $this->versionDate->format('U')) + 60 * 86400; $stub .= "define('COMPOSER_DEV_WARNING_TIME', $warningTime);\n"; } diff --git a/src/Composer/Composer.php b/src/Composer/Composer.php index 83e64ae4a..362ea0bcd 100644 --- a/src/Composer/Composer.php +++ b/src/Composer/Composer.php @@ -14,6 +14,7 @@ namespace Composer; use Composer\Package\RootPackageInterface; use Composer\Package\Locker; +use Composer\Pcre\Preg; use Composer\Util\Loop; use Composer\Repository\RepositoryManager; use Composer\Installer\InstallationManager; @@ -78,7 +79,7 @@ class Composer } // we have a branch alias and version is a commit id, this must be a snapshot build - if (self::BRANCH_ALIAS_VERSION !== '' && preg_match('{^[a-f0-9]{40}$}', self::VERSION)) { + if (self::BRANCH_ALIAS_VERSION !== '' && Preg::isMatch('{^[a-f0-9]{40}$}', self::VERSION)) { return self::BRANCH_ALIAS_VERSION.'+'.self::VERSION; } diff --git a/src/Composer/Config.php b/src/Composer/Config.php index ddf46a499..aa3fc3981 100644 --- a/src/Composer/Config.php +++ b/src/Composer/Config.php @@ -15,6 +15,7 @@ namespace Composer; use Composer\Config\ConfigSourceInterface; use Composer\Downloader\TransportException; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; @@ -225,7 +226,7 @@ class Config } // auto-deactivate the default packagist.org repo if it gets redefined - if (isset($repository['type'], $repository['url']) && $repository['type'] === 'composer' && preg_match('{^https?://(?:[a-z0-9-.]+\.)?packagist.org(/|$)}', $repository['url'])) { + if (isset($repository['type'], $repository['url']) && $repository['type'] === 'composer' && Preg::isMatch('{^https?://(?:[a-z0-9-.]+\.)?packagist.org(/|$)}', $repository['url'])) { $this->disableRepoByName('packagist.org'); } @@ -328,7 +329,7 @@ class Config // numbers with kb/mb/gb support, without env var support case 'cache-files-maxsize': - if (!preg_match('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) { + if (!Preg::isMatch('/^\s*([0-9.]+)\s*(?:([kmg])(?:i?b)?)?\s*$/i', $this->config[$key], $matches)) { throw new \RuntimeException( "Could not parse the value of '$key': {$this->config[$key]}" ); @@ -361,7 +362,7 @@ class Config return (int) $this->config['cache-ttl']; case 'home': - $val = preg_replace('#^(\$HOME|~)(/|$)#', rtrim(Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE'), '/\\') . '/', $this->config[$key]); + $val = Preg::replace('#^(\$HOME|~)(/|$)#', rtrim(Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE'), '/\\') . '/', $this->config[$key]); return rtrim($this->process($val, $flags), '/\\'); @@ -507,7 +508,7 @@ class Config return $value; } - return preg_replace_callback('#\{\$(.+)\}#', function ($match) use ($config, $flags) { + return Preg::replaceCallback('#\{\$(.+)\}#', function ($match) use ($config, $flags) { return $config->get($match[1], $flags); }, $value); } @@ -522,7 +523,7 @@ class Config */ private function realpath($path) { - if (preg_match('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) { + if (Preg::isMatch('{^(?:/|[a-z]:|[a-z0-9.]+://)}i', $path)) { return $path; } diff --git a/src/Composer/Config/JsonConfigSource.php b/src/Composer/Config/JsonConfigSource.php index d9165d719..d2db24afd 100644 --- a/src/Composer/Config/JsonConfigSource.php +++ b/src/Composer/Config/JsonConfigSource.php @@ -15,6 +15,7 @@ namespace Composer\Config; use Composer\Json\JsonFile; use Composer\Json\JsonManipulator; use Composer\Json\JsonValidationException; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Silencer; @@ -102,7 +103,7 @@ class JsonConfigSource implements ConfigSourceInterface { $authConfig = $this->authConfig; $this->manipulateJson('addConfigSetting', $name, $value, function (&$config, $key, $val) use ($authConfig) { - if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) { + if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) { list($key, $host) = explode('.', $key, 2); if ($authConfig) { $config[$key][$host] = $val; @@ -122,7 +123,7 @@ class JsonConfigSource implements ConfigSourceInterface { $authConfig = $this->authConfig; $this->manipulateJson('removeConfigSetting', $name, function (&$config, $key) use ($authConfig) { - if (preg_match('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) { + if (Preg::isMatch('{^(bitbucket-oauth|github-oauth|gitlab-oauth|gitlab-token|bearer|http-basic|platform)\.}', $key)) { list($key, $host) = explode('.', $key, 2); if ($authConfig) { unset($config[$key][$host]); diff --git a/src/Composer/Console/HtmlOutputFormatter.php b/src/Composer/Console/HtmlOutputFormatter.php index a94ad4d57..7fc0876ec 100644 --- a/src/Composer/Console/HtmlOutputFormatter.php +++ b/src/Composer/Console/HtmlOutputFormatter.php @@ -12,6 +12,7 @@ namespace Composer\Console; +use Composer\Pcre\Preg; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Formatter\OutputFormatterStyle; @@ -70,6 +71,7 @@ class HtmlOutputFormatter extends OutputFormatter $clearEscapeCodes = '(?:39|49|0|22|24|25|27|28)'; + // TODO in 2.3 replace with Closure::fromCallable and then use Preg::replaceCallback return preg_replace_callback("{\033\[([0-9;]+)m(.*?)\033\[(?:".$clearEscapeCodes.";)*?".$clearEscapeCodes."m}s", array($this, 'formatHtml'), $formatted); } diff --git a/src/Composer/DependencyResolver/PoolBuilder.php b/src/Composer/DependencyResolver/PoolBuilder.php index 30e24a5c2..9ff306324 100644 --- a/src/Composer/DependencyResolver/PoolBuilder.php +++ b/src/Composer/DependencyResolver/PoolBuilder.php @@ -20,6 +20,7 @@ use Composer\Package\CompleteAliasPackage; use Composer\Package\CompletePackage; use Composer\Package\PackageInterface; use Composer\Package\Version\StabilityFilter; +use Composer\Pcre\Preg; use Composer\Plugin\PluginEvents; use Composer\Plugin\PrePoolCreateEvent; use Composer\Repository\PlatformRepository; @@ -552,7 +553,7 @@ class PoolBuilder { foreach ($this->updateAllowList as $pattern => $void) { $patternRegexp = BasePackage::packageNameToRegexp($pattern); - if (preg_match($patternRegexp, $package->getName())) { + if (Preg::isMatch($patternRegexp, $package->getName())) { return true; } } @@ -569,13 +570,13 @@ class PoolBuilder $patternRegexp = BasePackage::packageNameToRegexp($pattern); // update pattern matches a locked package? => all good foreach ($request->getLockedRepository()->getPackages() as $package) { - if (preg_match($patternRegexp, $package->getName())) { + if (Preg::isMatch($patternRegexp, $package->getName())) { continue 2; } } // update pattern matches a root require? => all good, probably a new package foreach ($request->getRequires() as $packageName => $constraint) { - if (preg_match($patternRegexp, $packageName)) { + if (Preg::isMatch($patternRegexp, $packageName)) { continue 2; } } diff --git a/src/Composer/DependencyResolver/Problem.php b/src/Composer/DependencyResolver/Problem.php index 47c6c967c..deb39d5f6 100644 --- a/src/Composer/DependencyResolver/Problem.php +++ b/src/Composer/DependencyResolver/Problem.php @@ -17,6 +17,7 @@ use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\PackageInterface; use Composer\Package\RootPackageInterface; +use Composer\Pcre\Preg; use Composer\Repository\RepositorySet; use Composer\Repository\LockArrayRepository; use Composer\Semver\Constraint\Constraint; @@ -123,8 +124,8 @@ class Problem $deduplicatableRuleTypes = array(Rule::RULE_PACKAGE_REQUIRES, Rule::RULE_PACKAGE_CONFLICT); foreach ($rules as $rule) { $message = $rule->getPrettyString($repositorySet, $request, $pool, $isVerbose, $installedMap, $learnedPool); - if (in_array($rule->getReason(), $deduplicatableRuleTypes, true) && preg_match('{^(?P\S+) (?P\S+) (?Prequires|conflicts)}', $message, $m)) { - $template = preg_replace('{^\S+ \S+ }', '%s%s ', $message); + if (in_array($rule->getReason(), $deduplicatableRuleTypes, true) && Preg::isMatch('{^(?P\S+) (?P\S+) (?Prequires|conflicts)}', $message, $m)) { + $template = Preg::replace('{^\S+ \S+ }', '%s%s ', $message); $messages[] = $template; $templates[$template][$m[1]][$parser->normalize($m[2])] = $m[2]; $sourcePackage = $rule->getSourcePackage($pool); @@ -146,7 +147,7 @@ class Problem } if (count($versions) > 1) { // remove the s from requires/conflicts to correct grammar - $message = preg_replace('{^(%s%s (?:require|conflict))s}', '$1', $message); + $message = Preg::replace('{^(%s%s (?:require|conflict))s}', '$1', $message); $result[] = sprintf($message, $package, '['.implode(', ', $versions).']'); } else { $result[] = sprintf($message, $package, ' '.reset($versions)); @@ -350,8 +351,8 @@ class Problem return array("- Root composer.json requires $packageName".self::constraintToText($constraint) . ', ', 'found '.self::getPackageList($packages, $isVerbose, $pool, $constraint).' but '.(self::hasMultipleNames($packages) ? 'these do' : 'it does').' not match the constraint.' . $suffix); } - if (!preg_match('{^[A-Za-z0-9_./-]+$}', $packageName)) { - $illegalChars = preg_replace('{[A-Za-z0-9_./-]+}', '', $packageName); + if (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $packageName)) { + $illegalChars = Preg::replace('{[A-Za-z0-9_./-]+}', '', $packageName); return array("- Root composer.json requires $packageName, it ", 'could not be found, it looks like its name is invalid, "'.$illegalChars.'" is not allowed in package names.'); } @@ -461,7 +462,7 @@ class Problem if (0 === stripos($version, 'dev-')) { $byMajor['dev'][] = $pretty; } else { - $byMajor[preg_replace('{^(\d+)\..*}', '$1', $version)][] = $pretty; + $byMajor[Preg::replace('{^(\d+)\..*}', '$1', $version)][] = $pretty; } } foreach ($byMajor as $majorVersion => $versionsForMajor) { diff --git a/src/Composer/Downloader/DownloadManager.php b/src/Composer/Downloader/DownloadManager.php index fe737d1b5..8e457f117 100644 --- a/src/Composer/Downloader/DownloadManager.php +++ b/src/Composer/Downloader/DownloadManager.php @@ -14,6 +14,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Exception\IrrecoverableDownloadException; use React\Promise\PromiseInterface; @@ -392,7 +393,7 @@ class DownloadManager { foreach ($this->packagePreferences as $pattern => $preference) { $pattern = '{^'.str_replace('\\*', '.*', preg_quote($pattern)).'$}i'; - if (preg_match($pattern, $package->getName())) { + if (Preg::isMatch($pattern, $package->getName())) { if ('dist' === $preference || (!$package->isDev() && 'auto' === $preference)) { return 'dist'; } diff --git a/src/Composer/Downloader/FossilDownloader.php b/src/Composer/Downloader/FossilDownloader.php index ccef029f6..f5215d966 100644 --- a/src/Composer/Downloader/FossilDownloader.php +++ b/src/Composer/Downloader/FossilDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; /** @@ -108,7 +109,7 @@ class FossilDownloader extends VcsDownloader $match = '/\d\d:\d\d:\d\d\s+\[' . $toReference . '\]/'; foreach ($this->process->splitLines($output) as $line) { - if (preg_match($match, $line)) { + if (Preg::isMatch($match, $line)) { break; } $log .= $line; diff --git a/src/Composer/Downloader/GitDownloader.php b/src/Composer/Downloader/GitDownloader.php index 26ffb28cd..4575af29b 100644 --- a/src/Composer/Downloader/GitDownloader.php +++ b/src/Composer/Downloader/GitDownloader.php @@ -15,6 +15,7 @@ namespace Composer\Downloader; use Composer\Config; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Git as GitUtil; use Composer\Util\Url; @@ -61,7 +62,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface { GitUtil::cleanEnv(); - $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/'; + $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/'; $gitVersion = GitUtil::getVersion($this->process); // --dissociate option is only available since git 2.3.0-rc0 @@ -86,7 +87,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface { GitUtil::cleanEnv(); $path = $this->normalizePath($path); - $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/'; + $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/'; $ref = $package->getSourceReference(); $flag = Platform::isWindows() ? '/D ' : ''; @@ -120,7 +121,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface ProcessExecutor::escape($url), ProcessExecutor::escape($path), ProcessExecutor::escape($cachePath), - ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)), + ProcessExecutor::escape(Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)), ), $command ); @@ -155,7 +156,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface throw new \RuntimeException('The .git directory is missing from '.$path.', see https://getcomposer.org/commit-deps for more information'); } - $cachePath = $this->config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', $url).'/'; + $cachePath = $this->config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', $url).'/'; $ref = $target->getSourceReference(); if (!empty($this->cachedPackages[$target->getId()][$ref])) { @@ -178,7 +179,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface ProcessExecutor::escape($url), ProcessExecutor::escape($ref.'^{commit}'), ProcessExecutor::escape($cachePath), - ProcessExecutor::escape(preg_replace('{://([^@]+?):(.+?)@}', '://', $url)), + ProcessExecutor::escape(Preg::replace('{://([^@]+?):(.+?)@}', '://', $url)), ), $command ); @@ -195,8 +196,8 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface $updateOriginUrl = false; if ( 0 === $this->process->execute('git remote -v', $output, $path) - && preg_match('{^origin\s+(?P\S+)}m', $output, $originMatch) - && preg_match('{^composer\s+(?P\S+)}m', $output, $composerMatch) + && Preg::isMatch('{^origin\s+(?P\S+)}m', $output, $originMatch) + && Preg::isMatch('{^composer\s+(?P\S+)}m', $output, $composerMatch) ) { if ($originMatch['url'] === $composerMatch['url'] && $composerMatch['url'] !== $target->getSourceUrl()) { $updateOriginUrl = true; @@ -244,13 +245,13 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface } $refs = trim($output); - if (!preg_match('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) { + if (!Preg::isMatch('{^([a-f0-9]+) HEAD$}mi', $refs, $match)) { // could not match the HEAD for some reason return null; } $headRef = $match[1]; - if (!preg_match_all('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) { + if (!Preg::isMatchAll('{^'.$headRef.' refs/heads/(.+)$}mi', $refs, $matches)) { // not on a branch, we are either on a not-modified tag or some sort of detached head, so skip this return null; } @@ -267,7 +268,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface // try to find matching branch names in remote repos foreach ($candidateBranches as $candidate) { - if (preg_match_all('{^[a-f0-9]+ refs/remotes/((?:[^/]+)/'.preg_quote($candidate).')$}mi', $refs, $matches)) { + if (Preg::isMatchAll('{^[a-f0-9]+ refs/remotes/((?:[^/]+)/'.preg_quote($candidate).')$}mi', $refs, $matches)) { foreach ($matches[1] as $match) { $branch = $candidate; $remoteBranches[] = $match; @@ -359,7 +360,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface $changes = array_map(function ($elem) { return ' '.$elem; - }, preg_split('{\s*\r?\n\s*}', $changes)); + }, Preg::split('{\s*\r?\n\s*}', $changes)); $this->io->writeError(' '.$package->getPrettyName().' has modified files:'); $this->io->writeError(array_slice($changes, 0, 10)); if (count($changes) > 10) { @@ -448,7 +449,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface // If the non-existent branch is actually the name of a file, the file // is checked out. $template = 'git checkout '.$force.'%s -- && git reset --hard %1$s --'; - $branch = preg_replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch); + $branch = Preg::replace('{(?:^dev-|(?:\.x)?-dev$)}i', '', $branch); $branches = null; if (0 === $this->process->execute('git branch -r', $output, $path)) { @@ -457,9 +458,9 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface // check whether non-commitish are branches or tags, and fetch branches with the remote name $gitRef = $reference; - if (!preg_match('{^[a-f0-9]{40}$}', $reference) + if (!Preg::isMatch('{^[a-f0-9]{40}$}', $reference) && $branches - && preg_match('{^\s+composer/'.preg_quote($reference).'$}m', $branches) + && Preg::isMatch('{^\s+composer/'.preg_quote($reference).'$}m', $branches) ) { $command = sprintf('git checkout '.$force.'-B %s %s -- && git reset --hard %2$s --', ProcessExecutor::escape($branch), ProcessExecutor::escape('composer/'.$reference)); if (0 === $this->process->execute($command, $output, $path)) { @@ -468,9 +469,9 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface } // try to checkout branch by name and then reset it so it's on the proper branch name - if (preg_match('{^[a-f0-9]{40}$}', $reference)) { + if (Preg::isMatch('{^[a-f0-9]{40}$}', $reference)) { // add 'v' in front of the branch if it was stripped when generating the pretty name - if (!preg_match('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && preg_match('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) { + if (!Preg::isMatch('{^\s+composer/'.preg_quote($branch).'$}m', $branches) && Preg::isMatch('{^\s+composer/v'.preg_quote($branch).'$}m', $branches)) { $branch = 'v' . $branch; } @@ -517,7 +518,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface protected function setPushUrl($path, $url) { // set push url for github projects - if (preg_match('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) { + if (Preg::isMatch('{^(?:https?|git)://'.GitUtil::getGitHubDomainsRegex($this->config).'/([^/]+)/([^/]+?)(?:\.git)?$}', $url, $match)) { $protocols = $this->config->get('github-protocols'); $pushUrl = 'git@'.$match[1].':'.$match[2].'/'.$match[3].'.git'; if (!in_array('ssh', $protocols, true)) { @@ -640,7 +641,7 @@ class GitDownloader extends VcsDownloader implements DvcsDownloaderInterface */ protected function getShortHash($reference) { - if (!$this->io->isVerbose() && preg_match('{^[0-9a-f]{40}$}', $reference)) { + if (!$this->io->isVerbose() && Preg::isMatch('{^[0-9a-f]{40}$}', $reference)) { return substr($reference, 0, 10); } diff --git a/src/Composer/Downloader/SvnDownloader.php b/src/Composer/Downloader/SvnDownloader.php index fa5596094..0d269121c 100644 --- a/src/Composer/Downloader/SvnDownloader.php +++ b/src/Composer/Downloader/SvnDownloader.php @@ -13,6 +13,7 @@ namespace Composer\Downloader; use Composer\Package\PackageInterface; +use Composer\Pcre\Preg; use Composer\Util\Svn as SvnUtil; use Composer\Repository\VcsRepository; use Composer\Util\ProcessExecutor; @@ -98,7 +99,7 @@ class SvnDownloader extends VcsDownloader $this->process->execute('svn status --ignore-externals', $output, $path); - return preg_match('{^ *[^X ] +}m', $output) ? $output : null; + return Preg::isMatch('{^ *[^X ] +}m', $output) ? $output : null; } /** @@ -145,7 +146,7 @@ class SvnDownloader extends VcsDownloader $changes = array_map(function ($elem) { return ' '.$elem; - }, preg_split('{\s*\r?\n\s*}', $changes)); + }, Preg::split('{\s*\r?\n\s*}', $changes)); $countChanges = count($changes); $this->io->writeError(sprintf(' '.$package->getPrettyName().' has modified file%s:', $countChanges === 1 ? '' : 's')); $this->io->writeError(array_slice($changes, 0, 10)); @@ -192,7 +193,7 @@ class SvnDownloader extends VcsDownloader */ protected function getCommitLogs($fromReference, $toReference, $path) { - if (preg_match('{@(\d+)$}', $fromReference) && preg_match('{@(\d+)$}', $toReference)) { + if (Preg::isMatch('{@(\d+)$}', $fromReference) && Preg::isMatch('{@(\d+)$}', $toReference)) { // retrieve the svn base url from the checkout folder $command = sprintf('svn info --non-interactive --xml -- %s', ProcessExecutor::escape($path)); if (0 !== $this->process->execute($command, $output, $path)) { @@ -202,7 +203,7 @@ class SvnDownloader extends VcsDownloader } $urlPattern = '#(.*)#'; - if (preg_match($urlPattern, $output, $matches)) { + if (Preg::isMatch($urlPattern, $output, $matches)) { $baseUrl = $matches[1]; } else { throw new \RuntimeException( @@ -211,8 +212,8 @@ class SvnDownloader extends VcsDownloader } // strip paths from references and only keep the actual revision - $fromRevision = preg_replace('{.*@(\d+)$}', '$1', $fromReference); - $toRevision = preg_replace('{.*@(\d+)$}', '$1', $toReference); + $fromRevision = Preg::replace('{.*@(\d+)$}', '$1', $fromReference); + $toRevision = Preg::replace('{.*@(\d+)$}', '$1', $toReference); $command = sprintf('svn log -r%s:%s --incremental', ProcessExecutor::escape($fromRevision), ProcessExecutor::escape($toRevision)); diff --git a/src/Composer/EventDispatcher/EventDispatcher.php b/src/Composer/EventDispatcher/EventDispatcher.php index b43a92fb3..88969e1d9 100644 --- a/src/Composer/EventDispatcher/EventDispatcher.php +++ b/src/Composer/EventDispatcher/EventDispatcher.php @@ -16,6 +16,7 @@ use Composer\DependencyResolver\Transaction; use Composer\Installer\InstallerEvent; use Composer\IO\IOInterface; use Composer\Composer; +use Composer\Pcre\Preg; use Composer\Util\Platform; use Composer\DependencyResolver\Operation\OperationInterface; use Composer\Repository\RepositoryInterface; @@ -253,9 +254,9 @@ class EventDispatcher $possibleLocalBinaries = $this->composer->getPackage()->getBinaries(); if ($possibleLocalBinaries) { foreach ($possibleLocalBinaries as $localExec) { - if (preg_match('{\b'.preg_quote($callable).'$}', $localExec)) { + if (Preg::isMatch('{\b'.preg_quote($callable).'$}', $localExec)) { $caller = BinaryInstaller::determineBinaryCaller($localExec); - $exec = preg_replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec); + $exec = Preg::replace('{^'.preg_quote($callable).'}', $caller . ' ' . $localExec, $exec); break; } } @@ -274,13 +275,13 @@ class EventDispatcher if (strpos($exec, '@php ') === 0) { $pathAndArgs = substr($exec, 5); if (Platform::isWindows()) { - $pathAndArgs = preg_replace_callback('{^\S+}', function ($path) { + $pathAndArgs = Preg::replaceCallback('{^\S+}', function ($path) { return str_replace('/', '\\', $path[0]); }, $pathAndArgs); } // match somename (not in quote, and not a qualified path) and if it is not a valid path from CWD then try to find it // in $PATH. This allows support for `@php foo` where foo is a binary name found in PATH but not an actual relative path - $matched = preg_match('{^[^\'"\s/\\\\]+}', $pathAndArgs, $match); + $matched = Preg::isMatch('{^[^\'"\s/\\\\]+}', $pathAndArgs, $match); if ($matched && !file_exists($match[0])) { $finder = new ExecutableFinder; if ($pathToExec = $finder->find($match[0])) { @@ -296,7 +297,7 @@ class EventDispatcher } if (Platform::isWindows()) { - $exec = preg_replace_callback('{^\S+}', function ($path) { + $exec = Preg::replaceCallback('{^\S+}', function ($path) { return str_replace('/', '\\', $path[0]); }, $exec); } @@ -579,7 +580,7 @@ class EventDispatcher if (is_dir($binDir)) { $binDir = realpath($binDir); $pathValue = Platform::getEnv($pathEnv); - if (!preg_match('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $pathValue)) { + if (!Preg::isMatch('{(^|'.PATH_SEPARATOR.')'.preg_quote($binDir).'($|'.PATH_SEPARATOR.')}', $pathValue)) { Platform::putEnv($pathEnv, $binDir.PATH_SEPARATOR.$pathValue); } } diff --git a/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php b/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php index d9b0c018d..de1388edd 100644 --- a/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php +++ b/src/Composer/Filter/PlatformRequirementFilter/IgnoreListPlatformRequirementFilter.php @@ -3,6 +3,7 @@ namespace Composer\Filter\PlatformRequirementFilter; use Composer\Package\BasePackage; +use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFilterInterface @@ -30,6 +31,6 @@ final class IgnoreListPlatformRequirementFilter implements PlatformRequirementFi return false; } - return 1 === preg_match($this->regexp, $req); + return Preg::isMatch($this->regexp, $req); } } diff --git a/src/Composer/IO/BaseIO.php b/src/Composer/IO/BaseIO.php index b1c11a1cb..7974fb5ba 100644 --- a/src/Composer/IO/BaseIO.php +++ b/src/Composer/IO/BaseIO.php @@ -13,6 +13,7 @@ namespace Composer\IO; use Composer\Config; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Psr\Log\LogLevel; @@ -129,7 +130,7 @@ abstract class BaseIO implements IOInterface foreach ($githubOauth as $domain => $token) { // allowed chars for GH tokens are from https://github.blog/changelog/2021-03-04-authentication-token-format-updates/ // plus dots which were at some point used for GH app integration tokens - if (!preg_match('{^[.A-Za-z0-9_]+$}', $token)) { + if (!Preg::isMatch('{^[.A-Za-z0-9_]+$}', $token)) { throw new \UnexpectedValueException('Your github oauth token for '.$domain.' contains invalid characters: "'.$token.'"'); } $this->checkAndSetAuthentication($domain, $token, 'x-oauth-basic'); diff --git a/src/Composer/IO/BufferIO.php b/src/Composer/IO/BufferIO.php index ea9864e91..627abec9d 100644 --- a/src/Composer/IO/BufferIO.php +++ b/src/Composer/IO/BufferIO.php @@ -12,6 +12,7 @@ namespace Composer\IO; +use Composer\Pcre\Preg; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Formatter\OutputFormatterInterface; @@ -55,7 +56,7 @@ class BufferIO extends ConsoleIO $output = stream_get_contents($this->output->getStream()); - $output = preg_replace_callback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) { + $output = Preg::replaceCallback("{(?<=^|\n|\x08)(.+?)(\x08+)}", function ($matches) { $pre = strip_tags($matches[1]); if (strlen($pre) === strlen($matches[2])) { diff --git a/src/Composer/Installer/BinaryInstaller.php b/src/Composer/Installer/BinaryInstaller.php index d0997ea4c..12afb168a 100644 --- a/src/Composer/Installer/BinaryInstaller.php +++ b/src/Composer/Installer/BinaryInstaller.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; @@ -153,7 +154,7 @@ class BinaryInstaller $handle = fopen($bin, 'r'); $line = fgets($handle); fclose($handle); - if (preg_match('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) { + if (Preg::isMatch('{^#!/(?:usr/bin/env )?(?:[^/]+/)*(.+)$}m', $line, $match)) { return trim($match[1]); } @@ -255,7 +256,7 @@ class BinaryInstaller $binContents = file_get_contents($bin); // For php files, we generate a PHP proxy instead of a shell one, // which allows calling the proxy with a custom php process - if (preg_match('{^(#!.*\r?\n)?<\?php}', $binContents, $match)) { + if (Preg::isMatch('{^(#!.*\r?\n)?<\?php}', $binContents, $match)) { // carry over the existing shebang if present, otherwise add our own $proxyCode = empty($match[1]) ? '#!/usr/bin/env php' : trim($match[1]); $binPathExported = $this->filesystem->findShortestPathCode($link, $bin, false, true); diff --git a/src/Composer/Installer/LibraryInstaller.php b/src/Composer/Installer/LibraryInstaller.php index ace603cfb..71f45e8e4 100644 --- a/src/Composer/Installer/LibraryInstaller.php +++ b/src/Composer/Installer/LibraryInstaller.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\Composer; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Repository\InstalledRepositoryInterface; use Composer\Package\PackageInterface; use Composer\Util\Filesystem; @@ -252,7 +253,7 @@ class LibraryInstaller implements InstallerInterface, BinaryPresenceInterface $targetDir = $package->getTargetDir(); if ($targetDir) { - return preg_replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath); + return Preg::replace('{/*'.str_replace('/', '/+', preg_quote($targetDir)).'/?$}', '', $installPath); } return $installPath; diff --git a/src/Composer/Installer/SuggestedPackagesReporter.php b/src/Composer/Installer/SuggestedPackagesReporter.php index 144ce4735..f8fb9d887 100644 --- a/src/Composer/Installer/SuggestedPackagesReporter.php +++ b/src/Composer/Installer/SuggestedPackagesReporter.php @@ -14,6 +14,7 @@ namespace Composer\Installer; use Composer\IO\IOInterface; use Composer\Package\PackageInterface; +use Composer\Pcre\Preg; use Composer\Repository\InstalledRepository; use Symfony\Component\Console\Formatter\OutputFormatter; @@ -232,7 +233,7 @@ class SuggestedPackagesReporter */ private function removeControlCharacters($string) { - return preg_replace( + return Preg::replace( '/[[:cntrl:]]/', '', str_replace("\n", ' ', $string) diff --git a/src/Composer/Json/JsonFile.php b/src/Composer/Json/JsonFile.php index a83f2fd73..5eba52339 100644 --- a/src/Composer/Json/JsonFile.php +++ b/src/Composer/Json/JsonFile.php @@ -12,6 +12,7 @@ namespace Composer\Json; +use Composer\Pcre\Preg; use JsonSchema\Validator; use Seld\JsonLint\JsonParser; use Seld\JsonLint\ParsingException; @@ -55,7 +56,7 @@ class JsonFile { $this->path = $path; - if (null === $httpDownloader && preg_match('{^https?://}i', $path)) { + if (null === $httpDownloader && Preg::isMatch('{^https?://}i', $path)) { throw new \InvalidArgumentException('http urls require a HttpDownloader instance to be passed'); } $this->httpDownloader = $httpDownloader; @@ -245,8 +246,8 @@ class JsonFile // compact brackets to follow recent php versions if (PHP_VERSION_ID < 50428 || (PHP_VERSION_ID >= 50500 && PHP_VERSION_ID < 50512) || (defined('JSON_C_VERSION') && version_compare(phpversion('json'), '1.3.6', '<'))) { - $json = preg_replace('/\[\s+\]/', '[]', $json); - $json = preg_replace('/\{\s+\}/', '{}', $json); + $json = Preg::replace('/\[\s+\]/', '[]', $json); + $json = Preg::replace('/\{\s+\}/', '{}', $json); } return $json; diff --git a/src/Composer/Json/JsonFormatter.php b/src/Composer/Json/JsonFormatter.php index 386e62673..4f75498ff 100644 --- a/src/Composer/Json/JsonFormatter.php +++ b/src/Composer/Json/JsonFormatter.php @@ -12,6 +12,8 @@ namespace Composer\Json; +use Composer\Pcre\Preg; + /** * Formats json strings used for php < 5.4 because the json_encode doesn't * supports the flags JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE @@ -66,7 +68,7 @@ class JsonFormatter if ($unescapeUnicode && function_exists('mb_convert_encoding')) { // https://stackoverflow.com/questions/2934563/how-to-decode-unicode-escape-sequences-like-u00ed-to-proper-utf-8-encoded-cha - $buffer = preg_replace_callback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) { + $buffer = Preg::replaceCallback('/(\\\\+)u([0-9a-f]{4})/i', function ($match) { $l = strlen($match[1]); if ($l % 2) { diff --git a/src/Composer/Json/JsonManipulator.php b/src/Composer/Json/JsonManipulator.php index 2d8b1afeb..f1fcdf520 100644 --- a/src/Composer/Json/JsonManipulator.php +++ b/src/Composer/Json/JsonManipulator.php @@ -12,6 +12,7 @@ namespace Composer\Json; +use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; /** @@ -46,7 +47,7 @@ class JsonManipulator if ($contents === '') { $contents = '{}'; } - if (!$this->pregMatch('#^\{(.*)\}$#s', $contents)) { + if (!Preg::isMatch('#^\{(.*)\}$#s', $contents)) { throw new \InvalidArgumentException('The json file must be an object ({})'); } $this->newline = false !== strpos($contents, "\r\n") ? "\r\n" : "\n"; @@ -80,7 +81,7 @@ class JsonManipulator $regex = '{'.self::$DEFINES.'^(?P\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'. '(?P'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P(?&json))(?P.*)}sx'; - if (!$this->pregMatch($regex, $this->contents, $matches)) { + if (!Preg::isMatch($regex, $this->contents, $matches)) { return false; } @@ -89,17 +90,17 @@ class JsonManipulator // try to find existing link $packageRegex = str_replace('/', '\\\\?/', preg_quote($package)); $regex = '{'.self::$DEFINES.'"(?P'.$packageRegex.')"(\s*:\s*)(?&string)}ix'; - if ($this->pregMatch($regex, $links, $packageMatches)) { + if (Preg::isMatch($regex, $links, $packageMatches)) { // update existing link $existingPackage = $packageMatches['package']; $packageRegex = str_replace('/', '\\\\?/', preg_quote($existingPackage)); - $links = preg_replace_callback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) { + $links = Preg::replaceCallback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) { return JsonFile::encode(str_replace('\\/', '/', $existingPackage)) . $m['separator'] . '"' . $constraint . '"'; }, $links); } else { - if ($this->pregMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) { + if (Preg::isMatch('#^\s*\{\s*\S+.*?(\s*\}\s*)$#s', $links, $match)) { // link missing but non empty links - $links = preg_replace( + $links = Preg::replace( '{'.preg_quote($match[1]).'$}', // addcslashes is used to double up backslashes/$ since preg_replace resolves them as back references otherwise, see #1588 addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($package).': '.JsonFile::encode($constraint) . $match[1], '\\$'), @@ -136,7 +137,7 @@ class JsonManipulator { $prefix = function ($requirement) { if (PlatformRepository::isPlatformPackage($requirement)) { - return preg_replace( + return Preg::replace( array( '/^php/', '/^hhvm/', @@ -277,7 +278,7 @@ class JsonManipulator preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P(?&object))(?P.*)}sx'; try { - if (!$this->pregMatch($nodeRegex, $this->contents, $match)) { + if (!Preg::isMatch($nodeRegex, $this->contents, $match)) { return false; } } catch (\RuntimeException $e) { @@ -297,8 +298,8 @@ class JsonManipulator // child exists $childRegex = '{'.self::$DEFINES.'(?P"'.preg_quote($name).'"\s*:\s*)(?P(?&json))(?P,?)}x'; - if ($this->pregMatch($childRegex, $children, $matches)) { - $children = preg_replace_callback($childRegex, function ($matches) use ($subName, $value, $that) { + if (Preg::isMatch($childRegex, $children, $matches)) { + $children = Preg::replaceCallback($childRegex, function ($matches) use ($subName, $value, $that) { if ($subName !== null) { $curVal = json_decode($matches['content'], true); if (!is_array($curVal)) { @@ -311,7 +312,7 @@ class JsonManipulator return $matches['start'] . $that->format($value, 1) . $matches['end']; }, $children); } else { - $this->pregMatch('#^{ (?P\s*?) (?P\S+.*?)? (?P\s*) }$#sx', $children, $match); + Preg::match('#^{ (?P\s*?) (?P\S+.*?)? (?P\s*) }$#sx', $children, $match); $whitespace = ''; if (!empty($match['trailingspace'])) { @@ -325,7 +326,7 @@ class JsonManipulator // child missing but non empty children if ($append) { - $children = preg_replace( + $children = Preg::replace( '#'.$whitespace.'}$#', addcslashes(',' . $this->newline . $this->indent . $this->indent . JsonFile::encode($name).': '.$this->format($value, 1) . $whitespace . '}', '\\$'), $children @@ -336,7 +337,7 @@ class JsonManipulator $whitespace = $match['leadingspace']; } - $children = preg_replace( + $children = Preg::replace( '#^{'.$whitespace.'#', addcslashes('{' . $whitespace . JsonFile::encode($name).': '.$this->format($value, 1) . ',' . $this->newline . $this->indent . $this->indent, '\\$'), $children @@ -352,7 +353,7 @@ class JsonManipulator } } - $this->contents = preg_replace_callback($nodeRegex, function ($m) use ($children) { + $this->contents = Preg::replaceCallback($nodeRegex, function ($m) use ($children) { return $m['start'] . $children . $m['end']; }, $this->contents); @@ -377,7 +378,7 @@ class JsonManipulator $nodeRegex = '{'.self::$DEFINES.'^(?P \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'. preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P(?&object))(?P.*)}sx'; try { - if (!$this->pregMatch($nodeRegex, $this->contents, $match)) { + if (!Preg::isMatch($nodeRegex, $this->contents, $match)) { return false; } } catch (\RuntimeException $e) { @@ -406,18 +407,18 @@ class JsonManipulator // try and find a match for the subkey $keyRegex = str_replace('/', '\\\\?/', preg_quote($name)); - if ($this->pregMatch('{"'.$keyRegex.'"\s*:}i', $children)) { + if (Preg::isMatch('{"'.$keyRegex.'"\s*:}i', $children)) { // find best match for the value of "name" - if (preg_match_all('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) { + if (Preg::isMatchAll('{'.self::$DEFINES.'"'.$keyRegex.'"\s*:\s*(?:(?&json))}x', $children, $matches)) { $bestMatch = ''; foreach ($matches[0] as $match) { if (strlen($bestMatch) < strlen($match)) { $bestMatch = $match; } } - $childrenClean = preg_replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count); + $childrenClean = Preg::replace('{,\s*'.preg_quote($bestMatch).'}i', '', $children, -1, $count); if (1 !== $count) { - $childrenClean = preg_replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count); + $childrenClean = Preg::replace('{'.preg_quote($bestMatch).'\s*,?\s*}i', '', $childrenClean, -1, $count); if (1 !== $count) { return false; } @@ -432,12 +433,12 @@ class JsonManipulator } // no child data left, $name was the only key in - $this->pregMatch('#^{ \s*? (?P\S+.*?)? (?P\s*) }$#sx', $childrenClean, $match); + Preg::match('#^{ \s*? (?P\S+.*?)? (?P\s*) }$#sx', $childrenClean, $match); if (empty($match['content'])) { $newline = $this->newline; $indent = $this->indent; - $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($indent, $newline) { + $this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($indent, $newline) { return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end']; }, $this->contents); @@ -452,7 +453,7 @@ class JsonManipulator } $that = $this; - $this->contents = preg_replace_callback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) { + $this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($that, $name, $subName, $childrenClean) { if ($subName !== null) { $curVal = json_decode($matches['content'], true); unset($curVal[$name][$subName]); @@ -478,7 +479,7 @@ class JsonManipulator // key exists already $regex = '{'.self::$DEFINES.'^(?P\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'. '(?P'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P.*)}sx'; - if (isset($decoded[$key]) && $this->pregMatch($regex, $this->contents, $matches)) { + if (isset($decoded[$key]) && Preg::isMatch($regex, $this->contents, $matches)) { // invalid match due to un-regexable content, abort if (!@json_decode('{'.$matches['key'].'}')) { return false; @@ -490,8 +491,8 @@ class JsonManipulator } // append at the end of the file and keep whitespace - if ($this->pregMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) { - $this->contents = preg_replace( + if (Preg::isMatch('#[^{\s](\s*)\}$#', $this->contents, $match)) { + $this->contents = Preg::replace( '#'.$match[1].'\}$#', addcslashes(',' . $this->newline . $this->indent . JsonFile::encode($key). ': '. $content . $this->newline . '}', '\\$'), $this->contents @@ -501,7 +502,7 @@ class JsonManipulator } // append at the end of the file - $this->contents = preg_replace( + $this->contents = Preg::replace( '#\}$#', addcslashes($this->indent . JsonFile::encode($key). ': '.$content . $this->newline . '}', '\\$'), $this->contents @@ -525,19 +526,19 @@ class JsonManipulator // key exists already $regex = '{'.self::$DEFINES.'^(?P\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'. '(?P'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P.*)}sx'; - if ($this->pregMatch($regex, $this->contents, $matches)) { + if (Preg::isMatch($regex, $this->contents, $matches)) { // invalid match due to un-regexable content, abort if (!@json_decode('{'.$matches['removal'].'}')) { return false; } // check that we are not leaving a dangling comma on the previous line if the last line was removed - if (preg_match('#,\s*$#', $matches['start']) && preg_match('#^\}$#', $matches['end'])) { - $matches['start'] = rtrim(preg_replace('#,(\s*)$#', '$1', $matches['start']), $this->indent); + if (Preg::isMatch('#,\s*$#', $matches['start']) && Preg::isMatch('#^\}$#', $matches['end'])) { + $matches['start'] = rtrim(Preg::replace('#,(\s*)$#', '$1', $matches['start']), $this->indent); } $this->contents = $matches['start'] . $matches['end']; - if (preg_match('#^\{\s*\}\s*$#', $this->contents)) { + if (Preg::isMatch('#^\{\s*\}\s*$#', $this->contents)) { $this->contents = "{\n}"; } @@ -601,47 +602,10 @@ class JsonManipulator */ protected function detectIndenting() { - if ($this->pregMatch('{^([ \t]+)"}m', $this->contents, $match)) { + if (Preg::isMatch('{^([ \t]+)"}m', $this->contents, $match)) { $this->indent = $match[1]; } else { $this->indent = ' '; } } - - /** - * @param string $re - * @param string $str - * @param array $matches - * @return int - */ - protected function pregMatch($re, $str, &$matches = array()) - { - $count = preg_match($re, $str, $matches); - - if ($count === false) { - switch (preg_last_error()) { - case PREG_NO_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_NO_ERROR', PREG_NO_ERROR); - case PREG_INTERNAL_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_INTERNAL_ERROR', PREG_INTERNAL_ERROR); - case PREG_BACKTRACK_LIMIT_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_BACKTRACK_LIMIT_ERROR', PREG_BACKTRACK_LIMIT_ERROR); - case PREG_RECURSION_LIMIT_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_RECURSION_LIMIT_ERROR', PREG_RECURSION_LIMIT_ERROR); - case PREG_BAD_UTF8_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_ERROR', PREG_BAD_UTF8_ERROR); - case PREG_BAD_UTF8_OFFSET_ERROR: - throw new \RuntimeException('Failed to execute regex: PREG_BAD_UTF8_OFFSET_ERROR', PREG_BAD_UTF8_OFFSET_ERROR); - case 6: // PREG_JIT_STACKLIMIT_ERROR - if (PHP_VERSION_ID > 70000) { - throw new \RuntimeException('Failed to execute regex: PREG_JIT_STACKLIMIT_ERROR', 6); - } - // no break - default: - throw new \RuntimeException('Failed to execute regex: Unknown error'); - } - } - - return $count; - } } diff --git a/src/Composer/Package/Archiver/ArchivableFilesFinder.php b/src/Composer/Package/Archiver/ArchivableFilesFinder.php index 7ee4e90ad..4dcb718ba 100644 --- a/src/Composer/Package/Archiver/ArchivableFilesFinder.php +++ b/src/Composer/Package/Archiver/ArchivableFilesFinder.php @@ -12,6 +12,7 @@ namespace Composer\Package\Archiver; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use FilesystemIterator; use Symfony\Component\Finder\Finder; @@ -61,7 +62,7 @@ class ArchivableFilesFinder extends \FilterIterator return false; } - $relativePath = preg_replace( + $relativePath = Preg::replace( '#^'.preg_quote($sources, '#').'#', '', $fs->normalizePath($file->getRealPath()) diff --git a/src/Composer/Package/Archiver/ArchiveManager.php b/src/Composer/Package/Archiver/ArchiveManager.php index d41d5df1b..a6682fb3b 100644 --- a/src/Composer/Package/Archiver/ArchiveManager.php +++ b/src/Composer/Package/Archiver/ArchiveManager.php @@ -14,6 +14,7 @@ namespace Composer\Package\Archiver; use Composer\Downloader\DownloadManager; use Composer\Package\RootPackageInterface; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Composer\Util\Loop; use Composer\Util\SyncHelper; @@ -86,11 +87,11 @@ class ArchiveManager if ($package->getArchiveName()) { $baseName = $package->getArchiveName(); } else { - $baseName = preg_replace('#[^a-z0-9-_]#i', '-', $package->getName()); + $baseName = Preg::replace('#[^a-z0-9-_]#i', '-', $package->getName()); } $nameParts = array($baseName); - if (null !== $package->getDistReference() && preg_match('{^[a-f0-9]{40}$}', $package->getDistReference())) { + if (null !== $package->getDistReference() && Preg::isMatch('{^[a-f0-9]{40}$}', $package->getDistReference())) { array_push($nameParts, $package->getDistReference(), $package->getDistType()); } else { array_push($nameParts, $package->getPrettyVersion(), $package->getDistReference()); diff --git a/src/Composer/Package/Archiver/BaseExcludeFilter.php b/src/Composer/Package/Archiver/BaseExcludeFilter.php index 71462ef98..74efd68f1 100644 --- a/src/Composer/Package/Archiver/BaseExcludeFilter.php +++ b/src/Composer/Package/Archiver/BaseExcludeFilter.php @@ -12,6 +12,7 @@ namespace Composer\Package\Archiver; +use Composer\Pcre\Preg; use Symfony\Component\Finder; /** @@ -59,8 +60,12 @@ abstract class BaseExcludeFilter $path = $relativePath; } - if (@preg_match($pattern, $path)) { - $exclude = !$negate; + try { + if (Preg::isMatch($pattern, $path)) { + $exclude = !$negate; + } + } catch (\RuntimeException $e) { + // suppressed } } diff --git a/src/Composer/Package/Archiver/GitExcludeFilter.php b/src/Composer/Package/Archiver/GitExcludeFilter.php index 896c3946b..6a9294529 100644 --- a/src/Composer/Package/Archiver/GitExcludeFilter.php +++ b/src/Composer/Package/Archiver/GitExcludeFilter.php @@ -12,6 +12,8 @@ namespace Composer\Package\Archiver; +use Composer\Pcre\Preg; + /** * An exclude filter that processes gitattributes * @@ -50,7 +52,7 @@ class GitExcludeFilter extends BaseExcludeFilter */ public function parseGitAttributesLine($line) { - $parts = preg_split('#\s+#', $line); + $parts = Preg::split('#\s+#', $line); if (count($parts) == 2 && $parts[1] === 'export-ignore') { return $this->generatePattern($parts[0]); diff --git a/src/Composer/Package/Loader/ArrayLoader.php b/src/Composer/Package/Loader/ArrayLoader.php index 7e91cdac0..f7f677e1b 100644 --- a/src/Composer/Package/Loader/ArrayLoader.php +++ b/src/Composer/Package/Loader/ArrayLoader.php @@ -21,6 +21,7 @@ use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\RootAliasPackage; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; /** * @author Konstantin Kudryashiv @@ -227,7 +228,7 @@ class ArrayLoader implements LoaderInterface } if (!empty($config['time'])) { - $time = preg_match('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time']; + $time = Preg::isMatch('/^\d++$/D', $config['time']) ? '@'.$config['time'] : $config['time']; try { $date = new \DateTime($time, new \DateTimeZone('UTC')); @@ -298,7 +299,7 @@ class ArrayLoader implements LoaderInterface } if ($aliasNormalized = $this->getBranchAlias($config)) { - $prettyAlias = preg_replace('{(\.9{7})+}', '.x', $aliasNormalized); + $prettyAlias = Preg::replace('{(\.9{7})+}', '.x', $aliasNormalized); if ($package instanceof RootPackage) { return new RootAliasPackage($package, $aliasNormalized, $prettyAlias); diff --git a/src/Composer/Package/Loader/RootPackageLoader.php b/src/Composer/Package/Loader/RootPackageLoader.php index ce4601756..cd061941c 100644 --- a/src/Composer/Package/Loader/RootPackageLoader.php +++ b/src/Composer/Package/Loader/RootPackageLoader.php @@ -16,6 +16,7 @@ use Composer\Package\BasePackage; use Composer\Config; use Composer\IO\IOInterface; use Composer\Package\RootAliasPackage; +use Composer\Pcre\Preg; use Composer\Repository\RepositoryFactory; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; @@ -196,7 +197,7 @@ class RootPackageLoader extends ArrayLoader private function extractAliases(array $requires, array $aliases) { foreach ($requires as $reqName => $reqVersion) { - if (preg_match('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) { + if (Preg::isMatch('{^([^,\s#]+)(?:#[^ ]+)? +as +([^,\s]+)$}', $reqVersion, $match)) { $aliases[] = array( 'package' => strtolower($reqName), 'version' => $this->versionParser->normalize($match[1], $reqVersion), @@ -232,9 +233,9 @@ class RootPackageLoader extends ArrayLoader $constraints = array(); // extract all sub-constraints in case it is an OR/AND multi-constraint - $orSplit = preg_split('{\s*\|\|?\s*}', trim($reqVersion)); + $orSplit = Preg::split('{\s*\|\|?\s*}', trim($reqVersion)); foreach ($orSplit as $orConstraint) { - $andSplit = preg_split('{(?< ,]) *(?< ,]) *(? $stability) || ($minimumStability > $stability)) { @@ -288,8 +289,8 @@ class RootPackageLoader extends ArrayLoader public static function extractReferences(array $requires, array $references) { foreach ($requires as $reqName => $reqVersion) { - $reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion); - if (preg_match('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) { + $reqVersion = Preg::replace('{^([^,\s@]+) as .+$}', '$1', $reqVersion); + if (Preg::isMatch('{^[^,\s@]+?#([a-f0-9]+)$}', $reqVersion, $match) && 'dev' === VersionParser::parseStability($reqVersion)) { $name = strtolower($reqName); $references[$name] = $match[1]; } diff --git a/src/Composer/Package/Loader/ValidatingArrayLoader.php b/src/Composer/Package/Loader/ValidatingArrayLoader.php index 9e3d2bb0f..3b180139d 100644 --- a/src/Composer/Package/Loader/ValidatingArrayLoader.php +++ b/src/Composer/Package/Loader/ValidatingArrayLoader.php @@ -13,6 +13,7 @@ namespace Composer\Package\Loader; use Composer\Package\BasePackage; +use Composer\Pcre\Preg; use Composer\Semver\Constraint\Constraint; use Composer\Package\Version\VersionParser; use Composer\Repository\PlatformRepository; @@ -251,7 +252,7 @@ class ValidatingArrayLoader implements LoaderInterface } if ($err = self::hasPackageNamingError($package, true)) { $this->errors[] = $linkType.'.'.$err; - } elseif (!preg_match('{^[A-Za-z0-9_./-]+$}', $package)) { + } elseif (!Preg::isMatch('{^[A-Za-z0-9_./-]+$}', $package)) { $this->warnings[] = $linkType.'.'.$package.' : invalid key, package names must be strings containing only [A-Za-z0-9_./-]'; } if (!is_string($constraint)) { @@ -353,10 +354,10 @@ class ValidatingArrayLoader implements LoaderInterface if (isset($this->config[$srcType]['reference']) && !is_string($this->config[$srcType]['reference']) && !is_int($this->config[$srcType]['reference'])) { $this->errors[] = $srcType . '.reference : should be a string or int, '.gettype($this->config[$srcType]['reference']).' given'; } - if (isset($this->config[$srcType]['reference']) && preg_match('{^\s*-}', (string) $this->config[$srcType]['reference'])) { + if (isset($this->config[$srcType]['reference']) && Preg::isMatch('{^\s*-}', (string) $this->config[$srcType]['reference'])) { $this->errors[] = $srcType . '.reference : must not start with a "-", "'.$this->config[$srcType]['reference'].'" given'; } - if (preg_match('{^\s*-}', $this->config[$srcType]['url'])) { + if (Preg::isMatch('{^\s*-}', $this->config[$srcType]['url'])) { $this->errors[] = $srcType . '.url : must not start with a "-", "'.$this->config[$srcType]['url'].'" given'; } } @@ -448,7 +449,7 @@ class ValidatingArrayLoader implements LoaderInterface return null; } - if (!preg_match('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) { + if (!Preg::isMatch('{^[a-z0-9](?:[_.-]?[a-z0-9]+)*/[a-z0-9](?:(?:[_.]?|-{0,2})[a-z0-9]+)*$}iD', $name)) { return $name.' is invalid, it should have a vendor name, a forward slash, and a package name. The vendor and package name can be words separated by -, . or _. The complete name should match "^[a-z0-9]([_.-]?[a-z0-9]+)*/[a-z0-9](([_.]?|-{0,2})[a-z0-9]+)*$".'; } @@ -458,16 +459,16 @@ class ValidatingArrayLoader implements LoaderInterface return $name.' is reserved, package and vendor names can not match any of: '.implode(', ', $reservedNames).'.'; } - if (preg_match('{\.json$}', $name)) { + if (Preg::isMatch('{\.json$}', $name)) { return $name.' is invalid, package names can not end in .json, consider renaming it or perhaps using a -json suffix instead.'; } - if (preg_match('{[A-Z]}', $name)) { + if (Preg::isMatch('{[A-Z]}', $name)) { if ($isLink) { return $name.' is invalid, it should not contain uppercase characters. Please use '.strtolower($name).' instead.'; } - $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name); + $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $name); $suggestName = strtolower($suggestName); return $name.' is invalid, it should not contain uppercase characters. We suggest using '.$suggestName.' instead.'; @@ -492,7 +493,7 @@ class ValidatingArrayLoader implements LoaderInterface return false; } - if (!preg_match('{^'.$regex.'$}u', $this->config[$property])) { + if (!Preg::isMatch('{^'.$regex.'$}u', $this->config[$property])) { $message = $property.' : invalid value ('.$this->config[$property].'), must match '.$regex; if ($mandatory) { $this->errors[] = $message; @@ -591,7 +592,7 @@ class ValidatingArrayLoader implements LoaderInterface continue; } - if ($regex && !preg_match('{^'.$regex.'$}u', $value)) { + if ($regex && !Preg::isMatch('{^'.$regex.'$}u', $value)) { $this->warnings[] = $property.'.'.$key.' : invalid value ('.$value.'), must match '.$regex; unset($this->config[$property][$key]); $pass = false; diff --git a/src/Composer/Package/Locker.php b/src/Composer/Package/Locker.php index e96152338..7911c4c23 100644 --- a/src/Composer/Package/Locker.php +++ b/src/Composer/Package/Locker.php @@ -14,6 +14,7 @@ namespace Composer\Package; use Composer\Json\JsonFile; use Composer\Installer\InstallationManager; +use Composer\Pcre\Preg; use Composer\Repository\LockArrayRepository; use Composer\Util\ProcessExecutor; use Composer\Package\Dumper\ArrayDumper; @@ -492,13 +493,13 @@ class Locker case 'git': GitUtil::cleanEnv(); - if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef).GitUtil::getNoShowSignatureFlag($this->process), $output, $path) && preg_match('{^\s*\d+\s*$}', $output)) { + if (0 === $this->process->execute('git log -n1 --pretty=%ct '.ProcessExecutor::escape($sourceRef).GitUtil::getNoShowSignatureFlag($this->process), $output, $path) && Preg::isMatch('{^\s*\d+\s*$}', $output)) { $datetime = new \DateTime('@'.trim($output), new \DateTimeZone('UTC')); } break; case 'hg': - if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && preg_match('{^\s*(\d+)\s*}', $output, $match)) { + if (0 === $this->process->execute('hg log --template "{date|hgdate}" -r '.ProcessExecutor::escape($sourceRef), $output, $path) && Preg::isMatch('{^\s*(\d+)\s*}', $output, $match)) { $datetime = new \DateTime('@'.$match[1], new \DateTimeZone('UTC')); } break; diff --git a/src/Composer/Package/Package.php b/src/Composer/Package/Package.php index c2713f663..33addc7c0 100644 --- a/src/Composer/Package/Package.php +++ b/src/Composer/Package/Package.php @@ -13,6 +13,7 @@ namespace Composer\Package; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; use Composer\Util\ComposerMirror; /** @@ -160,7 +161,7 @@ class Package extends BasePackage return null; } - return ltrim(preg_replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/'); + return ltrim(Preg::replace('{ (?:^|[\\\\/]+) \.\.? (?:[\\\\/]+|$) (?:\.\.? (?:[\\\\/]+|$) )*}x', '/', $this->targetDir), '/'); } /** @@ -703,10 +704,10 @@ class Package extends BasePackage // TODO generalize this a bit for self-managed/on-prem versions? Some kind of replace token in dist urls which allow this? if ( $this->getDistUrl() !== null - && preg_match('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $this->getDistUrl()) + && Preg::isMatch('{^https?://(?:(?:www\.)?bitbucket\.org|(api\.)?github\.com|(?:www\.)?gitlab\.com)/}i', $this->getDistUrl()) ) { $this->setDistReference($reference); - $this->setDistUrl(preg_replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $this->getDistUrl())); + $this->setDistUrl(Preg::replace('{(?<=/|sha=)[a-f0-9]{40}(?=/|$)}i', $reference, $this->getDistUrl())); } elseif ($this->getDistReference()) { // update the dist reference if there was one, but if none was provided ignore it $this->setDistReference($reference); } diff --git a/src/Composer/Package/Version/VersionGuesser.php b/src/Composer/Package/Version/VersionGuesser.php index 504263a6c..d9c18a823 100644 --- a/src/Composer/Package/Version/VersionGuesser.php +++ b/src/Composer/Package/Version/VersionGuesser.php @@ -13,6 +13,7 @@ namespace Composer\Package\Version; use Composer\Config; +use Composer\Pcre\Preg; use Composer\Repository\Vcs\HgDriver; use Composer\IO\NullIO; use Composer\Semver\VersionParser as SemverVersionParser; @@ -108,12 +109,12 @@ class VersionGuesser unset($versionData['feature_version'], $versionData['feature_pretty_version']); } - if ('-dev' === substr($versionData['version'], -4) && preg_match('{\.9{7}}', $versionData['version'])) { - $versionData['pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['version']); + if ('-dev' === substr($versionData['version'], -4) && Preg::isMatch('{\.9{7}}', $versionData['version'])) { + $versionData['pretty_version'] = Preg::replace('{(\.9{7})+}', '.x', $versionData['version']); } - if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && preg_match('{\.9{7}}', $versionData['feature_version'])) { - $versionData['feature_pretty_version'] = preg_replace('{(\.9{7})+}', '.x', $versionData['feature_version']); + if (!empty($versionData['feature_version']) && '-dev' === substr($versionData['feature_version'], -4) && Preg::isMatch('{\.9{7}}', $versionData['feature_version'])) { + $versionData['feature_pretty_version'] = Preg::replace('{(\.9{7})+}', '.x', $versionData['feature_version']); } return $versionData; @@ -142,7 +143,7 @@ class VersionGuesser // find current branch and collect all branch names foreach ($this->process->splitLines($output) as $branch) { - if ($branch && preg_match('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { + if ($branch && Preg::isMatch('{^(?:\* ) *(\(no branch\)|\(detached from \S+\)|\(HEAD detached at \S+\)|\S+) *([a-f0-9]+) .*$}', $branch, $match)) { if ( $match[1] === '(no branch)' || strpos($match[1], '(detached ') === 0 @@ -163,8 +164,8 @@ class VersionGuesser } } - if ($branch && !preg_match('{^ *.+/HEAD }', $branch)) { - if (preg_match('{^(?:\* )? *((?:remotes/(?:origin|upstream)/)?[^\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) { + if ($branch && !Preg::isMatch('{^ *.+/HEAD }', $branch)) { + if (Preg::isMatch('{^(?:\* )? *((?:remotes/(?:origin|upstream)/)?[^\s/]+) *([a-f0-9]+) .*$}', $branch, $match)) { $branches[] = $match[1]; } } @@ -284,7 +285,7 @@ class VersionGuesser if (!isset($packageConfig['extra']['branch-alias'][$version]) || strpos(json_encode($packageConfig), '"self.version"') ) { - $branch = preg_replace('{^dev-}', '', $version); + $branch = Preg::replace('{^dev-}', '', $version); $length = PHP_INT_MAX; // return directly, if branch is configured to be non-feature branch @@ -307,7 +308,7 @@ class VersionGuesser }); foreach ($branches as $candidate) { - $candidateVersion = preg_replace('{^remotes/\S+/}', '', $candidate); + $candidateVersion = Preg::replace('{^remotes/\S+/}', '', $candidate); // do not compare against itself or other feature branches if ($candidate === $branch || $this->isFeatureBranch($packageConfig, $candidateVersion)) { @@ -346,7 +347,7 @@ class VersionGuesser $nonFeatureBranches = implode('|', $packageConfig['non-feature-branches']); } - return !preg_match('{^(' . $nonFeatureBranches . '|master|main|latest|next|current|support|tip|trunk|default|develop|\d+\..+)$}', $branchName, $match); + return !Preg::isMatch('{^(' . $nonFeatureBranches . '|master|main|latest|next|current|support|tip|trunk|default|develop|\d+\..+)$}', $branchName, $match); } /** @@ -396,7 +397,7 @@ class VersionGuesser $urlPattern = '#.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))#'; - if (preg_match($urlPattern, $output, $matches)) { + if (Preg::isMatch($urlPattern, $output, $matches)) { if (isset($matches[2]) && ($branchesPath === $matches[2] || $tagsPath === $matches[2])) { // we are in a branches path $version = $this->versionParser->normalizeBranch($matches[3]); diff --git a/src/Composer/Package/Version/VersionParser.php b/src/Composer/Package/Version/VersionParser.php index c848522e2..2d11bf0e4 100644 --- a/src/Composer/Package/Version/VersionParser.php +++ b/src/Composer/Package/Version/VersionParser.php @@ -12,6 +12,7 @@ namespace Composer\Package\Version; +use Composer\Pcre\Preg; use Composer\Repository\PlatformRepository; use Composer\Semver\VersionParser as SemverVersionParser; use Composer\Semver\Semver; @@ -52,8 +53,8 @@ class VersionParser extends SemverVersionParser $result = array(); for ($i = 0, $count = count($pairs); $i < $count; $i++) { - $pair = preg_replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i])); - if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !preg_match('{(?<=[a-z0-9_/-])\*|\*(?=[a-z0-9_/-])}i', $pairs[$i + 1]) && !PlatformRepository::isPlatformPackage($pairs[$i + 1])) { + $pair = Preg::replace('{^([^=: ]+)[=: ](.*)$}', '$1 $2', trim($pairs[$i])); + if (false === strpos($pair, ' ') && isset($pairs[$i + 1]) && false === strpos($pairs[$i + 1], '/') && !Preg::isMatch('{(?<=[a-z0-9_/-])\*|\*(?=[a-z0-9_/-])}i', $pairs[$i + 1]) && !PlatformRepository::isPlatformPackage($pairs[$i + 1])) { $pair .= ' '.$pairs[$i + 1]; $i++; } diff --git a/src/Composer/Package/Version/VersionSelector.php b/src/Composer/Package/Version/VersionSelector.php index 5dfd6fa50..8e4b45faa 100644 --- a/src/Composer/Package/Version/VersionSelector.php +++ b/src/Composer/Package/Version/VersionSelector.php @@ -21,6 +21,7 @@ use Composer\Package\PackageInterface; use Composer\Composer; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Dumper\ArrayDumper; +use Composer\Pcre\Preg; use Composer\Repository\RepositorySet; use Composer\Repository\PlatformRepository; use Composer\Semver\Constraint\Constraint; @@ -192,7 +193,7 @@ class VersionSelector $dumper = new ArrayDumper(); $extra = $loader->getBranchAlias($dumper->dump($package)); if ($extra && $extra !== VersionParser::DEFAULT_BRANCH_ALIAS) { - $extra = preg_replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count); + $extra = Preg::replace('{^(\d+\.\d+\.\d+)(\.9999999)-dev$}', '$1.0', $extra, -1, $count); if ($count) { $extra = str_replace('.9999999', '.0', $extra); @@ -217,7 +218,7 @@ class VersionSelector $semanticVersionParts = explode('.', $version); // check to see if we have a semver-looking version - if (count($semanticVersionParts) == 4 && preg_match('{^0\D?}', $semanticVersionParts[3])) { + if (count($semanticVersionParts) == 4 && Preg::isMatch('{^0\D?}', $semanticVersionParts[3])) { // remove the last parts (i.e. the patch version number and any extra) if ($semanticVersionParts[0] === '0') { unset($semanticVersionParts[3]); diff --git a/src/Composer/Platform/Version.php b/src/Composer/Platform/Version.php index f3ed82a96..6c9cd8fa5 100644 --- a/src/Composer/Platform/Version.php +++ b/src/Composer/Platform/Version.php @@ -12,6 +12,8 @@ namespace Composer\Platform; +use Composer\Pcre\Preg; + /** * @author Lars Strojny */ @@ -26,7 +28,7 @@ class Version { $isFips = false; - if (!preg_match('/^(?[0-9.]+)(?[a-z]{0,2})?(?(?:-?(?:dev|pre|alpha|beta|rc|fips)[\d]*)*)?(?-\w+)?$/', $opensslVersion, $matches)) { + if (!Preg::isMatch('/^(?[0-9.]+)(?[a-z]{0,2})?(?(?:-?(?:dev|pre|alpha|beta|rc|fips)[\d]*)*)?(?-\w+)?$/', $opensslVersion, $matches)) { return null; } @@ -43,7 +45,7 @@ class Version */ public static function parseLibjpeg($libjpegVersion) { - if (!preg_match('/^(?\d+)(?[a-z]*)$/', $libjpegVersion, $matches)) { + if (!Preg::isMatch('/^(?\d+)(?[a-z]*)$/', $libjpegVersion, $matches)) { return null; } @@ -56,7 +58,7 @@ class Version */ public static function parseZoneinfoVersion($zoneinfoVersion) { - if (!preg_match('/^(?\d{4})(?[a-z]*)$/', $zoneinfoVersion, $matches)) { + if (!Preg::isMatch('/^(?\d{4})(?[a-z]*)$/', $zoneinfoVersion, $matches)) { return null; } diff --git a/src/Composer/Plugin/PluginManager.php b/src/Composer/Plugin/PluginManager.php index 7c8734811..d1a9e79fe 100644 --- a/src/Composer/Plugin/PluginManager.php +++ b/src/Composer/Plugin/PluginManager.php @@ -18,6 +18,7 @@ use Composer\IO\IOInterface; use Composer\Package\CompletePackage; use Composer\Package\Package; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; use Composer\Repository\RepositoryInterface; use Composer\Repository\InstalledRepository; use Composer\Repository\RootPackageRepository; @@ -173,7 +174,7 @@ class PluginManager return; } - if ($package->getName() === 'symfony/flex' && preg_match('{^[0-9.]+$}', $package->getVersion()) && version_compare($package->getVersion(), '1.9.8', '<')) { + if ($package->getName() === 'symfony/flex' && Preg::isMatch('{^[0-9.]+$}', $package->getVersion()) && version_compare($package->getVersion(), '1.9.8', '<')) { $this->io->writeError('The "' . $package->getName() . '" plugin '.($isGlobalPlugin ? '(installed globally) ' : '').'was skipped because it is not compatible with Composer 2+. Make sure to update it to version 1.9.8 or greater.'); return; @@ -234,13 +235,13 @@ class PluginManager if ($separatorPos) { $className = substr($class, $separatorPos + 1); } - $code = preg_replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1); + $code = Preg::replace('{^((?:final\s+)?(?:\s*))class\s+('.preg_quote($className).')}mi', '$1class $2_composer_tmp'.self::$classCounter, $code, 1); $code = strtr($code, array( '__FILE__' => var_export($path, true), '__DIR__' => var_export(dirname($path), true), '__CLASS__' => var_export($class, true), )); - $code = preg_replace('/^\s*<\?(php)?/i', '', $code, 1); + $code = Preg::replace('/^\s*<\?(php)?/i', '', $code, 1); eval($code); $class .= '_composer_tmp'.self::$classCounter; self::$classCounter++; diff --git a/src/Composer/Question/StrictConfirmationQuestion.php b/src/Composer/Question/StrictConfirmationQuestion.php index 19432201d..fdd7fcf03 100644 --- a/src/Composer/Question/StrictConfirmationQuestion.php +++ b/src/Composer/Question/StrictConfirmationQuestion.php @@ -12,6 +12,7 @@ namespace Composer\Question; +use Composer\Pcre\Preg; use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Question\Question; @@ -66,11 +67,11 @@ class StrictConfirmationQuestion extends Question return $default; } - if (preg_match($trueRegex, $answer)) { + if (Preg::isMatch($trueRegex, $answer)) { return true; } - if (preg_match($falseRegex, $answer)) { + if (Preg::isMatch($falseRegex, $answer)) { return false; } diff --git a/src/Composer/Repository/ArrayRepository.php b/src/Composer/Repository/ArrayRepository.php index 1e7d69f73..65e23b86e 100644 --- a/src/Composer/Repository/ArrayRepository.php +++ b/src/Composer/Repository/ArrayRepository.php @@ -20,6 +20,7 @@ use Composer\Package\PackageInterface; use Composer\Package\CompletePackageInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Version\StabilityFilter; +use Composer\Pcre\Preg; use Composer\Semver\Constraint\ConstraintInterface; use Composer\Semver\Constraint\Constraint; @@ -147,7 +148,7 @@ class ArrayRepository implements RepositoryInterface */ public function search($query, $mode = 0, $type = null) { - $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i'; + $regex = '{(?:'.implode('|', Preg::split('{\s+}', $query)).')}i'; $matches = array(); foreach ($this->getPackages() as $package) { @@ -155,8 +156,8 @@ class ArrayRepository implements RepositoryInterface if (isset($matches[$name])) { continue; } - if (preg_match($regex, $name) - || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && preg_match($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription())) + if (Preg::isMatch($regex, $name) + || ($mode === self::SEARCH_FULLTEXT && $package instanceof CompletePackageInterface && Preg::isMatch($regex, implode(' ', (array) $package->getKeywords()) . ' ' . $package->getDescription())) ) { if (null !== $type && $package->getType() !== $type) { continue; diff --git a/src/Composer/Repository/ComposerRepository.php b/src/Composer/Repository/ComposerRepository.php index 33e40fdda..3cfc59725 100644 --- a/src/Composer/Repository/ComposerRepository.php +++ b/src/Composer/Repository/ComposerRepository.php @@ -24,6 +24,7 @@ use Composer\Json\JsonFile; use Composer\Cache; use Composer\Config; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Plugin\PostFileDownloadEvent; use Composer\Semver\CompilingMatcher; use Composer\Util\HttpDownloader; @@ -135,7 +136,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito public function __construct(array $repoConfig, IOInterface $io, Config $config, HttpDownloader $httpDownloader, EventDispatcher $eventDispatcher = null) { parent::__construct(); - if (!preg_match('{^[\w.]+\??://}', $repoConfig['url'])) { + if (!Preg::isMatch('{^[\w.]+\??://}', $repoConfig['url'])) { // assume http as the default protocol $repoConfig['url'] = 'http://'.$repoConfig['url']; } @@ -161,13 +162,13 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito $this->url = $repoConfig['url']; // force url for packagist.org to repo.packagist.org - if (preg_match('{^(?Phttps?)://packagist\.org/?$}i', $this->url, $match)) { + if (Preg::isMatch('{^(?Phttps?)://packagist\.org/?$}i', $this->url, $match)) { $this->url = $match['proto'].'://repo.packagist.org'; } - $this->baseUrl = rtrim(preg_replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/'); + $this->baseUrl = rtrim(Preg::replace('{(?:/[^/\\\\]+\.json)?(?:[?#].*)?$}', '', $this->url), '/'); $this->io = $io; - $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)), 'a-z0-9.$~'); + $this->cache = new Cache($io, $config->get('cache-repo-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->url)), 'a-z0-9.$~'); $this->cache->setReadOnly($config->get('cache-read-only')); $this->versionParser = new VersionParser(); $this->loader = new ArrayLoader($this->versionParser); @@ -350,7 +351,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito if (null !== $packageFilter) { $packageFilterRegex = '{^'.str_replace('\\*', '.*?', preg_quote($packageFilter)).'$}i'; $packageFilterCb = function ($name) use ($packageFilterRegex) { - return (bool) preg_match($packageFilterRegex, $name); + return Preg::isMatch($packageFilterRegex, $name); }; } @@ -490,11 +491,11 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito if ($this->hasProviders() || $this->lazyProvidersUrl) { $results = array(); - $regex = '{(?:'.implode('|', preg_split('{\s+}', $query)).')}i'; + $regex = '{(?:'.implode('|', Preg::split('{\s+}', $query)).')}i'; $packageNames = $this->getPackageNames(); - foreach (preg_grep($regex, $packageNames) as $name) { + foreach (Preg::grep($regex, $packageNames) as $name) { $results[] = array('name' => $name, 'description' => ''); } @@ -793,7 +794,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito foreach ($packageNames as $name => $constraint) { $name = strtolower($name); - $realName = preg_replace('{~dev$}', '', $name); + $realName = Preg::replace('{~dev$}', '', $name); // skip platform packages, root package and composer-plugin-api if (PlatformRepository::isPlatformPackage($realName) || '__root__' === $realName) { continue; @@ -1044,7 +1045,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito private function canonicalizeUrl($url) { if ('/' === $url[0]) { - if (preg_match('{^[^:]++://[^/]*+}', $this->url, $matches)) { + if (Preg::isMatch('{^[^:]++://[^/]*+}', $this->url, $matches)) { return $matches[0] . $url; } @@ -1204,7 +1205,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito } // url-encode $ signs in URLs as bad proxies choke on them - if (($pos = strpos($filename, '$')) && preg_match('{^https?://}i', $filename)) { + if (($pos = strpos($filename, '$')) && Preg::isMatch('{^https?://}i', $filename)) { $filename = substr($filename, 0, $pos) . '%24' . substr($filename, $pos + 1); } @@ -1509,7 +1510,7 @@ class ComposerRepository extends ArrayRepository implements ConfigurableReposito if (is_array($this->availablePackagePatterns)) { foreach ($this->availablePackagePatterns as $providerRegex) { - if (preg_match($providerRegex, $name)) { + if (Preg::isMatch($providerRegex, $name)) { return true; } } diff --git a/src/Composer/Repository/FilterRepository.php b/src/Composer/Repository/FilterRepository.php index 83b49df2b..0ee1ae53d 100644 --- a/src/Composer/Repository/FilterRepository.php +++ b/src/Composer/Repository/FilterRepository.php @@ -14,6 +14,7 @@ namespace Composer\Repository; use Composer\Package\PackageInterface; use Composer\Package\BasePackage; +use Composer\Pcre\Preg; /** * Filters which packages are seen as canonical on this repo by loadPackages @@ -202,9 +203,9 @@ class FilterRepository implements RepositoryInterface } if ($this->only) { - return (bool) preg_match($this->only, $name); + return Preg::isMatch($this->only, $name); } - return !preg_match($this->exclude, $name); + return !Preg::isMatch($this->exclude, $name); } } diff --git a/src/Composer/Repository/PackageRepository.php b/src/Composer/Repository/PackageRepository.php index 1a03f8347..b787931ca 100644 --- a/src/Composer/Repository/PackageRepository.php +++ b/src/Composer/Repository/PackageRepository.php @@ -14,6 +14,7 @@ namespace Composer\Repository; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Loader\ValidatingArrayLoader; +use Composer\Pcre\Preg; /** * Package repository. @@ -62,6 +63,6 @@ class PackageRepository extends ArrayRepository public function getRepoName() { - return preg_replace('{^array }', 'package ', parent::getRepoName()); + return Preg::replace('{^array }', 'package ', parent::getRepoName()); } } diff --git a/src/Composer/Repository/PathRepository.php b/src/Composer/Repository/PathRepository.php index ff1480dac..887d8151e 100644 --- a/src/Composer/Repository/PathRepository.php +++ b/src/Composer/Repository/PathRepository.php @@ -18,6 +18,7 @@ use Composer\Json\JsonFile; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionGuesser; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; use Composer\Util\Platform; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; @@ -141,9 +142,9 @@ class PathRepository extends ArrayRepository implements ConfigurableRepositoryIn $urlMatches = $this->getUrlMatches(); if (empty($urlMatches)) { - if (preg_match('{[*{}]}', $this->url)) { + if (Preg::isMatch('{[*{}]}', $this->url)) { $url = $this->url; - while (preg_match('{[*{}]}', $url)) { + while (Preg::isMatch('{[*{}]}', $url)) { $url = dirname($url); } // the parent directory before any wildcard exists, so we assume it is correctly configured but simply empty diff --git a/src/Composer/Repository/PlatformRepository.php b/src/Composer/Repository/PlatformRepository.php index 00e97f46f..4bf0a5b10 100644 --- a/src/Composer/Repository/PlatformRepository.php +++ b/src/Composer/Repository/PlatformRepository.php @@ -18,6 +18,7 @@ use Composer\Package\CompletePackageInterface; use Composer\Package\Link; use Composer\Package\PackageInterface; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; use Composer\Platform\HhvmDetector; use Composer\Platform\Runtime; use Composer\Platform\Version; @@ -146,7 +147,7 @@ class PlatformRepository extends ArrayRepository $prettyVersion = $this->runtime->getConstant('PHP_VERSION'); $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { - $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $this->runtime->getConstant('PHP_VERSION')); + $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $this->runtime->getConstant('PHP_VERSION')); $version = $this->versionParser->normalize($prettyVersion); } @@ -205,12 +206,12 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // librabbitmq version => 0.9.0 - if (preg_match('/^librabbitmq version => (?.+)$/im', $info, $librabbitmqMatches)) { + if (Preg::isMatch('/^librabbitmq version => (?.+)$/im', $info, $librabbitmqMatches)) { $this->addLibrary($name.'-librabbitmq', $librabbitmqMatches['version'], 'AMQP librabbitmq version'); } // AMQP protocol version => 0-9-1 - if (preg_match('/^AMQP protocol version => (?.+)$/im', $info, $protocolMatches)) { + if (Preg::isMatch('/^AMQP protocol version => (?.+)$/im', $info, $protocolMatches)) { $this->addLibrary($name.'-protocol', str_replace('-', '.', $protocolMatches['version']), 'AMQP protocol version'); } break; @@ -219,7 +220,7 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // BZip2 Version => 1.0.6, 6-Sept-2010 - if (preg_match('/^BZip2 Version => (?.*),/im', $info, $matches)) { + if (Preg::isMatch('/^BZip2 Version => (?.*),/im', $info, $matches)) { $this->addLibrary($name, $matches['version']); } break; @@ -231,7 +232,7 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // SSL Version => OpenSSL/1.0.1t - if (preg_match('{^SSL Version => (?[^/]+)/(?.+)$}im', $info, $sslMatches)) { + if (Preg::isMatch('{^SSL Version => (?[^/]+)/(?.+)$}im', $info, $sslMatches)) { $library = strtolower($sslMatches['library']); if ($library === 'openssl') { $parsedVersion = Version::parseOpenssl($sslMatches['version'], $isFips); @@ -242,12 +243,12 @@ class PlatformRepository extends ArrayRepository } // libSSH Version => libssh2/1.4.3 - if (preg_match('{^libSSH Version => (?[^/]+)/(?.+?)(?:/.*)?$}im', $info, $sshMatches)) { + if (Preg::isMatch('{^libSSH Version => (?[^/]+)/(?.+?)(?:/.*)?$}im', $info, $sshMatches)) { $this->addLibrary($name.'-'.strtolower($sshMatches['library']), $sshMatches['version'], 'curl '.$sshMatches['library'].' version'); } // ZLib Version => 1.2.8 - if (preg_match('{^ZLib Version => (?.+)$}im', $info, $zlibMatches)) { + if (Preg::isMatch('{^ZLib Version => (?.+)$}im', $info, $zlibMatches)) { $this->addLibrary($name.'-zlib', $zlibMatches['version'], 'curl zlib version'); } break; @@ -256,14 +257,14 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // timelib version => 2018.03 - if (preg_match('/^timelib version => (?.+)$/im', $info, $timelibMatches)) { + if (Preg::isMatch('/^timelib version => (?.+)$/im', $info, $timelibMatches)) { $this->addLibrary($name.'-timelib', $timelibMatches['version'], 'date timelib version'); } // Timezone Database => internal - if (preg_match('/^Timezone Database => (?internal|external)$/im', $info, $zoneinfoSourceMatches)) { + if (Preg::isMatch('/^Timezone Database => (?internal|external)$/im', $info, $zoneinfoSourceMatches)) { $external = $zoneinfoSourceMatches['source'] === 'external'; - if (preg_match('/^"Olson" Timezone Database Version => (?.+?)(\.system)?$/im', $info, $zoneinfoMatches)) { + if (Preg::isMatch('/^"Olson" Timezone Database Version => (?.+?)(\.system)?$/im', $info, $zoneinfoMatches)) { // If the timezonedb is provided by ext/timezonedb, register that version as a replacement if ($external && in_array('timezonedb', $loadedExtensions, true)) { $this->addLibrary('timezonedb-zoneinfo', $zoneinfoMatches['version'], 'zoneinfo ("Olson") database for date (replaced by timezonedb)', array($name.'-zoneinfo')); @@ -278,7 +279,7 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // libmagic => 537 - if (preg_match('/^libmagic => (?.+)$/im', $info, $magicMatches)) { + if (Preg::isMatch('/^libmagic => (?.+)$/im', $info, $magicMatches)) { $this->addLibrary($name.'-libmagic', $magicMatches['version'], 'fileinfo libmagic version'); } break; @@ -288,19 +289,19 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^libJPEG Version => (?.+?)(?: compatible)?$/im', $info, $libjpegMatches)) { + if (Preg::isMatch('/^libJPEG Version => (?.+?)(?: compatible)?$/im', $info, $libjpegMatches)) { $this->addLibrary($name.'-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd'); } - if (preg_match('/^libPNG Version => (?.+)$/im', $info, $libpngMatches)) { + if (Preg::isMatch('/^libPNG Version => (?.+)$/im', $info, $libpngMatches)) { $this->addLibrary($name.'-libpng', $libpngMatches['version'], 'libpng version for gd'); } - if (preg_match('/^FreeType Version => (?.+)$/im', $info, $freetypeMatches)) { + if (Preg::isMatch('/^FreeType Version => (?.+)$/im', $info, $freetypeMatches)) { $this->addLibrary($name.'-freetype', $freetypeMatches['version'], 'freetype version for gd'); } - if (preg_match('/^libXpm Version => (?\d+)$/im', $info, $libxpmMatches)) { + if (Preg::isMatch('/^libXpm Version => (?\d+)$/im', $info, $libxpmMatches)) { $this->addLibrary($name.'-libxpm', Version::convertLibxpmVersionId($libxpmMatches['versionId']), 'libxpm version for gd'); } @@ -321,12 +322,12 @@ class PlatformRepository extends ArrayRepository // Truthy check is for testing only so we can make the condition fail if ($this->runtime->hasConstant('INTL_ICU_VERSION')) { $this->addLibrary('icu', $this->runtime->getConstant('INTL_ICU_VERSION'), $description); - } elseif (preg_match('/^ICU version => (?.+)$/im', $info, $matches)) { + } elseif (Preg::isMatch('/^ICU version => (?.+)$/im', $info, $matches)) { $this->addLibrary('icu', $matches['version'], $description); } // ICU TZData version => 2019c - if (preg_match('/^ICU TZData version => (?.*)$/im', $info, $zoneinfoMatches)) { + if (Preg::isMatch('/^ICU TZData version => (?.*)$/im', $info, $zoneinfoMatches)) { $this->addLibrary('icu-zoneinfo', Version::parseZoneinfoVersion($zoneinfoMatches['version']), 'zoneinfo ("Olson") database for icu'); } @@ -345,7 +346,7 @@ class PlatformRepository extends ArrayRepository $imageMagickVersion = $this->runtime->construct('Imagick')->getVersion(); // 6.x: ImageMagick 6.2.9 08/24/06 Q16 http://www.imagemagick.org // 7.x: ImageMagick 7.0.8-34 Q16 x86_64 2019-03-23 https://imagemagick.org - preg_match('/^ImageMagick (?[\d.]+)(?:-(?\d+))?/', $imageMagickVersion['versionString'], $matches); + Preg::match('/^ImageMagick (?[\d.]+)(?:-(?\d+))?/', $imageMagickVersion['versionString'], $matches); $version = $matches['version']; if (isset($matches['patch'])) { $version .= '.'.$matches['patch']; @@ -357,7 +358,7 @@ class PlatformRepository extends ArrayRepository case 'ldap': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^Vendor Version => (?\d+)$/im', $info, $matches) && preg_match('/^Vendor Name => (?.+)$/im', $info, $vendorMatches)) { + if (Preg::isMatch('/^Vendor Version => (?\d+)$/im', $info, $matches) && Preg::isMatch('/^Vendor Name => (?.+)$/im', $info, $vendorMatches)) { $this->addLibrary($name.'-'.strtolower($vendorMatches['vendor']), Version::convertOpenldapVersionId($matches['versionId']), $vendorMatches['vendor'].' version of ldap'); } break; @@ -375,7 +376,7 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // libmbfl version => 1.3.2 - if (preg_match('/^libmbfl version => (?.+)$/im', $info, $libmbflMatches)) { + if (Preg::isMatch('/^libmbfl version => (?.+)$/im', $info, $libmbflMatches)) { $this->addLibrary($name.'-libmbfl', $libmbflMatches['version'], 'mbstring libmbfl version'); } @@ -384,7 +385,7 @@ class PlatformRepository extends ArrayRepository // Multibyte regex (oniguruma) version => 5.9.5 // oniguruma version => 6.9.0 - } elseif (preg_match('/^(?:oniguruma|Multibyte regex \(oniguruma\)) version => (?.+)$/im', $info, $onigurumaMatches)) { + } elseif (Preg::isMatch('/^(?:oniguruma|Multibyte regex \(oniguruma\)) version => (?.+)$/im', $info, $onigurumaMatches)) { $this->addLibrary($name.'-oniguruma', $onigurumaMatches['version'], 'mbstring oniguruma version'); } @@ -394,26 +395,26 @@ class PlatformRepository extends ArrayRepository $info = $this->runtime->getExtensionInfo($name); // libmemcached version => 1.0.18 - if (preg_match('/^libmemcached version => (?.+)$/im', $info, $matches)) { + if (Preg::isMatch('/^libmemcached version => (?.+)$/im', $info, $matches)) { $this->addLibrary($name.'-libmemcached', $matches['version'], 'libmemcached version'); } break; case 'openssl': // OpenSSL 1.1.1g 21 Apr 2020 - if (preg_match('{^(?:OpenSSL|LibreSSL)?\s*(?\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) { + if (Preg::isMatch('{^(?:OpenSSL|LibreSSL)?\s*(?\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) { $parsedVersion = Version::parseOpenssl($matches['version'], $isFips); $this->addLibrary($name.($isFips ? '-fips' : ''), $parsedVersion, $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), array(), $isFips ? array($name) : array()); } break; case 'pcre': - $this->addLibrary($name, preg_replace('{^(\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION'))); + $this->addLibrary($name, Preg::replace('{^(\S+).*}', '$1', $this->runtime->getConstant('PCRE_VERSION'))); $info = $this->runtime->getExtensionInfo($name); // PCRE Unicode Version => 12.1.0 - if (preg_match('/^PCRE Unicode Version => (?.+)$/im', $info, $pcreUnicodeMatches)) { + if (Preg::isMatch('/^PCRE Unicode Version => (?.+)$/im', $info, $pcreUnicodeMatches)) { $this->addLibrary($name.'-unicode', $pcreUnicodeMatches['version'], 'PCRE Unicode version support'); } @@ -423,7 +424,7 @@ class PlatformRepository extends ArrayRepository case 'pdo_mysql': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^(?:Client API version|Version) => mysqlnd (?.+?) /mi', $info, $matches)) { + if (Preg::isMatch('/^(?:Client API version|Version) => mysqlnd (?.+?) /mi', $info, $matches)) { $this->addLibrary($name.'-mysqlnd', $matches['version'], 'mysqlnd library version for '.$name); } break; @@ -431,11 +432,11 @@ class PlatformRepository extends ArrayRepository case 'mongodb': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^libmongoc bundled version => (?.+)$/im', $info, $libmongocMatches)) { + if (Preg::isMatch('/^libmongoc bundled version => (?.+)$/im', $info, $libmongocMatches)) { $this->addLibrary($name.'-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb'); } - if (preg_match('/^libbson bundled version => (?.+)$/im', $info, $libbsonMatches)) { + if (Preg::isMatch('/^libbson bundled version => (?.+)$/im', $info, $libbsonMatches)) { $this->addLibrary($name.'-libbson', $libbsonMatches['version'], 'libbson version of mongodb'); } break; @@ -444,7 +445,7 @@ class PlatformRepository extends ArrayRepository case 'pdo_pgsql': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^PostgreSQL\(libpq\) Version => (?.*)$/im', $info, $matches)) { + if (Preg::isMatch('/^PostgreSQL\(libpq\) Version => (?.*)$/im', $info, $matches)) { $this->addLibrary($name.'-libpq', $matches['version'], 'libpq for '.$name); } break; @@ -460,7 +461,7 @@ class PlatformRepository extends ArrayRepository case 'pdo_sqlite': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^SQLite Library => (?.+)$/im', $info, $matches)) { + if (Preg::isMatch('/^SQLite Library => (?.+)$/im', $info, $matches)) { $this->addLibrary($name.'-sqlite', $matches['version']); } break; @@ -468,7 +469,7 @@ class PlatformRepository extends ArrayRepository case 'ssh2': $info = $this->runtime->getExtensionInfo($name); - if (preg_match('/^libssh2 version => (?.+)$/im', $info, $matches)) { + if (Preg::isMatch('/^libssh2 version => (?.+)$/im', $info, $matches)) { $this->addLibrary($name.'-libssh2', $matches['version']); } break; @@ -477,7 +478,7 @@ class PlatformRepository extends ArrayRepository $this->addLibrary('libxslt', $this->runtime->getConstant('LIBXSLT_DOTTED_VERSION'), null, array('xsl')); $info = $this->runtime->getExtensionInfo('xsl'); - if (preg_match('/^libxslt compiled against libxml Version => (?.+)$/im', $info, $matches)) { + if (Preg::isMatch('/^libxslt compiled against libxml Version => (?.+)$/im', $info, $matches)) { $this->addLibrary('libxslt-libxml', $matches['version'], 'libxml version libxslt is compiled against'); } break; @@ -485,7 +486,7 @@ class PlatformRepository extends ArrayRepository case 'yaml': $info = $this->runtime->getExtensionInfo('yaml'); - if (preg_match('/^LibYAML Version => (?.+)$/im', $info, $matches)) { + if (Preg::isMatch('/^LibYAML Version => (?.+)$/im', $info, $matches)) { $this->addLibrary($name.'-libyaml', $matches['version'], 'libyaml version of yaml'); } break; @@ -501,7 +502,7 @@ class PlatformRepository extends ArrayRepository $this->addLibrary($name, $this->runtime->getConstant('ZLIB_VERSION')); // Linked Version => 1.2.8 - } elseif (preg_match('/^Linked Version => (?.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) { + } elseif (Preg::isMatch('/^Linked Version => (?.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) { $this->addLibrary($name, $matches['version']); } break; @@ -517,7 +518,7 @@ class PlatformRepository extends ArrayRepository $prettyVersion = $hhvmVersion; $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { - $prettyVersion = preg_replace('#^([^~+-]+).*$#', '$1', $hhvmVersion); + $prettyVersion = Preg::replace('#^([^~+-]+).*$#', '$1', $hhvmVersion); $version = $this->versionParser->normalize($prettyVersion); } @@ -625,7 +626,7 @@ class PlatformRepository extends ArrayRepository $version = $this->versionParser->normalize($prettyVersion); } catch (\UnexpectedValueException $e) { $extraDescription = ' (actual version: '.$prettyVersion.')'; - if (preg_match('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) { + if (Preg::isMatch('{^(\d+\.\d+\.\d+(?:\.\d+)?)}', $prettyVersion, $match)) { $prettyVersion = $match[1]; } else { $prettyVersion = '0'; @@ -709,7 +710,7 @@ class PlatformRepository extends ArrayRepository return $cache[$name]; } - return $cache[$name] = (bool) preg_match(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name); + return $cache[$name] = Preg::isMatch(PlatformRepository::PLATFORM_PACKAGE_REGEX, $name); } /** diff --git a/src/Composer/Repository/RepositoryFactory.php b/src/Composer/Repository/RepositoryFactory.php index 7143501fb..5891d0f7a 100644 --- a/src/Composer/Repository/RepositoryFactory.php +++ b/src/Composer/Repository/RepositoryFactory.php @@ -16,6 +16,7 @@ use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\EventDispatcher\EventDispatcher; +use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Util\ProcessExecutor; use Composer\Json\JsonFile; @@ -179,7 +180,7 @@ class RepositoryFactory */ public static function generateRepositoryName($index, array $repo, array $existingRepos) { - $name = is_int($index) && isset($repo['url']) ? preg_replace('{^https?://}i', '', $repo['url']) : $index; + $name = is_int($index) && isset($repo['url']) ? Preg::replace('{^https?://}i', '', $repo['url']) : $index; while (isset($existingRepos[$name])) { $name .= '2'; } diff --git a/src/Composer/Repository/Vcs/FossilDriver.php b/src/Composer/Repository/Vcs/FossilDriver.php index e78c399a8..66a50bdff 100644 --- a/src/Composer/Repository/Vcs/FossilDriver.php +++ b/src/Composer/Repository/Vcs/FossilDriver.php @@ -14,6 +14,7 @@ namespace Composer\Repository\Vcs; use Composer\Cache; use Composer\Config; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\IO\IOInterface; @@ -54,7 +55,7 @@ class FossilDriver extends VcsDriver throw new \RuntimeException('FossilDriver requires a usable cache directory, and it looks like you set it to be disabled'); } - $localName = preg_replace('{[^a-z0-9]}i', '-', $this->url); + $localName = Preg::replace('{[^a-z0-9]}i', '-', $this->url); $this->repoFile = $this->config->get('cache-repo-dir') . '/' . $localName . '.fossil'; $this->checkoutDir = $this->config->get('cache-vcs-dir') . '/' . $localName . '/'; @@ -208,7 +209,7 @@ class FossilDriver extends VcsDriver $this->process->execute('fossil branch list', $output, $this->checkoutDir); foreach ($this->process->splitLines($output) as $branch) { - $branch = trim(preg_replace('/^\*/', '', trim($branch))); + $branch = trim(Preg::replace('/^\*/', '', trim($branch))); $branches[$branch] = $branch; } @@ -223,11 +224,11 @@ class FossilDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (preg_match('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) { + if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]@)?(?:chiselapp\.com|fossil\.))#i', $url)) { return true; } - if (preg_match('!/fossil/|\.fossil!', $url)) { + if (Preg::isMatch('!/fossil/|\.fossil!', $url)) { return true; } diff --git a/src/Composer/Repository/Vcs/GitBitbucketDriver.php b/src/Composer/Repository/Vcs/GitBitbucketDriver.php index 8424ba61a..694204899 100644 --- a/src/Composer/Repository/Vcs/GitBitbucketDriver.php +++ b/src/Composer/Repository/Vcs/GitBitbucketDriver.php @@ -17,6 +17,7 @@ use Composer\IO\IOInterface; use Composer\Cache; use Composer\Downloader\TransportException; use Composer\Json\JsonFile; +use Composer\Pcre\Preg; use Composer\Util\Bitbucket; use Composer\Util\Http\Response; @@ -60,7 +61,7 @@ class GitBitbucketDriver extends VcsDriver */ public function initialize() { - preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i', $this->url, $match); + Preg::match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i', $this->url, $match); $this->owner = $match[1]; $this->repository = $match[2]; $this->originUrl = 'bitbucket.org'; @@ -463,7 +464,7 @@ class GitBitbucketDriver extends VcsDriver if ($cloneLink['name'] === 'https') { // Format: https://(user@)bitbucket.org/{user}/{repo} // Strip username from URL (only present in clone URL's for private repositories) - $this->cloneHttpsUrl = preg_replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']); + $this->cloneHttpsUrl = Preg::replace('/https:\/\/([^@]+@)?/', 'https://', $cloneLink['href']); } } } @@ -525,7 +526,7 @@ class GitBitbucketDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (!preg_match('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i', $url)) { + if (!Preg::isMatch('#^https?://bitbucket\.org/([^/]+)/([^/]+?)(\.git|/?)?$#i', $url)) { return false; } diff --git a/src/Composer/Repository/Vcs/GitDriver.php b/src/Composer/Repository/Vcs/GitDriver.php index dd0bab0f5..6b5cb2420 100644 --- a/src/Composer/Repository/Vcs/GitDriver.php +++ b/src/Composer/Repository/Vcs/GitDriver.php @@ -12,6 +12,7 @@ namespace Composer\Repository\Vcs; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Url; @@ -40,7 +41,7 @@ class GitDriver extends VcsDriver public function initialize() { if (Filesystem::isLocalPath($this->url)) { - $this->url = preg_replace('{[\\/]\.git/?$}', '', $this->url); + $this->url = Preg::replace('{[\\/]\.git/?$}', '', $this->url); if (!is_dir($this->url)) { throw new \RuntimeException('Failed to read package information from '.$this->url.' as the path does not exist'); } @@ -51,7 +52,7 @@ class GitDriver extends VcsDriver throw new \RuntimeException('GitDriver requires a usable cache directory, and it looks like you set it to be disabled'); } - $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . preg_replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; + $this->repoDir = $this->config->get('cache-vcs-dir') . '/' . Preg::replace('{[^a-z0-9.]}i', '-', $this->url) . '/'; GitUtil::cleanEnv(); @@ -62,7 +63,7 @@ class GitDriver extends VcsDriver throw new \RuntimeException('Can not clone '.$this->url.' to access package information. The "'.dirname($this->repoDir).'" directory is not writable by the current user.'); } - if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) { + if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $this->url)) { throw new \InvalidArgumentException('The source URL '.$this->url.' is invalid, ssh URLs should have a port number after ":".'."\n".'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); } @@ -80,7 +81,7 @@ class GitDriver extends VcsDriver $this->getTags(); $this->getBranches(); - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', Url::sanitize($cacheUrl))); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($cacheUrl))); $this->cache->setReadOnly($this->config->get('cache-read-only')); } @@ -97,7 +98,7 @@ class GitDriver extends VcsDriver $branches = $this->process->splitLines($output); if (!in_array('* master', $branches)) { foreach ($branches as $branch) { - if ($branch && preg_match('{^\* +(\S+)}', $branch, $match)) { + if ($branch && Preg::isMatch('{^\* +(\S+)}', $branch, $match)) { $this->rootIdentifier = $match[1]; break; } @@ -170,7 +171,7 @@ class GitDriver extends VcsDriver $this->process->execute('git show-ref --tags --dereference', $output, $this->repoDir); foreach ($output = $this->process->splitLines($output) as $tag) { - if ($tag && preg_match('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) { + if ($tag && Preg::isMatch('{^([a-f0-9]{40}) refs/tags/(\S+?)(\^\{\})?$}', $tag, $match)) { $this->tags[$match[2]] = $match[1]; } } @@ -189,8 +190,8 @@ class GitDriver extends VcsDriver $this->process->execute('git branch --no-color --no-abbrev -v', $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { - if ($branch && !preg_match('{^ *[^/]+/HEAD }', $branch)) { - if (preg_match('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) { + if ($branch && !Preg::isMatch('{^ *[^/]+/HEAD }', $branch)) { + if (Preg::isMatch('{^(?:\* )? *(\S+) *([a-f0-9]+)(?: .*)?$}', $branch, $match)) { $branches[$match[1]] = $match[2]; } } @@ -207,7 +208,7 @@ class GitDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (preg_match('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) { + if (Preg::isMatch('#(^git://|\.git/?$|git(?:olite)?@|//git\.|//github.com/)#i', $url)) { return true; } diff --git a/src/Composer/Repository/Vcs/GitHubDriver.php b/src/Composer/Repository/Vcs/GitHubDriver.php index 07daab475..e95492a66 100644 --- a/src/Composer/Repository/Vcs/GitHubDriver.php +++ b/src/Composer/Repository/Vcs/GitHubDriver.php @@ -17,6 +17,7 @@ use Composer\Downloader\TransportException; use Composer\Json\JsonFile; use Composer\Cache; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Util\GitHub; use Composer\Util\Http\Response; @@ -58,7 +59,7 @@ class GitHubDriver extends VcsDriver */ public function initialize() { - preg_match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match); + Preg::match('#^(?:(?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $this->url, $match); $this->owner = $match[3]; $this->repository = $match[4]; $this->originUrl = strtolower(!empty($match[1]) ? $match[1] : $match[2]); @@ -227,20 +228,20 @@ class GitHubDriver extends VcsDriver $result = array(); $key = null; - foreach (preg_split('{\r?\n}', $funding) as $line) { + foreach (Preg::split('{\r?\n}', $funding) as $line) { $line = trim($line); - if (preg_match('{^(\w+)\s*:\s*(.+)$}', $line, $match)) { - if (preg_match('{^\[(.*)\](?:\s*#.*)?$}', $match[2], $match2)) { - foreach (array_map('trim', preg_split('{[\'"]?\s*,\s*[\'"]?}', $match2[1])) as $item) { + if (Preg::isMatch('{^(\w+)\s*:\s*(.+)$}', $line, $match)) { + if (Preg::isMatch('{^\[(.*)\](?:\s*#.*)?$}', $match[2], $match2)) { + foreach (array_map('trim', Preg::split('{[\'"]?\s*,\s*[\'"]?}', $match2[1])) as $item) { $result[] = array('type' => $match[1], 'url' => trim($item, '"\' ')); } - } elseif (preg_match('{^([^#].*?)(\s+#.*)?$}', $match[2], $match2)) { + } elseif (Preg::isMatch('{^([^#].*?)(\s+#.*)?$}', $match[2], $match2)) { $result[] = array('type' => $match[1], 'url' => trim($match2[1], '"\' ')); } $key = null; - } elseif (preg_match('{^(\w+)\s*:\s*#\s*$}', $line, $match)) { + } elseif (Preg::isMatch('{^(\w+)\s*:\s*#\s*$}', $line, $match)) { $key = $match[1]; - } elseif ($key && preg_match('{^-\s*(.+)(\s+#.*)?$}', $line, $match)) { + } elseif ($key && Preg::isMatch('{^-\s*(.+)(\s+#.*)?$}', $line, $match)) { $result[] = array('type' => $key, 'url' => trim($match[1], '"\' ')); } } @@ -377,12 +378,12 @@ class GitHubDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (!preg_match('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) { + if (!Preg::isMatch('#^((?:https?|git)://([^/]+)/|git@([^:]+):/?)([^/]+)/(.+?)(?:\.git|/)?$#', $url, $matches)) { return false; } $originUrl = !empty($matches[2]) ? $matches[2] : $matches[3]; - if (!in_array(strtolower(preg_replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) { + if (!in_array(strtolower(Preg::replace('{^www\.}i', '', $originUrl)), $config->get('github-domains'))) { return false; } @@ -608,7 +609,7 @@ class GitHubDriver extends VcsDriver $links = explode(',', $header); foreach ($links as $link) { - if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) { + if (Preg::isMatch('{<(.+?)>; *rel="next"}', $link, $match)) { return $match[1]; } } diff --git a/src/Composer/Repository/Vcs/GitLabDriver.php b/src/Composer/Repository/Vcs/GitLabDriver.php index cfecee898..508a2aba0 100644 --- a/src/Composer/Repository/Vcs/GitLabDriver.php +++ b/src/Composer/Repository/Vcs/GitLabDriver.php @@ -17,6 +17,7 @@ use Composer\Cache; use Composer\IO\IOInterface; use Composer\Json\JsonFile; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; use Composer\Util\GitLab; use Composer\Util\Http\Response; @@ -92,7 +93,7 @@ class GitLabDriver extends VcsDriver */ public function initialize() { - if (!preg_match(self::URL_REGEX, $this->url, $match)) { + if (!Preg::isMatch(self::URL_REGEX, $this->url, $match)) { throw new \InvalidArgumentException('The URL provided is invalid. It must be the HTTP URL of a GitLab project.'); } @@ -119,7 +120,7 @@ class GitLabDriver extends VcsDriver } $this->namespace = implode('/', $urlParts); - $this->repository = preg_replace('#(\.git)$#', '', $match['repo']); + $this->repository = Preg::replace('#(\.git)$#', '', $match['repo']); $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.$this->originUrl.'/'.$this->namespace.'/'.$this->repository); $this->cache->setReadOnly($this->config->get('cache-read-only')); @@ -186,7 +187,7 @@ class GitLabDriver extends VcsDriver } // Convert the root identifier to a cacheable commit id - if (!preg_match('{[a-f0-9]{40}}i', $identifier)) { + if (!Preg::isMatch('{[a-f0-9]{40}}i', $identifier)) { $branches = $this->getBranches(); if (isset($branches[$identifier])) { $identifier = $branches[$identifier]; @@ -560,7 +561,7 @@ class GitLabDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (!preg_match(self::URL_REGEX, $url, $match)) { + if (!Preg::isMatch(self::URL_REGEX, $url, $match)) { return false; } @@ -590,7 +591,7 @@ class GitLabDriver extends VcsDriver $links = explode(',', $header); foreach ($links as $link) { - if (preg_match('{<(.+?)>; *rel="next"}', $link, $match)) { + if (Preg::isMatch('{<(.+?)>; *rel="next"}', $link, $match)) { return $match[1]; } } @@ -625,7 +626,7 @@ class GitLabDriver extends VcsDriver while (null !== ($part = array_shift($urlParts))) { $guessedDomain .= '/' . $part; - if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(preg_replace('{:\d+}', '', $guessedDomain), $configuredDomains))) { + if (in_array($guessedDomain, $configuredDomains) || ($portNumber && in_array(Preg::replace('{:\d+}', '', $guessedDomain), $configuredDomains))) { return $guessedDomain; } } diff --git a/src/Composer/Repository/Vcs/HgDriver.php b/src/Composer/Repository/Vcs/HgDriver.php index b1f63afd4..73bc426e5 100644 --- a/src/Composer/Repository/Vcs/HgDriver.php +++ b/src/Composer/Repository/Vcs/HgDriver.php @@ -14,6 +14,7 @@ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Cache; +use Composer\Pcre\Preg; use Composer\Util\Hg as HgUtils; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; @@ -46,7 +47,7 @@ class HgDriver extends VcsDriver } $cacheDir = $this->config->get('cache-vcs-dir'); - $this->repoDir = $cacheDir . '/' . preg_replace('{[^a-z0-9]}i', '-', $this->url) . '/'; + $this->repoDir = $cacheDir . '/' . Preg::replace('{[^a-z0-9]}i', '-', $this->url) . '/'; $fs = new Filesystem(); $fs->ensureDirectoryExists($cacheDir); @@ -162,7 +163,7 @@ class HgDriver extends VcsDriver $this->process->execute('hg tags', $output, $this->repoDir); foreach ($this->process->splitLines($output) as $tag) { - if ($tag && preg_match('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) { + if ($tag && Preg::isMatch('(^([^\s]+)\s+\d+:(.*)$)', $tag, $match)) { $tags[$match[1]] = $match[2]; } } @@ -185,14 +186,14 @@ class HgDriver extends VcsDriver $this->process->execute('hg branches', $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { - if ($branch && preg_match('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) { + if ($branch && Preg::isMatch('(^([^\s]+)\s+\d+:([a-f0-9]+))', $branch, $match)) { $branches[$match[1]] = $match[2]; } } $this->process->execute('hg bookmarks', $output, $this->repoDir); foreach ($this->process->splitLines($output) as $branch) { - if ($branch && preg_match('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) { + if ($branch && Preg::isMatch('(^(?:[\s*]*)([^\s]+)\s+\d+:(.*)$)', $branch, $match)) { $bookmarks[$match[1]] = $match[2]; } } @@ -209,7 +210,7 @@ class HgDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if (preg_match('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { + if (Preg::isMatch('#(^(?:https?|ssh)://(?:[^@]+@)?bitbucket.org|https://(?:.*?)\.kilnhg.com)#i', $url)) { return true; } diff --git a/src/Composer/Repository/Vcs/PerforceDriver.php b/src/Composer/Repository/Vcs/PerforceDriver.php index 3a8c99758..75a61037c 100644 --- a/src/Composer/Repository/Vcs/PerforceDriver.php +++ b/src/Composer/Repository/Vcs/PerforceDriver.php @@ -15,6 +15,7 @@ namespace Composer\Repository\Vcs; use Composer\Config; use Composer\Cache; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Perforce; @@ -160,7 +161,7 @@ class PerforceDriver extends VcsDriver */ public static function supports(IOInterface $io, Config $config, $url, $deep = false) { - if ($deep || preg_match('#\b(perforce|p4)\b#i', $url)) { + if ($deep || Preg::isMatch('#\b(perforce|p4)\b#i', $url)) { return Perforce::checkServerExists($url, new ProcessExecutor($io)); } diff --git a/src/Composer/Repository/Vcs/SvnDriver.php b/src/Composer/Repository/Vcs/SvnDriver.php index 6380ea387..c54b04838 100644 --- a/src/Composer/Repository/Vcs/SvnDriver.php +++ b/src/Composer/Repository/Vcs/SvnDriver.php @@ -15,6 +15,7 @@ namespace Composer\Repository\Vcs; use Composer\Cache; use Composer\Config; use Composer\Json\JsonFile; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\Filesystem; use Composer\Util\Url; @@ -82,7 +83,7 @@ class SvnDriver extends VcsDriver $this->baseUrl = substr($this->url, 0, $pos); } - $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->baseUrl))); + $this->cache = new Cache($this->io, $this->config->get('cache-repo-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', Url::sanitize($this->baseUrl))); $this->cache->setReadOnly($this->config->get('cache-read-only')); $this->getBranches(); @@ -126,7 +127,7 @@ class SvnDriver extends VcsDriver */ protected function shouldCache($identifier) { - return $this->cache && preg_match('{@\d+$}', $identifier); + return $this->cache && Preg::isMatch('{@\d+$}', $identifier); } /** @@ -168,7 +169,7 @@ class SvnDriver extends VcsDriver { $identifier = '/' . trim($identifier, '/') . '/'; - preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); + Preg::match('{^(.+?)(@\d+)?/$}', $identifier, $match); if (!empty($match[2])) { $path = $match[1]; $rev = $match[2]; @@ -197,7 +198,7 @@ class SvnDriver extends VcsDriver { $identifier = '/' . trim($identifier, '/') . '/'; - preg_match('{^(.+?)(@\d+)?/$}', $identifier, $match); + Preg::match('{^(.+?)(@\d+)?/$}', $identifier, $match); if (!empty($match[2])) { $path = $match[1]; $rev = $match[2]; @@ -208,7 +209,7 @@ class SvnDriver extends VcsDriver $output = $this->execute('svn info', $this->baseUrl . $path . $rev); foreach ($this->process->splitLines($output) as $line) { - if ($line && preg_match('{^Last Changed Date: ([^(]+)}', $line, $match)) { + if ($line && Preg::isMatch('{^Last Changed Date: ([^(]+)}', $line, $match)) { return new \DateTime($match[1], new \DateTimeZone('UTC')); } } @@ -229,7 +230,7 @@ class SvnDriver extends VcsDriver if ($output) { foreach ($this->process->splitLines($output) as $line) { $line = trim($line); - if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { + if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { if (isset($match[1], $match[2]) && $match[2] !== './') { $tags[rtrim($match[2], '/')] = $this->buildIdentifier( '/' . $this->tagsPath . '/' . $match[2], @@ -265,7 +266,7 @@ class SvnDriver extends VcsDriver if ($output) { foreach ($this->process->splitLines($output) as $line) { $line = trim($line); - if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { + if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { if (isset($match[1], $match[2]) && $match[2] === './') { $branches['trunk'] = $this->buildIdentifier( '/' . $this->trunkPath, @@ -284,7 +285,7 @@ class SvnDriver extends VcsDriver if ($output) { foreach ($this->process->splitLines(trim($output)) as $line) { $line = trim($line); - if ($line && preg_match('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { + if ($line && Preg::isMatch('{^\s*(\S+).*?(\S+)\s*$}', $line, $match)) { if (isset($match[1], $match[2]) && $match[2] !== './') { $branches[rtrim($match[2], '/')] = $this->buildIdentifier( '/' . $this->branchesPath . '/' . $match[2], @@ -308,7 +309,7 @@ class SvnDriver extends VcsDriver public static function supports(IOInterface $io, Config $config, $url, $deep = false) { $url = self::normalizeUrl($url); - if (preg_match('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) { + if (Preg::isMatch('#(^svn://|^svn\+ssh://|svn\.)#i', $url)) { return true; } diff --git a/src/Composer/Repository/Vcs/VcsDriver.php b/src/Composer/Repository/Vcs/VcsDriver.php index 060e20a4b..510e7efe8 100644 --- a/src/Composer/Repository/Vcs/VcsDriver.php +++ b/src/Composer/Repository/Vcs/VcsDriver.php @@ -17,6 +17,7 @@ use Composer\Downloader\TransportException; use Composer\Config; use Composer\IO\IOInterface; use Composer\Json\JsonFile; +use Composer\Pcre\Preg; use Composer\Util\ProcessExecutor; use Composer\Util\HttpDownloader; use Composer\Util\Filesystem; @@ -80,7 +81,7 @@ abstract class VcsDriver implements VcsDriverInterface */ protected function shouldCache($identifier) { - return $this->cache && preg_match('{^[a-f0-9]{40}$}iD', $identifier); + return $this->cache && Preg::isMatch('{^[a-f0-9]{40}$}iD', $identifier); } /** diff --git a/src/Composer/Repository/VcsRepository.php b/src/Composer/Repository/VcsRepository.php index 2281f1c76..993343188 100644 --- a/src/Composer/Repository/VcsRepository.php +++ b/src/Composer/Repository/VcsRepository.php @@ -13,6 +13,7 @@ namespace Composer\Repository; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; use Composer\Repository\Vcs\VcsDriverInterface; use Composer\Package\Version\VersionParser; use Composer\Package\Loader\ArrayLoader; @@ -270,8 +271,8 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt } // make sure tag packages have no -dev flag - $data['version'] = preg_replace('{[.-]?dev$}i', '', $data['version']); - $data['version_normalized'] = preg_replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']); + $data['version'] = Preg::replace('{[.-]?dev$}i', '', $data['version']); + $data['version_normalized'] = Preg::replace('{(^dev-|[.-]?dev$)}i', '', $data['version_normalized']); // make sure tag do not contain the default-branch marker unset($data['default-branch']); @@ -279,7 +280,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt // broken package, version doesn't match tag if ($data['version_normalized'] !== $parsedTag) { if ($isVeryVerbose) { - if (preg_match('{(^dev-|[.-]?dev$)}i', $parsedTag)) { + if (Preg::isMatch('{(^dev-|[.-]?dev$)}i', $parsedTag)) { $this->io->writeError('Skipped tag '.$tag.', invalid tag name, tags can not use dev prefixes or suffixes'); } else { $this->io->writeError('Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json'); @@ -348,7 +349,7 @@ class VcsRepository extends ArrayRepository implements ConfigurableRepositoryInt $version = 'dev-' . $branch; } else { $prefix = strpos($branch, 'v') === 0 ? 'v' : ''; - $version = $prefix . preg_replace('{(\.9{7})+}', '.x', $parsedBranch); + $version = $prefix . Preg::replace('{(\.9{7})+}', '.x', $parsedBranch); } $cachedPackage = $this->getCachedPackageVersion($version, $identifier, $isVerbose, $isVeryVerbose, $driver->getRootIdentifier() === $branch); diff --git a/src/Composer/SelfUpdate/Keys.php b/src/Composer/SelfUpdate/Keys.php index 808b8766d..64666f251 100644 --- a/src/Composer/SelfUpdate/Keys.php +++ b/src/Composer/SelfUpdate/Keys.php @@ -12,6 +12,8 @@ namespace Composer\SelfUpdate; +use Composer\Pcre\Preg; + /** * @author Jordi Boggiano */ @@ -24,7 +26,7 @@ class Keys */ public static function fingerprint($path) { - $hash = strtoupper(hash('sha256', preg_replace('{\s}', '', file_get_contents($path)))); + $hash = strtoupper(hash('sha256', Preg::replace('{\s}', '', file_get_contents($path)))); return implode(' ', array( substr($hash, 0, 8), diff --git a/src/Composer/Util/AuthHelper.php b/src/Composer/Util/AuthHelper.php index 6f6f2447d..daac49439 100644 --- a/src/Composer/Util/AuthHelper.php +++ b/src/Composer/Util/AuthHelper.php @@ -15,6 +15,7 @@ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; /** * @author Jordi Boggiano @@ -209,7 +210,7 @@ class AuthHelper $headers[] = 'Authorization: Bearer '.$auth['username']; } elseif ('github.com' === $origin && 'x-oauth-basic' === $auth['password']) { // only add the access_token if it is actually a github API URL - if (preg_match('{^https?://api\.github\.com/}', $url)) { + if (Preg::isMatch('{^https?://api\.github\.com/}', $url)) { $headers[] = 'Authorization: token '.$auth['username']; $authenticationDisplayMessage = 'Using GitHub token authentication'; } diff --git a/src/Composer/Util/ComposerMirror.php b/src/Composer/Util/ComposerMirror.php index 047c9c29b..f06668518 100644 --- a/src/Composer/Util/ComposerMirror.php +++ b/src/Composer/Util/ComposerMirror.php @@ -12,6 +12,8 @@ namespace Composer\Util; +use Composer\Pcre\Preg; + /** * Composer mirror utilities * @@ -32,7 +34,7 @@ class ComposerMirror public static function processUrl($mirrorUrl, $packageName, $version, $reference, $type, $prettyVersion = null) { if ($reference) { - $reference = preg_match('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference); + $reference = Preg::isMatch('{^([a-f0-9]*|%reference%)$}', $reference) ? $reference : md5($reference); } $version = strpos($version, '/') === false ? $version : md5($version); @@ -56,12 +58,12 @@ class ComposerMirror */ public static function processGitUrl($mirrorUrl, $packageName, $url, $type) { - if (preg_match('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) { + if (Preg::isMatch('#^(?:(?:https?|git)://github\.com/|git@github\.com:)([^/]+)/(.+?)(?:\.git)?$#', $url, $match)) { $url = 'gh-'.$match[1].'/'.$match[2]; - } elseif (preg_match('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) { + } elseif (Preg::isMatch('#^https://bitbucket\.org/([^/]+)/(.+?)(?:\.git)?/?$#', $url, $match)) { $url = 'bb-'.$match[1].'/'.$match[2]; } else { - $url = preg_replace('{[^a-z0-9_.-]}i', '-', trim($url, '/')); + $url = Preg::replace('{[^a-z0-9_.-]}i', '-', trim($url, '/')); } return str_replace( diff --git a/src/Composer/Util/ConfigValidator.php b/src/Composer/Util/ConfigValidator.php index b64f48d4b..aab3e3220 100644 --- a/src/Composer/Util/ConfigValidator.php +++ b/src/Composer/Util/ConfigValidator.php @@ -18,6 +18,7 @@ use Composer\Package\Loader\InvalidPackageException; use Composer\Json\JsonValidationException; use Composer\IO\IOInterface; use Composer\Json\JsonFile; +use Composer\Pcre\Preg; use Composer\Spdx\SpdxLicenses; /** @@ -93,12 +94,12 @@ class ConfigValidator foreach ($licenses as $license) { $spdxLicense = $licenseValidator->getLicenseByIdentifier($license); if ($spdxLicense && $spdxLicense[3]) { - if (preg_match('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) { + if (Preg::isMatch('{^[AL]?GPL-[123](\.[01])?\+$}i', $license)) { $warnings[] = sprintf( 'License "%s" is a deprecated SPDX license identifier, use "'.str_replace('+', '', $license).'-or-later" instead', $license ); - } elseif (preg_match('{^[AL]?GPL-[123](\.[01])?$}i', $license)) { + } elseif (Preg::isMatch('{^[AL]?GPL-[123](\.[01])?$}i', $license)) { $warnings[] = sprintf( 'License "%s" is a deprecated SPDX license identifier, use "'.$license.'-only" or "'.$license.'-or-later" instead', $license @@ -117,8 +118,8 @@ class ConfigValidator $warnings[] = 'The version field is present, it is recommended to leave it out if the package is published on Packagist.'; } - if (!empty($manifest['name']) && preg_match('{[A-Z]}', $manifest['name'])) { - $suggestName = preg_replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']); + if (!empty($manifest['name']) && Preg::isMatch('{[A-Z]}', $manifest['name'])) { + $suggestName = Preg::replace('{(?:([a-z])([A-Z])|([A-Z])([A-Z][a-z]))}', '\\1\\3-\\2\\4', $manifest['name']); $suggestName = strtolower($suggestName); $publishErrors[] = sprintf( @@ -162,7 +163,7 @@ class ConfigValidator $requireDev = isset($manifest['require-dev']) ? $manifest['require-dev'] : array(); $packages = array_merge($require, $requireDev); foreach ($packages as $package => $version) { - if (preg_match('/#/', $version) === 1) { + if (Preg::isMatch('/#/', $version)) { $warnings[] = sprintf( 'The package "%s" is pointing to a commit-ref, this is bad practice and can cause unforeseen issues.', $package diff --git a/src/Composer/Util/ErrorHandler.php b/src/Composer/Util/ErrorHandler.php index 7933f04e0..1bb7d4301 100644 --- a/src/Composer/Util/ErrorHandler.php +++ b/src/Composer/Util/ErrorHandler.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; /** * Convert PHP errors into exceptions @@ -55,7 +56,7 @@ class ErrorHandler if (self::$io) { // ignore symfony/* deprecation warnings // TODO remove in 2.3 - if (preg_match('{^Return type of Symfony\\\\.*ReturnTypeWillChange}is', $message)) { + if (Preg::isMatch('{^Return type of Symfony\\\\.*ReturnTypeWillChange}is', $message)) { return true; } if (strpos(strtr($file, '\\', '/'), 'vendor/symfony/') !== false) { diff --git a/src/Composer/Util/Filesystem.php b/src/Composer/Util/Filesystem.php index f3c660893..91b1cbe48 100644 --- a/src/Composer/Util/Filesystem.php +++ b/src/Composer/Util/Filesystem.php @@ -12,6 +12,7 @@ namespace Composer\Util; +use Composer\Pcre\Preg; use React\Promise\PromiseInterface; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -196,7 +197,7 @@ class Filesystem return true; } - if (preg_match('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) { + if (Preg::isMatch('{^(?:[a-z]:)?[/\\\\]+$}i', $directory)) { throw new \RuntimeException('Aborting an attempted deletion of '.$directory.', this was probably not intended, if it is a real use case please report it.'); } @@ -464,7 +465,7 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath)) { + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[a-z]:/?$}i', $commonPath)) { $commonPath = strtr(\dirname($commonPath), '\\', '/'); } @@ -503,7 +504,7 @@ class Filesystem } $commonPath = $to; - while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !preg_match('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { + while (strpos($from.'/', $commonPath.'/') !== 0 && '/' !== $commonPath && !Preg::isMatch('{^[a-z]:/?$}i', $commonPath) && '.' !== $commonPath) { $commonPath = strtr(\dirname($commonPath), '\\', '/'); } @@ -578,7 +579,7 @@ class Filesystem } // extract a prefix being a protocol://, protocol:, protocol://drive: or simply drive: - if (preg_match('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) { + if (Preg::isMatch('{^( [0-9a-z]{2,}+: (?: // (?: [a-z]: )? )? | [a-z]: )}ix', $path, $match)) { $prefix = $match[1]; $path = substr($path, \strlen($prefix)); } @@ -612,7 +613,7 @@ class Filesystem */ public static function trimTrailingSlash($path) { - if (!preg_match('{^[/\\\\]+$}', $path)) { + if (!Preg::isMatch('{^[/\\\\]+$}', $path)) { $path = rtrim($path, '/\\'); } @@ -627,7 +628,7 @@ class Filesystem */ public static function isLocalPath($path) { - return (bool) preg_match('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path); + return Preg::isMatch('{^(file://(?!//)|/(?!/)|/?[a-z]:[\\\\/]|\.\.[\\\\/]|[a-z0-9_.-]+[\\\\/])}i', $path); } /** @@ -638,10 +639,10 @@ class Filesystem public static function getPlatformPath($path) { if (Platform::isWindows()) { - $path = preg_replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path); + $path = Preg::replace('{^(?:file:///([a-z]):?/)}i', 'file://$1:/', $path); } - return (string) preg_replace('{^file://}i', '', $path); + return (string) Preg::replace('{^file://}i', '', $path); } /** diff --git a/src/Composer/Util/Git.php b/src/Composer/Util/Git.php index f3ebd1301..19f411bba 100644 --- a/src/Composer/Util/Git.php +++ b/src/Composer/Util/Git.php @@ -14,6 +14,7 @@ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; /** * @author Jordi Boggiano @@ -58,14 +59,14 @@ class Git $cwd = null; } - if (preg_match('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) { + if (Preg::isMatch('{^ssh://[^@]+@[^:]+:[^0-9]+}', $url)) { throw new \InvalidArgumentException('The source URL ' . $url . ' is invalid, ssh URLs should have a port number after ":".' . "\n" . 'Use ssh://git@example.com:22/path or just git@example.com:path if you do not want to provide a password or custom port.'); } if (!$initialClone) { // capture username/password from URL if there is one and we have no auth configured yet $this->process->execute('git remote -v', $output, $cwd); - if (preg_match('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) { + if (Preg::isMatch('{^(?:composer|origin)\s+https?://(.+):(.+)@([^/]+)}im', $output, $match) && !$this->io->hasAuthentication($match[3])) { $this->io->setAuthentication($match[3], rawurldecode($match[1]), rawurldecode($match[2])); } } @@ -75,7 +76,7 @@ class Git throw new \RuntimeException('Config value "github-protocols" must be an array, got ' . gettype($protocols)); } // public github, autoswitch protocols - if (preg_match('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) { + if (Preg::isMatch('{^(?:https?|git)://' . self::getGitHubDomainsRegex($this->config) . '/(.*)}', $url, $match)) { $messages = array(); foreach ($protocols as $protocol) { if ('ssh' === $protocol) { @@ -87,7 +88,7 @@ class Git if (0 === $this->process->execute(call_user_func($commandCallable, $protoUrl), $ignoredOutput, $cwd)) { return; } - $messages[] = '- ' . $protoUrl . "\n" . preg_replace('#^#m', ' ', $this->process->getErrorOutput()); + $messages[] = '- ' . $protoUrl . "\n" . Preg::replace('#^#m', ' ', $this->process->getErrorOutput()); if ($initialClone && isset($origCwd)) { $this->filesystem->removeDirectory($origCwd); @@ -101,7 +102,7 @@ class Git } // if we have a private github url and the ssh protocol is disabled then we skip it and directly fallback to https - $bypassSshForGitHub = preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true); + $bypassSshForGitHub = Preg::isMatch('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url) && !in_array('ssh', $protocols, true); $command = call_user_func($commandCallable, $url); @@ -110,8 +111,8 @@ class Git if ($bypassSshForGitHub || 0 !== $this->process->execute($command, $ignoredOutput, $cwd)) { $errorMsg = $this->process->getErrorOutput(); // private github repository without ssh key access, try https with auth - if (preg_match('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match) - || preg_match('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*?)(?:\.git)?$}i', $url, $match) + if (Preg::isMatch('{^git@' . self::getGitHubDomainsRegex($this->config) . ':(.+?)\.git$}i', $url, $match) + || Preg::isMatch('{^https?://' . self::getGitHubDomainsRegex($this->config) . '/(.*?)(?:\.git)?$}i', $url, $match) ) { if (!$this->io->hasAuthentication($match[1])) { $gitHubUtil = new GitHub($this->io, $this->config, $this->process); @@ -133,7 +134,7 @@ class Git $credentials = array(rawurlencode($auth['username']), rawurlencode($auth['password'])); $errorMsg = $this->process->getErrorOutput(); } - } elseif (preg_match('{^https://(bitbucket\.org)/(.*?)(?:\.git)?$}i', $url, $match)) { //bitbucket oauth + } elseif (Preg::isMatch('{^https://(bitbucket\.org)/(.*?)(?:\.git)?$}i', $url, $match)) { //bitbucket oauth $bitbucketUtil = new Bitbucket($this->io, $this->config, $this->process); if (!$this->io->hasAuthentication($match[1])) { @@ -178,8 +179,8 @@ class Git $errorMsg = $this->process->getErrorOutput(); } } elseif ( - preg_match('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match) - || preg_match('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}i', $url, $match) + Preg::isMatch('{^(git)@' . self::getGitLabDomainsRegex($this->config) . ':(.+?\.git)$}i', $url, $match) + || Preg::isMatch('{^(https?)://' . self::getGitLabDomainsRegex($this->config) . '/(.*)}i', $url, $match) ) { if ($match[1] === 'git') { $match[1] = 'https'; @@ -283,7 +284,7 @@ class Git if (is_dir($dir) && 0 === $this->process->execute('git rev-parse --git-dir', $output, $dir) && trim($output) === '.') { try { $commandCallable = function ($url) { - $sanitizedUrl = preg_replace('{://([^@]+?):(.+?)@}', '://', $url); + $sanitizedUrl = Preg::replace('{://([^@]+?):(.+?)@}', '://', $url); return sprintf('git remote set-url origin -- %s && git remote update --prune origin && git remote set-url origin -- %s && git gc --auto', ProcessExecutor::escape($url), ProcessExecutor::escape($sanitizedUrl)); }; @@ -369,7 +370,7 @@ class Git */ private function isAuthenticationFailure($url, &$match) { - if (!preg_match('{^(https?://)([^/]+)(.*)$}i', $url, $match)) { + if (!Preg::isMatch('{^(https?://)([^/]+)(.*)$}i', $url, $match)) { return false; } @@ -465,7 +466,7 @@ class Git { if (false === self::$version) { self::$version = null; - if (0 === $process->execute('git --version', $output) && preg_match('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) { + if (0 === $process->execute('git --version', $output) && Preg::isMatch('/^git version (\d+(?:\.\d+)+)/m', $output, $matches)) { self::$version = $matches[1]; } } diff --git a/src/Composer/Util/GitHub.php b/src/Composer/Util/GitHub.php index 190b50fe1..1c5b9a2aa 100644 --- a/src/Composer/Util/GitHub.php +++ b/src/Composer/Util/GitHub.php @@ -16,6 +16,7 @@ use Composer\Factory; use Composer\IO\IOInterface; use Composer\Config; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; /** * @author Jordi Boggiano @@ -180,7 +181,7 @@ class GitHub public function isRateLimited(array $headers) { foreach ($headers as $header) { - if (preg_match('{^X-RateLimit-Remaining: *0$}i', trim($header))) { + if (Preg::isMatch('{^X-RateLimit-Remaining: *0$}i', trim($header))) { return true; } } diff --git a/src/Composer/Util/GitLab.php b/src/Composer/Util/GitLab.php index f81a469c2..4c1376ad4 100644 --- a/src/Composer/Util/GitLab.php +++ b/src/Composer/Util/GitLab.php @@ -16,6 +16,7 @@ use Composer\IO\IOInterface; use Composer\Config; use Composer\Factory; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; /** * @author Roshan Gautam @@ -57,7 +58,7 @@ class GitLab public function authorizeOAuth($originUrl) { // before composer 1.9, origin URLs had no port number in them - $bcOriginUrl = preg_replace('{:\d+}', '', $originUrl); + $bcOriginUrl = Preg::replace('{:\d+}', '', $originUrl); if (!in_array($originUrl, $this->config->get('gitlab-domains'), true) && !in_array($bcOriginUrl, $this->config->get('gitlab-domains'), true)) { return false; diff --git a/src/Composer/Util/Hg.php b/src/Composer/Util/Hg.php index 94f1313f9..73e3a8e52 100644 --- a/src/Composer/Util/Hg.php +++ b/src/Composer/Util/Hg.php @@ -14,6 +14,7 @@ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; /** * @author Jonas Renaudot @@ -64,7 +65,7 @@ class Hg } // Try with the authentication information available - if (preg_match('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) { + if (Preg::isMatch('{^(https?)://((.+)(?:\:(.+))?@)?([^/]+)(/.*)?}mi', $url, $match) && $this->io->hasAuthentication($match[5])) { $auth = $this->io->getAuthentication($match[5]); $authenticatedUrl = $match[1] . '://' . rawurlencode($auth['username']) . ':' . rawurlencode($auth['password']) . '@' . $match[5] . (!empty($match[6]) ? $match[6] : null); @@ -106,7 +107,7 @@ class Hg { if (false === self::$version) { self::$version = null; - if (0 === $process->execute('hg --version', $output) && preg_match('/^.+? (\d+(?:\.\d+)+)\)?\r?\n/', $output, $matches)) { + if (0 === $process->execute('hg --version', $output) && Preg::isMatch('/^.+? (\d+(?:\.\d+)+)\)?\r?\n/', $output, $matches)) { self::$version = $matches[1]; } } diff --git a/src/Composer/Util/Http/CurlDownloader.php b/src/Composer/Util/Http/CurlDownloader.php index ac79b105c..b5d4f35d9 100644 --- a/src/Composer/Util/Http/CurlDownloader.php +++ b/src/Composer/Util/Http/CurlDownloader.php @@ -16,6 +16,7 @@ use Composer\Config; use Composer\Downloader\MaxFileSizeExceededException; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; use Composer\Util\StreamContextFactory; use Composer\Util\AuthHelper; use Composer\Util\Url; @@ -167,7 +168,7 @@ class CurlDownloader $originalOptions = $options; // check URL can be accessed (i.e. is not insecure), but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256 - if (!preg_match('{^http://(repo\.)?packagist\.org/p/}', $url) || (false === strpos($url, '$') && false === strpos($url, '%24'))) { + if (!Preg::isMatch('{^http://(repo\.)?packagist\.org/p/}', $url) || (false === strpos($url, '$') && false === strpos($url, '%24'))) { $this->config->prohibitUrlByConfig($url, $this->io); } @@ -181,7 +182,7 @@ class CurlDownloader if ($errorMessage) { $errorMessage .= "\n"; } - $errorMessage .= preg_replace('{^fopen\(.*?\): }', '', $msg); + $errorMessage .= Preg::replace('{^fopen\(.*?\): }', '', $msg); }); $bodyHandle = fopen($copyTo.'~', 'w+b'); restore_error_handler(); @@ -500,11 +501,11 @@ class CurlDownloader $urlHost = parse_url($job['url'], PHP_URL_HOST); // Replace path using hostname as an anchor. - $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $job['url']); + $targetUrl = Preg::replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $job['url']); } else { // Relative path; e.g. foo // This actually differs from PHP which seems to add duplicate slashes. - $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $job['url']); + $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $job['url']); } } @@ -540,7 +541,7 @@ class CurlDownloader && !$this->authHelper->isPublicBitBucketDownload($job['url']) && substr($job['url'], -4) === '.zip' && (!$locationHeader || substr($locationHeader, -4) !== '.zip') - && preg_match('{^text/html\b}i', $response->getHeader('content-type')) + && Preg::isMatch('{^text/html\b}i', $response->getHeader('content-type')) ) { $needsAuthRetry = 'Bitbucket requires authentication and it was not provided'; } diff --git a/src/Composer/Util/Http/Response.php b/src/Composer/Util/Http/Response.php index 46f0b3bf7..d94638ae4 100644 --- a/src/Composer/Util/Http/Response.php +++ b/src/Composer/Util/Http/Response.php @@ -13,6 +13,7 @@ namespace Composer\Util\Http; use Composer\Json\JsonFile; +use Composer\Pcre\Preg; use Composer\Util\HttpDownloader; /** @@ -61,7 +62,7 @@ class Response { $value = null; foreach ($this->headers as $header) { - if (preg_match('{^HTTP/\S+ \d+}i', $header)) { + if (Preg::isMatch('{^HTTP/\S+ \d+}i', $header)) { // In case of redirects, headers contain the headers of all responses // so we can not return directly and need to keep iterating $value = $header; @@ -123,7 +124,7 @@ class Response { $value = null; foreach ($headers as $header) { - if (preg_match('{^'.preg_quote($name).':\s*(.+?)\s*$}i', $header, $match)) { + if (Preg::isMatch('{^'.preg_quote($name).':\s*(.+?)\s*$}i', $header, $match)) { $value = $match[1]; } } diff --git a/src/Composer/Util/HttpDownloader.php b/src/Composer/Util/HttpDownloader.php index bb1f1f52d..6b3e7d61d 100644 --- a/src/Composer/Util/HttpDownloader.php +++ b/src/Composer/Util/HttpDownloader.php @@ -15,6 +15,7 @@ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; +use Composer\Pcre\Preg; use Composer\Util\Http\Response; use Composer\Util\Http\CurlDownloader; use Composer\Composer; @@ -226,7 +227,7 @@ class HttpDownloader } // capture username/password from URL if there is one - if (preg_match('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $request['url'], $match)) { + if (Preg::isMatch('{^https?://([^:/]+):([^@/]+)@([^/]+)}i', $request['url'], $match)) { $this->io->setAuthentication($job['origin'], rawurldecode($match[1]), rawurldecode($match[2])); } @@ -536,7 +537,7 @@ class HttpDownloader return false; } - if (!preg_match('{^https?://}i', $job['request']['url'])) { + if (!Preg::isMatch('{^https?://}i', $job['request']['url'])) { return false; } diff --git a/src/Composer/Util/NoProxyPattern.php b/src/Composer/Util/NoProxyPattern.php index 21f7c4fca..d06529eed 100644 --- a/src/Composer/Util/NoProxyPattern.php +++ b/src/Composer/Util/NoProxyPattern.php @@ -12,6 +12,7 @@ namespace Composer\Util; +use Composer\Pcre\Preg; use stdClass; /** @@ -39,7 +40,7 @@ class NoProxyPattern */ public function __construct($pattern) { - $this->hostNames = preg_split('{[\s,]+}', $pattern, -1, PREG_SPLIT_NO_EMPTY); + $this->hostNames = Preg::split('{[\s,]+}', $pattern, -1, PREG_SPLIT_NO_EMPTY); $this->noproxy = empty($this->hostNames) || '*' === $this->hostNames[0]; } diff --git a/src/Composer/Util/Perforce.php b/src/Composer/Util/Perforce.php index abf22dc45..d8ee9436b 100644 --- a/src/Composer/Util/Perforce.php +++ b/src/Composer/Util/Perforce.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Symfony\Component\Process\Process; /** @@ -634,7 +635,7 @@ class Perforce foreach ($resArray as $line) { $resBits = explode(' ', $line); if (count($resBits) > 4) { - $branch = preg_replace('/[^A-Za-z0-9 ]/', '', $resBits[4]); + $branch = Preg::replace('/[^A-Za-z0-9 ]/', '', $resBits[4]); $possibleBranches[$branch] = $resBits[1]; } } diff --git a/src/Composer/Util/Platform.php b/src/Composer/Util/Platform.php index 3098a4aa3..756c11506 100644 --- a/src/Composer/Util/Platform.php +++ b/src/Composer/Util/Platform.php @@ -12,6 +12,8 @@ namespace Composer\Util; +use Composer\Pcre\Preg; + /** * Platform helper for uniform platform-specific tests. * @@ -76,11 +78,11 @@ class Platform */ public static function expandPath($path) { - if (preg_match('#^~[\\/]#', $path)) { + if (Preg::isMatch('#^~[\\/]#', $path)) { return self::getUserDirectory() . substr($path, 1); } - return preg_replace_callback('#^(\$|(?P%))(?P\w++)(?(percent)%)(?P.*)#', function ($matches) { + return Preg::replaceCallback('#^(\$|(?P%))(?P\w++)(?(percent)%)(?P.*)#', function ($matches) { // Treat HOME as an alias for USERPROFILE on Windows for legacy reasons if (Platform::isWindows() && $matches['var'] == 'HOME') { return (Platform::getEnv('HOME') ?: Platform::getEnv('USERPROFILE')) . $matches['path']; diff --git a/src/Composer/Util/ProcessExecutor.php b/src/Composer/Util/ProcessExecutor.php index ddcf13139..afb3a0a07 100644 --- a/src/Composer/Util/ProcessExecutor.php +++ b/src/Composer/Util/ProcessExecutor.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; use Symfony\Component\Process\Process; use Symfony\Component\Process\Exception\RuntimeException; use React\Promise\Promise; @@ -102,15 +103,15 @@ class ProcessExecutor private function doExecute($command, $cwd, $tty, &$output = null) { if ($this->io && $this->io->isDebug()) { - $safeCommand = preg_replace_callback('{://(?P[^:/\s]+):(?P[^@\s/]+)@}i', function ($m) { + $safeCommand = Preg::replaceCallback('{://(?P[^:/\s]+):(?P[^@\s/]+)@}i', function ($m) { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that - if (preg_match('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { + if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { return '://***:***@'; } return '://'.$m['user'].':***@'; }, $command); - $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); + $safeCommand = Preg::replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); $this->io->writeError('Executing command ('.($cwd ?: 'CWD').'): '.$safeCommand); } @@ -249,14 +250,14 @@ class ProcessExecutor $cwd = $job['cwd']; if ($this->io && $this->io->isDebug()) { - $safeCommand = preg_replace_callback('{://(?P[^:/\s]+):(?P[^@\s/]+)@}i', function ($m) { - if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) { + $safeCommand = Preg::replaceCallback('{://(?P[^:/\s]+):(?P[^@\s/]+)@}i', function ($m) { + if (Preg::isMatch('{^[a-f0-9]{12,}$}', $m['user'])) { return '://***:***@'; } return '://'.$m['user'].':***@'; }, $command); - $safeCommand = preg_replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); + $safeCommand = Preg::replace("{--password (.*[^\\\\]\') }", '--password \'***\' ', $safeCommand); $this->io->writeError('Executing async command ('.($cwd ?: 'CWD').'): '.$safeCommand); } @@ -384,7 +385,7 @@ class ProcessExecutor { $output = trim((string) $output); - return $output === '' ? array() : preg_split('{\r?\n}', $output); + return $output === '' ? array() : Preg::split('{\r?\n}', $output); } /** @@ -482,20 +483,20 @@ class ProcessExecutor $argument = strtr($argument, "\n", ' '); $quote = strpbrk($argument, " \t") !== false; - $argument = preg_replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes); - $meta = $dquotes || preg_match('/%[^%]+%|![^!]+!/', $argument); + $argument = Preg::replace('/(\\\\*)"/', '$1$1\\"', $argument, -1, $dquotes); + $meta = $dquotes || Preg::isMatch('/%[^%]+%|![^!]+!/', $argument); if (!$meta && !$quote) { $quote = strpbrk($argument, '^&|<>()') !== false; } if ($quote) { - $argument = '"'.preg_replace('/(\\\\*)$/', '$1$1', $argument).'"'; + $argument = '"'.Preg::replace('/(\\\\*)$/', '$1$1', $argument).'"'; } if ($meta) { - $argument = preg_replace('/(["^&|<>()%])/', '^$1', $argument); - $argument = preg_replace('/(!)/', '^^$1', $argument); + $argument = Preg::replace('/(["^&|<>()%])/', '^$1', $argument); + $argument = Preg::replace('/(!)/', '^^$1', $argument); } return $argument; diff --git a/src/Composer/Util/RemoteFilesystem.php b/src/Composer/Util/RemoteFilesystem.php index 205c34a53..f35964975 100644 --- a/src/Composer/Util/RemoteFilesystem.php +++ b/src/Composer/Util/RemoteFilesystem.php @@ -17,6 +17,7 @@ use Composer\Downloader\MaxFileSizeExceededException; use Composer\IO\IOInterface; use Composer\Downloader\TransportException; use Composer\CaBundle\CaBundle; +use Composer\Pcre\Preg; use Composer\Util\Http\Response; use Composer\Util\Http\ProxyManager; @@ -177,7 +178,7 @@ class RemoteFilesystem { $value = null; foreach ($headers as $header) { - if (preg_match('{^HTTP/\S+ (\d+)}i', $header, $match)) { + if (Preg::isMatch('{^HTTP/\S+ (\d+)}i', $header, $match)) { // In case of redirects, http_response_headers contains the headers of all responses // so we can not return directly and need to keep iterating $value = (int) $match[1]; @@ -195,7 +196,7 @@ class RemoteFilesystem { $value = null; foreach ($headers as $header) { - if (preg_match('{^HTTP/\S+ \d+}i', $header)) { + if (Preg::isMatch('{^HTTP/\S+ \d+}i', $header)) { // In case of redirects, http_response_headers contains the headers of all responses // so we can not return directly and need to keep iterating $value = $header; @@ -281,7 +282,7 @@ class RemoteFilesystem unset($origFileUrl, $proxy, $usingProxy); // Check for secure HTTP, but allow insecure Packagist calls to $hashed providers as file integrity is verified with sha256 - if ((!preg_match('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist)) { + if ((!Preg::isMatch('{^http://(repo\.)?packagist\.org/p/}', $fileUrl) || (false === strpos($fileUrl, '$') && false === strpos($fileUrl, '%24'))) && empty($degradedPackagist)) { $this->config->prohibitUrlByConfig($fileUrl, $this->io); } @@ -296,7 +297,7 @@ class RemoteFilesystem if ($errorMessage) { $errorMessage .= "\n"; } - $errorMessage .= preg_replace('{^file_get_contents\(.*?\): }', '', $msg); + $errorMessage .= Preg::replace('{^file_get_contents\(.*?\): }', '', $msg); return true; }); @@ -386,7 +387,7 @@ class RemoteFilesystem && !$this->authHelper->isPublicBitBucketDownload($fileUrl) && substr($fileUrl, -4) === '.zip' && (!$locationHeader || substr(parse_url($locationHeader, PHP_URL_PATH), -4) !== '.zip') - && $contentType && preg_match('{^text/html\b}i', $contentType) + && $contentType && Preg::isMatch('{^text/html\b}i', $contentType) ) { $result = false; if ($retryAuthFailure) { @@ -463,7 +464,7 @@ class RemoteFilesystem if ($errorMessage) { $errorMessage .= "\n"; } - $errorMessage .= preg_replace('{^file_put_contents\(.*?\): }', '', $msg); + $errorMessage .= Preg::replace('{^file_put_contents\(.*?\): }', '', $msg); return true; }); @@ -752,11 +753,11 @@ class RemoteFilesystem $urlHost = parse_url($this->fileUrl, PHP_URL_HOST); // Replace path using hostname as an anchor. - $targetUrl = preg_replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl); + $targetUrl = Preg::replace('{^(.+(?://|@)'.preg_quote($urlHost).'(?::\d+)?)(?:[/\?].*)?$}', '\1'.$locationHeader, $this->fileUrl); } else { // Relative path; e.g. foo // This actually differs from PHP which seems to add duplicate slashes. - $targetUrl = preg_replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl); + $targetUrl = Preg::replace('{^(.+/)[^/?]*(?:\?.*)?$}', '\1'.$locationHeader, $this->fileUrl); } } diff --git a/src/Composer/Util/Svn.php b/src/Composer/Util/Svn.php index 4c59eab06..333802035 100644 --- a/src/Composer/Util/Svn.php +++ b/src/Composer/Util/Svn.php @@ -14,6 +14,7 @@ namespace Composer\Util; use Composer\Config; use Composer\IO\IOInterface; +use Composer\Pcre\Preg; /** * @author Till Klampaeckel @@ -380,7 +381,7 @@ class Svn { if (!self::$version) { if (0 === $this->process->execute('svn --version', $output)) { - if (preg_match('{(\d+(?:\.\d+)+)}', $output, $match)) { + if (Preg::isMatch('{(\d+(?:\.\d+)+)}', $output, $match)) { self::$version = $match[1]; } } diff --git a/src/Composer/Util/TlsHelper.php b/src/Composer/Util/TlsHelper.php index 01166d7b3..1ba0f806d 100644 --- a/src/Composer/Util/TlsHelper.php +++ b/src/Composer/Util/TlsHelper.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\CaBundle\CaBundle; +use Composer\Pcre\Preg; /** * @author Chris Smith @@ -75,7 +76,7 @@ final class TlsHelper $subjectAltNames = array(); if (isset($info['extensions']['subjectAltName'])) { - $subjectAltNames = preg_split('{\s*,\s*}', $info['extensions']['subjectAltName']); + $subjectAltNames = Preg::split('{\s*,\s*}', $info['extensions']['subjectAltName']); $subjectAltNames = array_filter(array_map(function ($name) { if (0 === strpos($name, 'DNS:')) { return strtolower(ltrim(substr($name, 4))); @@ -198,7 +199,7 @@ final class TlsHelper $wildcardRegex = "{^{$wildcardRegex}$}"; return function ($hostname) use ($wildcardRegex) { - return 1 === preg_match($wildcardRegex, $hostname); + return Preg::isMatch($wildcardRegex, $hostname); }; } diff --git a/src/Composer/Util/Url.php b/src/Composer/Util/Url.php index 7a281c924..c2ee92465 100644 --- a/src/Composer/Util/Url.php +++ b/src/Composer/Util/Url.php @@ -13,6 +13,7 @@ namespace Composer\Util; use Composer\Config; +use Composer\Pcre\Preg; /** * @author Jordi Boggiano @@ -30,30 +31,30 @@ class Url $host = parse_url($url, PHP_URL_HOST); if ($host === 'api.github.com' || $host === 'github.com' || $host === 'www.github.com') { - if (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) { + if (Preg::isMatch('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/(zip|tar)ball/(.+)$}i', $url, $match)) { // update legacy github archives to API calls with the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref; - } elseif (preg_match('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) { + } elseif (Preg::isMatch('{^https?://(?:www\.)?github\.com/([^/]+)/([^/]+)/archive/.+\.(zip|tar)(?:\.gz)?$}i', $url, $match)) { // update current github web archives to API calls with the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref; - } elseif (preg_match('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) { + } elseif (Preg::isMatch('{^https?://api\.github\.com/repos/([^/]+)/([^/]+)/(zip|tar)ball(?:/.+)?$}i', $url, $match)) { // update api archives to the proper reference $url = 'https://api.github.com/repos/' . $match[1] . '/'. $match[2] . '/' . $match[3] . 'ball/' . $ref; } } elseif ($host === 'bitbucket.org' || $host === 'www.bitbucket.org') { - if (preg_match('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) { + if (Preg::isMatch('{^https?://(?:www\.)?bitbucket\.org/([^/]+)/([^/]+)/get/(.+)\.(zip|tar\.gz|tar\.bz2)$}i', $url, $match)) { // update Bitbucket archives to the proper reference $url = 'https://bitbucket.org/' . $match[1] . '/'. $match[2] . '/get/' . $ref . '.' . $match[4]; } } elseif ($host === 'gitlab.com' || $host === 'www.gitlab.com') { - if (preg_match('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) { + if (Preg::isMatch('{^https?://(?:www\.)?gitlab\.com/api/v[34]/projects/([^/]+)/repository/archive\.(zip|tar\.gz|tar\.bz2|tar)\?sha=.+$}i', $url, $match)) { // update Gitlab archives to the proper reference $url = 'https://gitlab.com/api/v4/projects/' . $match[1] . '/repository/archive.' . $match[2] . '?sha=' . $ref; } } elseif (in_array($host, $config->get('github-domains'), true)) { - $url = preg_replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url); + $url = Preg::replace('{(/repos/[^/]+/[^/]+/(zip|tar)ball)(?:/.+)?$}i', '$1/'.$ref, $url); } elseif (in_array($host, $config->get('gitlab-domains'), true)) { - $url = preg_replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url); + $url = Preg::replace('{(/api/v[34]/projects/[^/]+/repository/archive\.(?:zip|tar\.gz|tar\.bz2|tar)\?sha=).+$}i', '${1}'.$ref, $url); } return $url; @@ -111,11 +112,11 @@ class Url { // GitHub repository rename result in redirect locations containing the access_token as GET parameter // e.g. https://api.github.com/repositories/9999999999?access_token=github_token - $url = preg_replace('{([&?]access_token=)[^&]+}', '$1***', $url); + $url = Preg::replace('{([&?]access_token=)[^&]+}', '$1***', $url); - $url = preg_replace_callback('{^(?P[a-z0-9]+://)?(?P[^:/\s@]+):(?P[^@\s/]+)@}i', function ($m) { + $url = Preg::replaceCallback('{^(?P[a-z0-9]+://)?(?P[^:/\s@]+):(?P[^@\s/]+)@}i', function ($m) { // if the username looks like a long (12char+) hex string, or a modern github token (e.g. ghp_xxx) we obfuscate that - if (preg_match('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { + if (Preg::isMatch('{^([a-f0-9]{12,}|gh[a-z]_[a-zA-Z0-9_]+)$}', $m['user'])) { return $m['prefix'].'***:***@'; } diff --git a/tests/Composer/Test/AllFunctionalTest.php b/tests/Composer/Test/AllFunctionalTest.php index 0f89f1f57..aefea3312 100644 --- a/tests/Composer/Test/AllFunctionalTest.php +++ b/tests/Composer/Test/AllFunctionalTest.php @@ -12,6 +12,7 @@ namespace Composer\Test; +use Composer\Pcre\Preg; use Composer\Util\Filesystem; use Symfony\Component\Finder\Finder; use Symfony\Component\Process\Process; @@ -147,10 +148,10 @@ class AllFunctionalTest extends TestCase $line++; } if ($expected[$i] === '%') { - preg_match('{%(.+?)%}', substr($expected, $i), $match); + Preg::isMatch('{%(.+?)%}', substr($expected, $i), $match); $regex = $match[1]; - if (preg_match('{'.$regex.'}', substr($output, $j), $match)) { + if (Preg::isMatch('{'.$regex.'}', substr($output, $j), $match)) { $i += strlen($regex) + 2; $j += strlen($match[0]); continue; @@ -207,7 +208,7 @@ class AllFunctionalTest extends TestCase */ private function parseTestFile($file) { - $tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file), -1, PREG_SPLIT_DELIM_CAPTURE); $data = array(); $section = null; diff --git a/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php b/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php index 58517af28..a3a911e46 100644 --- a/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolBuilderTest.php @@ -17,6 +17,7 @@ use Composer\DependencyResolver\Pool; use Composer\DependencyResolver\PoolOptimizer; use Composer\Config; use Composer\IO\NullIO; +use Composer\Pcre\Preg; use Composer\Repository\ArrayRepository; use Composer\Repository\FilterRepository; use Composer\Repository\LockArrayRepository; @@ -188,7 +189,7 @@ class PoolBuilderTest extends TestCase $fixturesDir = realpath(__DIR__.'/Fixtures/poolbuilder/'); $tests = array(); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (!preg_match('/\.test$/', $file)) { + if (!Preg::isMatch('/\.test$/', $file)) { continue; } @@ -224,7 +225,7 @@ class PoolBuilderTest extends TestCase */ protected function readTestFile(\SplFileInfo $file, $fixturesDir) { - $tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); $sectionInfo = array( 'TEST' => true, diff --git a/tests/Composer/Test/DependencyResolver/PoolOptimizerTest.php b/tests/Composer/Test/DependencyResolver/PoolOptimizerTest.php index 27358e62f..85d70d6f6 100644 --- a/tests/Composer/Test/DependencyResolver/PoolOptimizerTest.php +++ b/tests/Composer/Test/DependencyResolver/PoolOptimizerTest.php @@ -21,6 +21,7 @@ use Composer\Package\AliasPackage; use Composer\Package\BasePackage; use Composer\Package\Loader\ArrayLoader; use Composer\Package\Version\VersionParser; +use Composer\Pcre\Preg; use Composer\Repository\LockArrayRepository; use Composer\Test\TestCase; @@ -75,7 +76,7 @@ class PoolOptimizerTest extends TestCase $fixturesDir = realpath(__DIR__.'/Fixtures/pooloptimizer/'); $tests = array(); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (!preg_match('/\.test$/', $file)) { + if (!Preg::isMatch('/\.test$/', $file)) { continue; } @@ -102,7 +103,7 @@ class PoolOptimizerTest extends TestCase */ protected function readTestFile(\SplFileInfo $file, $fixturesDir) { - $tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); /** @var array $sectionInfo */ $sectionInfo = array( diff --git a/tests/Composer/Test/Downloader/GitDownloaderTest.php b/tests/Composer/Test/Downloader/GitDownloaderTest.php index 1999b423e..d3b046406 100644 --- a/tests/Composer/Test/Downloader/GitDownloaderTest.php +++ b/tests/Composer/Test/Downloader/GitDownloaderTest.php @@ -14,6 +14,7 @@ namespace Composer\Test\Downloader; use Composer\Downloader\GitDownloader; use Composer\Config; +use Composer\Pcre\Preg; use Composer\Test\TestCase; use Composer\Util\Filesystem; use Composer\Util\Platform; @@ -159,7 +160,7 @@ class GitDownloaderTest extends TestCase $config = new Config; $this->setupConfig($config); - $cachePath = $config->get('cache-vcs-dir').'/'.preg_replace('{[^a-z0-9.]}i', '-', 'https://example.com/composer/composer').'/'; + $cachePath = $config->get('cache-vcs-dir').'/'.Preg::replace('{[^a-z0-9.]}i', '-', 'https://example.com/composer/composer').'/'; $filesystem = new \Composer\Util\Filesystem; $filesystem->removeDirectory($cachePath); diff --git a/tests/Composer/Test/IO/ConsoleIOTest.php b/tests/Composer/Test/IO/ConsoleIOTest.php index b89932bd4..3d2d29fba 100644 --- a/tests/Composer/Test/IO/ConsoleIOTest.php +++ b/tests/Composer/Test/IO/ConsoleIOTest.php @@ -13,6 +13,7 @@ namespace Composer\Test\IO; use Composer\IO\ConsoleIO; +use Composer\Pcre\Preg; use Composer\Test\TestCase; use Symfony\Component\Console\Output\OutputInterface; @@ -83,8 +84,8 @@ class ConsoleIOTest extends TestCase ->method('write') ->with( $this->callback(function ($messages) { - $result = preg_match("[(.*)/(.*) First line]", $messages[0]) > 0; - $result = $result && preg_match("[(.*)/(.*) Second line]", $messages[1]) > 0; + $result = Preg::isMatch("[(.*)/(.*) First line]", $messages[0]); + $result = $result && Preg::isMatch("[(.*)/(.*) Second line]", $messages[1]); return $result; }), diff --git a/tests/Composer/Test/InstallerTest.php b/tests/Composer/Test/InstallerTest.php index 973ea2c7a..46d2f625f 100644 --- a/tests/Composer/Test/InstallerTest.php +++ b/tests/Composer/Test/InstallerTest.php @@ -15,6 +15,7 @@ namespace Composer\Test; use Composer\DependencyResolver\Request; use Composer\Filter\PlatformRequirementFilter\PlatformRequirementFilterFactory; use Composer\Installer; +use Composer\Pcre\Preg; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; @@ -444,7 +445,7 @@ class InstallerTest extends TestCase }); $application->add($update); - if (!preg_match('{^(install|update)\b}', $run)) { + if (!Preg::isMatch('{^(install|update)\b}', $run)) { throw new \UnexpectedValueException('The run command only supports install and update'); } @@ -489,8 +490,8 @@ class InstallerTest extends TestCase $this->assertSame(rtrim($expect), implode("\n", $installationManager->getTrace())); if ($expectOutput) { - $output = preg_replace('{^ - .*?\.ini$}m', '__inilist__', $output); - $output = preg_replace('{(__inilist__\r?\n)+}', "__inilist__\n", $output); + $output = Preg::replace('{^ - .*?\.ini$}m', '__inilist__', $output); + $output = Preg::replace('{(__inilist__\r?\n)+}', "__inilist__\n", $output); $this->assertStringMatchesFormat(rtrim($expectOutput), rtrim($output)); } @@ -516,7 +517,7 @@ class InstallerTest extends TestCase $tests = array(); foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (!preg_match('/\.test$/', $file)) { + if (!Preg::isMatch('/\.test$/', $file)) { continue; } @@ -541,7 +542,7 @@ class InstallerTest extends TestCase } // Change paths like file://foobar to file:///path/to/fixtures - if (preg_match('{^file://[^/]}', $repo['url'])) { + if (Preg::isMatch('{^file://[^/]}', $repo['url'])) { $repo['url'] = 'file://' . strtr($fixturesDir, '\\', '/') . '/' . substr($repo['url'], 7); } @@ -598,7 +599,7 @@ class InstallerTest extends TestCase */ protected function readTestFile(\SplFileInfo $file, $fixturesDir) { - $tokens = preg_split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); + $tokens = Preg::split('#(?:^|\n*)--([A-Z-]+)--\n#', file_get_contents($file->getRealPath()), -1, PREG_SPLIT_DELIM_CAPTURE); $sectionInfo = array( 'TEST' => true, diff --git a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php index b98e59589..6aad38c2c 100644 --- a/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php +++ b/tests/Composer/Test/Package/Archiver/ArchivableFilesFinderTest.php @@ -13,6 +13,7 @@ namespace Composer\Test\Package\Archiver; use Composer\Package\Archiver\ArchivableFilesFinder; +use Composer\Pcre\Preg; use Composer\Test\TestCase; use Composer\Util\Filesystem; use Symfony\Component\Process\Process; @@ -263,7 +264,7 @@ class ArchivableFilesFinderTest extends TestCase $files = array(); foreach ($this->finder as $file) { if (!$file->isDir()) { - $files[] = preg_replace('#^'.preg_quote($this->sources, '#').'#', '', $this->fs->normalizePath($file->getRealPath())); + $files[] = Preg::replace('#^'.preg_quote($this->sources, '#').'#', '', $this->fs->normalizePath($file->getRealPath())); } } @@ -292,7 +293,7 @@ class ArchivableFilesFinderTest extends TestCase $files = array(); foreach ($iterator as $file) { - $files[] = preg_replace('#^phar://'.preg_quote($this->sources, '#').'/archive\.zip/archive#', '', $this->fs->normalizePath($file)); + $files[] = Preg::replace('#^phar://'.preg_quote($this->sources, '#').'/archive\.zip/archive#', '', $this->fs->normalizePath($file)); } unset($archive, $iterator, $file); diff --git a/tests/Composer/Test/TestCase.php b/tests/Composer/Test/TestCase.php index 08bee500c..5255b5066 100644 --- a/tests/Composer/Test/TestCase.php +++ b/tests/Composer/Test/TestCase.php @@ -12,6 +12,7 @@ namespace Composer\Test; +use Composer\Pcre\Preg; use Composer\Semver\VersionParser; use Composer\Package\RootPackageInterface; use Composer\Package\PackageInterface; @@ -215,7 +216,7 @@ abstract class TestCase extends PolyfillTestCase protected function getCmd($cmd) { if (Platform::isWindows()) { - $cmd = preg_replace_callback("/('[^']*')/", function ($m) { + $cmd = Preg::replaceCallback("/('[^']*')/", function ($m) { // Double-quotes are used only when needed $char = (strpbrk($m[1], " \t^&|<>()") !== false || $m[1] === "''") ? '"' : '';