-
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathListElementCollection.php
103 lines (84 loc) · 2.44 KB
/
ListElementCollection.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
<?php
namespace Gt\DomTemplate;
use Gt\Dom\Document;
use Gt\Dom\Element;
class ListElementCollection {
/** @var array<string, ListElement> */
private array $elementKVP;
public function __construct(
Document $document
) {
$this->elementKVP = [];
$this->extractTemplates($document);
}
public function get(
Element|Document $context,
?string $templateName = null
):ListElement {
if($context instanceof Document) {
$context = $context->documentElement;
}
if($templateName) {
if(!isset($this->elementKVP[$templateName])) {
throw new ListElementNotFoundInContextException("List element with name \"$templateName\" can not be found within the context $context->tagName element.");
}
return $this->elementKVP[$templateName];
}
return $this->findMatch($context);
}
private function extractTemplates(Document $document):void {
$dataTemplateArray = [];
/** @var Element $element */
foreach($document->querySelectorAll("[data-list],[data-template]") as $element) {
$templateElement = new ListElement($element);
$nodePath = (string)(new NodePathCalculator($element));
$key = $templateElement->getListItemName() ?? $nodePath;
$dataTemplateArray[$key] = $templateElement;
}
uksort($dataTemplateArray,
fn(string $a, string $b):int => (
(substr_count($a, "/") > substr_count($b, "/"))
? -1
: 1
)
);
foreach($dataTemplateArray as $template) {
$template->removeOriginalElement();
}
$this->elementKVP = array_reverse($dataTemplateArray, true);
}
private function findMatch(Element $context):ListElement {
$contextPath = (string)(new NodePathCalculator($context));
/** @noinspection RegExpRedundantEscape */
$contextPath = preg_replace(
"/(\[\d+\])/",
"",
$contextPath
);
foreach($this->elementKVP as $name => $element) {
if($contextPath === $name) {
continue;
}
if(!str_starts_with($name, $contextPath)) {
continue;
}
$xpathResult = $context->ownerDocument->evaluate(
$contextPath
);
if($xpathResult->valid()) {
return $element;
}
}
$elementDescription = $context->tagName;
foreach($context->classList as $className) {
$elementDescription .= ".$className";
}
if($context->id) {
$elementDescription .= "#$context->id";
}
$elementNodePath = $context->getNodePath();
throw new ListElementNotFoundInContextException(
"There is no unnamed list element in the context element $elementDescription ($elementNodePath)."
);
}
}