mirror of
https://github.com/FreshRSS/FreshRSS.git
synced 2026-10-12 09:23:24 -04:00
108 lines
2.0 KiB
PHP
108 lines
2.0 KiB
PHP
<?php
|
|
|
|
namespace Gt\CssXPath;
|
|
|
|
class SelectorListSplitter {
|
|
/** @return array<int, string> */
|
|
public function split(string $selectorList):array {
|
|
$selectorList = trim($selectorList);
|
|
if($selectorList === "") {
|
|
return [];
|
|
}
|
|
|
|
$parts = [];
|
|
$current = "";
|
|
$quote = null;
|
|
$bracketDepth = 0;
|
|
$parenDepth = 0;
|
|
$length = strlen($selectorList);
|
|
|
|
for($i = 0; $i < $length; $i++) {
|
|
$char = $selectorList[$i];
|
|
|
|
if($this->handleQuotedState($char, $current, $quote)) {
|
|
continue;
|
|
}
|
|
|
|
if($this->openQuoteIfNeeded($char, $current, $quote)) {
|
|
continue;
|
|
}
|
|
|
|
$this->trackDepth($char, $bracketDepth, $parenDepth);
|
|
if($this->isTopLevelComma($char, $bracketDepth, $parenDepth)) {
|
|
$this->appendCurrentPart($parts, $current);
|
|
$current = "";
|
|
continue;
|
|
}
|
|
|
|
$current .= $char;
|
|
}
|
|
|
|
$this->appendCurrentPart($parts, $current);
|
|
return $parts;
|
|
}
|
|
|
|
private function handleQuotedState(
|
|
string $char,
|
|
string &$current,
|
|
?string &$quote
|
|
):bool {
|
|
if($quote === null) {
|
|
return false;
|
|
}
|
|
|
|
$current .= $char;
|
|
if($char === $quote) {
|
|
$quote = null;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private function openQuoteIfNeeded(
|
|
string $char,
|
|
string &$current,
|
|
?string &$quote
|
|
):bool {
|
|
if($char !== "'" && $char !== '"') {
|
|
return false;
|
|
}
|
|
|
|
$quote = $char;
|
|
$current .= $char;
|
|
return true;
|
|
}
|
|
|
|
private function trackDepth(
|
|
string $char,
|
|
int &$bracketDepth,
|
|
int &$parenDepth
|
|
):void {
|
|
match($char) {
|
|
"[" => $bracketDepth++,
|
|
"]" => $bracketDepth = max(0, $bracketDepth - 1),
|
|
"(" => $parenDepth++,
|
|
")" => $parenDepth = max(0, $parenDepth - 1),
|
|
default => null,
|
|
};
|
|
}
|
|
|
|
private function isTopLevelComma(
|
|
string $char,
|
|
int $bracketDepth,
|
|
int $parenDepth
|
|
):bool {
|
|
return $char === ","
|
|
&& $bracketDepth === 0
|
|
&& $parenDepth === 0;
|
|
}
|
|
|
|
/** @param array<int, string> $parts */
|
|
private function appendCurrentPart(array &$parts, string $current):void {
|
|
$trimmed = trim($current);
|
|
if($trimmed !== "") {
|
|
$parts[] = $trimmed;
|
|
}
|
|
}
|
|
}
|