aboutsummaryrefslogtreecommitdiff
path: root/lib/phpgt/cssxpath/src/Translator.php
diff options
context:
space:
mode:
Diffstat (limited to 'lib/phpgt/cssxpath/src/Translator.php')
-rw-r--r--lib/phpgt/cssxpath/src/Translator.php91
1 files changed, 76 insertions, 15 deletions
diff --git a/lib/phpgt/cssxpath/src/Translator.php b/lib/phpgt/cssxpath/src/Translator.php
index 01ed98bc6..7bb11265c 100644
--- a/lib/phpgt/cssxpath/src/Translator.php
+++ b/lib/phpgt/cssxpath/src/Translator.php
@@ -12,7 +12,7 @@ class Translator {
. '|(#(?P<id>[\w-]*))'
. '|(\.(?P<class>[\w-]*))'
. '|(?P<sibling>\s*\+\s*)'
- . "|(\[(?P<attribute>[\w-]*)((?P<attribute_equals>[=~$*]+)(?P<attribute_value>(.+\[\]'?)|[^\]]+))*\])+"
+ . "|(\[(?P<attribute>[\w-]*)((?P<attribute_equals>[=~$|^*]+)(?P<attribute_value>(.+\[\]'?)|[^\]]+))*\])+"
. '|(?P<descendant>\s+)'
. '/';
@@ -20,17 +20,14 @@ class Translator {
const EQUALS_CONTAINS_WORD = "~=";
const EQUALS_ENDS_WITH = "$=";
const EQUALS_CONTAINS = "*=";
- const EQUALS_STARTS_WITH_OR_STARTS_WITH_HYPHENATED = "|=";
+ const EQUALS_OR_STARTS_WITH_HYPHENATED = "|=";
const EQUALS_STARTS_WITH = "^=";
- /** @var string */
- protected $cssSelector;
- /** @var string */
- protected $prefix;
-
- public function __construct(string $cssSelector, string $prefix = ".//") {
- $this->cssSelector = $cssSelector;
- $this->prefix = $prefix;
+ public function __construct(
+ protected string $cssSelector,
+ protected string $prefix = ".//",
+ protected bool $htmlMode = true
+ ) {
}
public function __toString():string {
@@ -70,7 +67,11 @@ class Translator {
switch ($currentThreadItem["type"]) {
case "star":
case "element":
- $xpath []= $currentThreadItem['content'];
+ if($this->htmlMode) {
+ $xpath []= strtolower($currentThreadItem['content']);
+ } else {
+ $xpath []= $currentThreadItem['content'];
+ }
$hasElement = true;
break;
@@ -135,6 +136,30 @@ class Translator {
);
}
break;
+
+ case "last-child":
+ $prev = count($xpath) - 1;
+ $xpath[$prev] = '*[last()]/self::' . $xpath[$prev];
+ break;
+
+ case 'first-of-type':
+ $prev = count($xpath) - 1;
+ $previous = $xpath[$prev];
+
+ if(substr($previous, -1, 1) === "]") {
+ array_push(
+ $xpath,
+ "[1]"
+ );
+ }
+ else {
+ array_push(
+ $xpath,
+ "[1]"
+ );
+ }
+ break;
+
case "nth-of-type":
if (empty($specifier)) {
continue 3;
@@ -156,6 +181,25 @@ class Translator {
);
}
break;
+
+ case "last-of-type":
+ $prev = count($xpath) - 1;
+ $previous = $xpath[$prev];
+
+ if(substr($previous, -1, 1) === "]") {
+ array_push(
+ $xpath,
+ "[last()]"
+ );
+ }
+ else {
+ array_push(
+ $xpath,
+ "[last()]"
+ );
+ }
+ break;
+
}
break;
@@ -197,6 +241,10 @@ class Translator {
$hasElement = true;
}
+ if($this->htmlMode) {
+ $currentThreadItem['content'] = strtolower($currentThreadItem['content']);
+ }
+
/** @var null|array<int, array<string, string>> $detail */
$detail = $currentThreadItem["detail"] ?? null;
$detailType = $detail[0] ?? null;
@@ -244,11 +292,24 @@ class Translator {
);
break;
- case self::EQUALS_STARTS_WITH_OR_STARTS_WITH_HYPHENATED:
- throw new NotYetImplementedException();
+ case self::EQUALS_OR_STARTS_WITH_HYPHENATED:
+ array_push(
+ $xpath,
+ "["
+ . "@{$currentThreadItem['content']}=\"{$valueString}\" or "
+ . "starts-with(@{$currentThreadItem['content']}, \"{$valueString}-\")"
+ . "]"
+ );
+ break;
case self::EQUALS_STARTS_WITH:
- throw new NotYetImplementedException();
+ array_push(
+ $xpath,
+ "[starts-with("
+ . "@{$currentThreadItem['content']}, \"{$valueString}\""
+ . ")]"
+ );
+ break;
case self::EQUALS_ENDS_WITH:
array_push(
@@ -279,7 +340,7 @@ class Translator {
protected function preg_match_collated(
string $regex,
string $string,
- callable $transform = null
+ ?callable $transform = null
):array {
preg_match_all(
$regex,