Add composer/pcre dependency and use it everywhere instead of preg_*

main
Jordi Boggiano 2 years ago
parent 2d92e2119a
commit 24ce1eddbd
No known key found for this signature in database
GPG Key ID: 7BBD42C429EC80BC

@ -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",

73
composer.lock generated

@ -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",

@ -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('\\<dirsep\\>', '[\\\\/]', preg_quote(str_replace(array('/', '\\'), '<dirsep>', $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])) {

@ -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>Warning: Ambiguous class resolution, "'.$class.'"'.
' was found in both "'.$map[$class].'" and "'.$filePath.'", the first will be used.</warning>'
@ -196,7 +197,7 @@ class ClassMapGenerator
if (empty($validClasses)) {
foreach ($rejectedClasses as $class) {
if ($io) {
$io->writeError("<warning>Class $class located in ".preg_replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping.</warning>");
$io->writeError("<warning>Class $class located in ".Preg::replace('{^'.preg_quote(getcwd()).'}', '.', $filePath, 1)." does not comply with $namespaceType autoloading standard. Skipping.</warning>");
}
}
@ -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(?<![\$:>])(?P<type>class|interface'.$extraTypes.') \s++ (?P<name>[a-zA-Z_\x7f-\xff:][a-zA-Z0-9_\x7f-\xff:\-]*+)
| \b(?<![\$:>])(?P<ns>namespace) (?P<nsname>\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*+ [\{;]

@ -12,6 +12,8 @@
namespace Composer\Autoload;
use Composer\Pcre\Preg;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
* @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);
}
}

@ -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('<warning>Failed to write into cache: '.$e->getMessage().'</warning>', 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);
}

@ -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;

@ -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);

@ -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(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
if (Preg::isMatch('{Configure Command(?: *</td><td class="v">| *=> *)(.*?)(?:</td>|$)}m', $phpinfo, $match)) {
$configure = $match[1];
if (false !== strpos($configure, '--enable-sigchild')) {

@ -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;

@ -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('<info>Changed current directory to '.$home.'</info>');
// 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);

@ -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<name>[- .,\p{L}\p{N}\p{Mn}\'"()]+) <(?P<email>.+?)>$/u', $author, $match)) {
if (Preg::isMatch('/^(?P<name>[- .,\p{L}\p{N}\p{Mn}\'"()]+) <(?P<email>.+?)>$/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<name>[\S/]+)(?:\s+(?P<version>\S+))?\s*$}', $selection, $packageMatches)) {
if (Preg::isMatch('{^\s*(?P<name>[\S/]+)(?:\s+(?P<version>\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;
}
}

@ -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();

@ -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('<warning>' . $matchedPackage . ' could not be found in ' . $type . ' but it is present in ' . $altType . '</warning>');
if ($io->isInteractive()) {

@ -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>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.</warning>');
}
if (preg_match('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
if (Preg::isMatch('{^[0-9a-f]{40}$}', $updateVersion) && $updateVersion !== $latestVersion) {
$io->writeError('<error>You can not update to a specific SHA-1 as those phars are not available for download</error>');
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 <info>%s</info> (%s channel).", $updateVersion, $channelString));
$remoteFilename = $baseUrl . ($updatingToTag ? "/download/{$updateVersion}/composer.phar" : '/composer.phar');
@ -351,7 +352,7 @@ TAGSPUBKEY
$io->write('Open <info>https://composer.github.io/pubkeys.html</info> 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";

@ -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;
}

@ -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;
}

@ -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";
}

@ -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;
}

@ -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;
}

@ -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]);

@ -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);
}

@ -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;
}
}

@ -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<package>\S+) (?P<version>\S+) (?P<type>requires|conflicts)}', $message, $m)) {
$template = preg_replace('{^\S+ \S+ }', '%s%s ', $message);
if (in_array($rule->getReason(), $deduplicatableRuleTypes, true) && Preg::isMatch('{^(?P<package>\S+) (?P<version>\S+) (?P<type>requires|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) {

@ -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';
}

@ -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;

@ -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<url>\S+)}m', $output, $originMatch)
&& preg_match('{^composer\s+(?P<url>\S+)}m', $output, $composerMatch)
&& Preg::isMatch('{^origin\s+(?P<url>\S+)}m', $output, $originMatch)
&& Preg::isMatch('{^composer\s+(?P<url>\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(' <error>'.$package->getPrettyName().' has modified files:</error>');
$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);
}

@ -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(' <error>'.$package->getPrettyName().' has modified file%s:</error>', $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 = '#<url>(.*)</url>#';
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));

@ -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);
}
}

@ -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);
}
}

@ -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');

@ -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])) {

@ -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);

@ -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;

@ -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)

@ -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;

@ -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) {

@ -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<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
'(?P<property>'.preg_quote(JsonFile::encode($type)).'\s*:\s*)(?P<value>(?&json))(?P<end>.*)}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<package>'.$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<separator>\s*:\s*)(?&string)}ix', function ($m) use ($existingPackage, $constraint) {
$links = Preg::replaceCallback('{'.self::$DEFINES.'"'.$packageRegex.'"(?P<separator>\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<content>(?&object))(?P<end>.*)}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<start>"'.preg_quote($name).'"\s*:\s*)(?P<content>(?&json))(?P<end>,?)}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<leadingspace>\s*?) (?P<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $children, $match);
Preg::match('#^{ (?P<leadingspace>\s*?) (?P<content>\S+.*?)? (?P<trailingspace>\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<start> \s* \{ \s* (?: (?&string) \s* : (?&json) \s* , \s* )*?'.
preg_quote(JsonFile::encode($mainNode)).'\s*:\s*)(?P<content>(?&object))(?P<end>.*)}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<content>\S+.*?)? (?P<trailingspace>\s*) }$#sx', $childrenClean, $match);
Preg::match('#^{ \s*? (?P<content>\S+.*?)? (?P<trailingspace>\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<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
'(?P<key>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))(?P<end>.*)}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<start>\s*\{\s*(?:(?&string)\s*:\s*(?&json)\s*,\s*)*?)'.
'(?P<removal>'.preg_quote(JsonFile::encode($key)).'\s*:\s*(?&json))\s*,?\s*(?P<end>.*)}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<string> $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;
}
}

@ -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())

@ -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());

@ -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
}
}

@ -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]);

@ -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 <ever.zet@gmail.com>
@ -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);

@ -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('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
$andSplit = Preg::split('{(?<!^|as|[=>< ,]) *(?<!-)[, ](?!-) *(?!,|as|$)}', $orConstraint);
foreach ($andSplit as $andConstraint) {
$constraints[] = $andConstraint;
}
@ -243,7 +244,7 @@ class RootPackageLoader extends ArrayLoader
// parse explicit stability flags to the most unstable
$match = false;
foreach ($constraints as $constraint) {
if (preg_match('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
if (Preg::isMatch('{^[^@]*?@('.implode('|', array_keys($stabilities)).')$}i', $constraint, $match)) {
$name = strtolower($reqName);
$stability = $stabilities[VersionParser::normalizeStability($match[1])];
@ -262,8 +263,8 @@ class RootPackageLoader extends ArrayLoader
foreach ($constraints as $constraint) {
// infer flags for requirements that have an explicit -dev or -beta version specified but only
// for those that are more unstable than the minimumStability or existing flags
$reqVersion = preg_replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
if (preg_match('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
$reqVersion = Preg::replace('{^([^,\s@]+) as .+$}', '$1', $constraint);
if (Preg::isMatch('{^[^,\s@]+$}', $reqVersion) && 'stable' !== ($stabilityName = VersionParser::parseStability($reqVersion))) {
$name = strtolower($reqName);
$stability = $stabilities[$stabilityName];
if ((isset($stabilityFlags[$name]) && $stabilityFlags[$name] > $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];
}

@ -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;

@ -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;

@ -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);
}

@ -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 = '#<url>.*/(' . $trunkPath . '|(' . $branchesPath . '|' . $tagsPath . ')/(.*))</url>#';
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]);

@ -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++;
}

@ -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]);

@ -12,6 +12,8 @@
namespace Composer\Platform;
use Composer\Pcre\Preg;
/**
* @author Lars Strojny <lars@strojny.net>
*/
@ -26,7 +28,7 @@ class Version
{
$isFips = false;
if (!preg_match('/^(?<version>[0-9.]+)(?<patch>[a-z]{0,2})?(?<suffix>(?:-?(?:dev|pre|alpha|beta|rc|fips)[\d]*)*)?(?<garbage>-\w+)?$/', $opensslVersion, $matches)) {
if (!Preg::isMatch('/^(?<version>[0-9.]+)(?<patch>[a-z]{0,2})?(?<suffix>(?:-?(?:dev|pre|alpha|beta|rc|fips)[\d]*)*)?(?<garbage>-\w+)?$/', $opensslVersion, $matches)) {
return null;
}
@ -43,7 +45,7 @@ class Version
*/
public static function parseLibjpeg($libjpegVersion)
{
if (!preg_match('/^(?<major>\d+)(?<minor>[a-z]*)$/', $libjpegVersion, $matches)) {
if (!Preg::isMatch('/^(?<major>\d+)(?<minor>[a-z]*)$/', $libjpegVersion, $matches)) {
return null;
}
@ -56,7 +58,7 @@ class Version
*/
public static function parseZoneinfoVersion($zoneinfoVersion)
{
if (!preg_match('/^(?<year>\d{4})(?<revision>[a-z]*)$/', $zoneinfoVersion, $matches)) {
if (!Preg::isMatch('/^(?<year>\d{4})(?<revision>[a-z]*)$/', $zoneinfoVersion, $matches)) {
return null;
}

@ -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('<warning>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.</warning>');
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++;

@ -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;
}

@ -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;

@ -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('{^(?P<proto>https?)://packagist\.org/?$}i', $this->url, $match)) {
if (Preg::isMatch('{^(?P<proto>https?)://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;
}
}

@ -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);
}
}

@ -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());
}
}

@ -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

@ -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 => (?<version>.+)$/im', $info, $librabbitmqMatches)) {
if (Preg::isMatch('/^librabbitmq version => (?<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 => (?<version>.+)$/im', $info, $protocolMatches)) {
if (Preg::isMatch('/^AMQP protocol version => (?<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 => (?<version>.*),/im', $info, $matches)) {
if (Preg::isMatch('/^BZip2 Version => (?<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 => (?<library>[^/]+)/(?<version>.+)$}im', $info, $sslMatches)) {
if (Preg::isMatch('{^SSL Version => (?<library>[^/]+)/(?<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 => (?<library>[^/]+)/(?<version>.+?)(?:/.*)?$}im', $info, $sshMatches)) {
if (Preg::isMatch('{^libSSH Version => (?<library>[^/]+)/(?<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 => (?<version>.+)$}im', $info, $zlibMatches)) {
if (Preg::isMatch('{^ZLib Version => (?<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 => (?<version>.+)$/im', $info, $timelibMatches)) {
if (Preg::isMatch('/^timelib version => (?<version>.+)$/im', $info, $timelibMatches)) {
$this->addLibrary($name.'-timelib', $timelibMatches['version'], 'date timelib version');
}
// Timezone Database => internal
if (preg_match('/^Timezone Database => (?<source>internal|external)$/im', $info, $zoneinfoSourceMatches)) {
if (Preg::isMatch('/^Timezone Database => (?<source>internal|external)$/im', $info, $zoneinfoSourceMatches)) {
$external = $zoneinfoSourceMatches['source'] === 'external';
if (preg_match('/^"Olson" Timezone Database Version => (?<version>.+?)(\.system)?$/im', $info, $zoneinfoMatches)) {
if (Preg::isMatch('/^"Olson" Timezone Database Version => (?<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 => (?<version>.+)$/im', $info, $magicMatches)) {
if (Preg::isMatch('/^libmagic => (?<version>.+)$/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 => (?<version>.+?)(?: compatible)?$/im', $info, $libjpegMatches)) {
if (Preg::isMatch('/^libJPEG Version => (?<version>.+?)(?: compatible)?$/im', $info, $libjpegMatches)) {
$this->addLibrary($name.'-libjpeg', Version::parseLibjpeg($libjpegMatches['version']), 'libjpeg version for gd');
}
if (preg_match('/^libPNG Version => (?<version>.+)$/im', $info, $libpngMatches)) {
if (Preg::isMatch('/^libPNG Version => (?<version>.+)$/im', $info, $libpngMatches)) {
$this->addLibrary($name.'-libpng', $libpngMatches['version'], 'libpng version for gd');
}
if (preg_match('/^FreeType Version => (?<version>.+)$/im', $info, $freetypeMatches)) {
if (Preg::isMatch('/^FreeType Version => (?<version>.+)$/im', $info, $freetypeMatches)) {
$this->addLibrary($name.'-freetype', $freetypeMatches['version'], 'freetype version for gd');
}
if (preg_match('/^libXpm Version => (?<versionId>\d+)$/im', $info, $libxpmMatches)) {
if (Preg::isMatch('/^libXpm Version => (?<versionId>\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 => (?<version>.+)$/im', $info, $matches)) {
} elseif (Preg::isMatch('/^ICU version => (?<version>.+)$/im', $info, $matches)) {
$this->addLibrary('icu', $matches['version'], $description);
}
// ICU TZData version => 2019c
if (preg_match('/^ICU TZData version => (?<version>.*)$/im', $info, $zoneinfoMatches)) {
if (Preg::isMatch('/^ICU TZData version => (?<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 (?<version>[\d.]+)(?:-(?<patch>\d+))?/', $imageMagickVersion['versionString'], $matches);
Preg::match('/^ImageMagick (?<version>[\d.]+)(?:-(?<patch>\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 => (?<versionId>\d+)$/im', $info, $matches) && preg_match('/^Vendor Name => (?<vendor>.+)$/im', $info, $vendorMatches)) {
if (Preg::isMatch('/^Vendor Version => (?<versionId>\d+)$/im', $info, $matches) && Preg::isMatch('/^Vendor Name => (?<vendor>.+)$/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 => (?<version>.+)$/im', $info, $libmbflMatches)) {
if (Preg::isMatch('/^libmbfl version => (?<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 => (?<version>.+)$/im', $info, $onigurumaMatches)) {
} elseif (Preg::isMatch('/^(?:oniguruma|Multibyte regex \(oniguruma\)) version => (?<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 => (?<version>.+)$/im', $info, $matches)) {
if (Preg::isMatch('/^libmemcached version => (?<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*(?<version>\S+)}i', $this->runtime->getConstant('OPENSSL_VERSION_TEXT'), $matches)) {
if (Preg::isMatch('{^(?:OpenSSL|LibreSSL)?\s*(?<version>\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 => (?<version>.+)$/im', $info, $pcreUnicodeMatches)) {
if (Preg::isMatch('/^PCRE Unicode Version => (?<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 (?<version>.+?) /mi', $info, $matches)) {
if (Preg::isMatch('/^(?:Client API version|Version) => mysqlnd (?<version>.+?) /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 => (?<version>.+)$/im', $info, $libmongocMatches)) {
if (Preg::isMatch('/^libmongoc bundled version => (?<version>.+)$/im', $info, $libmongocMatches)) {
$this->addLibrary($name.'-libmongoc', $libmongocMatches['version'], 'libmongoc version of mongodb');
}
if (preg_match('/^libbson bundled version => (?<version>.+)$/im', $info, $libbsonMatches)) {
if (Preg::isMatch('/^libbson bundled version => (?<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 => (?<version>.*)$/im', $info, $matches)) {
if (Preg::isMatch('/^PostgreSQL\(libpq\) Version => (?<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 => (?<version>.+)$/im', $info, $matches)) {
if (Preg::isMatch('/^SQLite Library => (?<version>.+)$/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 => (?<version>.+)$/im', $info, $matches)) {
if (Preg::isMatch('/^libssh2 version => (?<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 => (?<version>.+)$/im', $info, $matches)) {
if (Preg::isMatch('/^libxslt compiled against libxml Version => (?<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 => (?<version>.+)$/im', $info, $matches)) {
if (Preg::isMatch('/^LibYAML Version => (?<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 => (?<version>.+)$/im', $this->runtime->getExtensionInfo($name), $matches)) {
} elseif (Preg::isMatch('/^Linked Version => (?<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);
}
/**

@ -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';
}

@ -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;
}

@ -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;
}

@ -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;
}

@ -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];
}
}

@ -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;
}
}

@ -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;
}

@ -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));
}

@ -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;
}

@ -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);
}
/**

@ -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('<warning>Skipped tag '.$tag.', invalid tag name, tags can not use dev prefixes or suffixes</warning>');
} else {
$this->io->writeError('<warning>Skipped tag '.$tag.', tag ('.$parsedTag.') does not match version ('.$data['version_normalized'].') in composer.json</warning>');
@ -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);

@ -12,6 +12,8 @@
namespace Composer\SelfUpdate;
use Composer\Pcre\Preg;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
@ -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),

@ -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 <j.boggiano@seld.be>
@ -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';
}

@ -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(

@ -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

@ -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) {

@ -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);
}
/**

@ -14,6 +14,7 @@ namespace Composer\Util;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
@ -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];
}
}

@ -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 <j.boggiano@seld.be>
@ -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;
}
}

@ -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 <roshan.gautam@hotmail.com>
@ -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;

@ -14,6 +14,7 @@ namespace Composer\Util;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
* @author Jonas Renaudot <jonas.renaudot@gmail.com>
@ -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];
}
}

@ -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';
}

@ -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];
}
}

@ -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;
}

@ -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];
}

@ -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];
}
}

@ -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<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', function ($matches) {
return Preg::replaceCallback('#^(\$|(?P<percent>%))(?P<var>\w++)(?(percent)%)(?P<path>.*)#', 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'];

@ -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<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
$safeCommand = Preg::replaceCallback('{://(?P<user>[^:/\s]+):(?P<password>[^@\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<user>[^:/\s]+):(?P<password>[^@\s/]+)@}i', function ($m) {
if (preg_match('{^[a-f0-9]{12,}$}', $m['user'])) {
$safeCommand = Preg::replaceCallback('{://(?P<user>[^:/\s]+):(?P<password>[^@\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;

@ -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);
}
}

@ -14,6 +14,7 @@ namespace Composer\Util;
use Composer\Config;
use Composer\IO\IOInterface;
use Composer\Pcre\Preg;
/**
* @author Till Klampaeckel <till@php.net>
@ -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];
}
}

@ -13,6 +13,7 @@
namespace Composer\Util;
use Composer\CaBundle\CaBundle;
use Composer\Pcre\Preg;
/**
* @author Chris Smith <chris@cs278.org>
@ -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);
};
}

@ -13,6 +13,7 @@
namespace Composer\Util;
use Composer\Config;
use Composer\Pcre\Preg;
/**
* @author Jordi Boggiano <j.boggiano@seld.be>
@ -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<prefix>[a-z0-9]+://)?(?P<user>[^:/\s@]+):(?P<password>[^@\s/]+)@}i', function ($m) {
$url = Preg::replaceCallback('{^(?P<prefix>[a-z0-9]+://)?(?P<user>[^:/\s@]+):(?P<password>[^@\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'].'***:***@';
}

@ -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;

@ -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,

@ -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<string, bool> $sectionInfo */
$sectionInfo = array(

@ -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);

@ -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;
}),

@ -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,

@ -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);

@ -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] === "''") ? '"' : '';

Loading…
Cancel
Save