function JsonManipulator::removeSubNode
3 calls to JsonManipulator::removeSubNode()
- JsonManipulator::removeConfigSetting in vendor/
composer/ composer/ src/ Composer/ Json/ JsonManipulator.php - JsonManipulator::removeProperty in vendor/
composer/ composer/ src/ Composer/ Json/ JsonManipulator.php - JsonManipulator::removeRepository in vendor/
composer/ composer/ src/ Composer/ Json/ JsonManipulator.php
File
-
vendor/
composer/ composer/ src/ Composer/ Json/ JsonManipulator.php, line 340
Class
- JsonManipulator
- @author Jordi Boggiano <j.boggiano@seld.be>
Namespace
Composer\JsonCode
public function removeSubNode(string $mainNode, string $name) : bool {
$decoded = JsonFile::parseJson($this->contents);
// no node or empty node
if (empty($decoded[$mainNode])) {
return true;
}
// no node content match-able
$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 (!Preg::isMatch($nodeRegex, $this->contents, $match)) {
return false;
}
} catch (\RuntimeException $e) {
if ($e->getCode() === PREG_BACKTRACK_LIMIT_ERROR) {
return false;
}
throw $e;
}
assert(is_string($match['start']));
assert(is_string($match['content']));
assert(is_string($match['end']));
$children = $match['content'];
// invalid match due to un-regexable content, abort
if (!@json_decode($children, true)) {
return false;
}
$subName = null;
if (in_array($mainNode, [
'config',
'extra',
'scripts',
]) && false !== strpos($name, '.')) {
[
$name,
$subName,
] = explode('.', $name, 2);
}
// no node to remove
if (!isset($decoded[$mainNode][$name]) || $subName && !isset($decoded[$mainNode][$name][$subName])) {
return true;
}
// try and find a match for the subkey
$keyRegex = str_replace('/', '\\\\?/', preg_quote($name));
if (Preg::isMatch('{"' . $keyRegex . '"\\s*:}i', $children)) {
// find best match for the value of "name"
if (Preg::isMatchAll('{' . self::DEFINES . '"' . $keyRegex . '"\\s*:\\s*(?:(?&json))}x', $children, $matches)) {
$bestMatch = '';
foreach ($matches[0] as $match) {
assert(is_string($match));
if (strlen($bestMatch) < strlen($match)) {
$bestMatch = $match;
}
}
$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);
if (1 !== $count) {
return false;
}
}
}
}
else {
$childrenClean = $children;
}
if (!isset($childrenClean)) {
throw new \InvalidArgumentException("JsonManipulator: \$childrenClean is not defined. Please report at https://github.com/composer/composer/issues/new.");
}
// no child data left, $name was the only key in
unset($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::replaceCallback($nodeRegex, static function ($matches) use ($indent, $newline) : string {
return $matches['start'] . '{' . $newline . $indent . '}' . $matches['end'];
}, $this->contents);
// we have a subname, so we restore the rest of $name
if ($subName !== null) {
$curVal = json_decode($children, true);
unset($curVal[$name][$subName]);
if ($curVal[$name] === []) {
$curVal[$name] = new \ArrayObject();
}
$this->addSubNode($mainNode, $name, $curVal[$name]);
}
return true;
}
$this->contents = Preg::replaceCallback($nodeRegex, function ($matches) use ($name, $subName, $childrenClean) : string {
assert(is_string($matches['content']));
if ($subName !== null) {
$curVal = json_decode($matches['content'], true);
unset($curVal[$name][$subName]);
if ($curVal[$name] === []) {
$curVal[$name] = new \ArrayObject();
}
$childrenClean = $this->format($curVal, 0, true);
}
return $matches['start'] . $childrenClean . $matches['end'];
}, $this->contents);
return true;
}