PluginProbe
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript / 4.1.17
BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript v4.1.17
4.1.19 4.1.18 4.1.17 4.1.16 4.1.15 4.1.14 4.1.13 4.1.12 4.1.11 4.1.10 4.0.30 4.0.29 4.0.28 4.0.27 4.0.26 4.0.24 4.0.25 4.0.23 4.0.22 4.0.21 4.0.19 4.0.18 4.0.17 4.0.16 1.9.3 All 173 releases
searchpro / BerqWP / vendor / symfony / css-selector / XPath / Extension / NodeExtension.php

NodeExtension.php in BerqWP – All-In-One Optimization for Core Web Vitals, Cache, CDN, Images, CSS & JavaScript 4.1.17, at BerqWP/vendor/symfony/css-selector/XPath/Extension/NodeExtension.php

198 lines 5.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <[email protected]>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12 namespace Symfony\Component\CssSelector\XPath\Extension;
13
14 use Symfony\Component\CssSelector\Node;
15 use Symfony\Component\CssSelector\XPath\Translator;
16 use Symfony\Component\CssSelector\XPath\XPathExpr;
17
18 /**
19 * XPath expression translator node extension.
20 *
21 * This component is a port of the Python cssselect library,
22 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
23 *
24 * @author Jean-François Simon <[email protected]>
25 *
26 * @internal
27 */
28 class NodeExtension extends AbstractExtension
29 {
30 public const ELEMENT_NAME_IN_LOWER_CASE = 1;
31 public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2;
32 public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4;
33
34 private $flags;
35
36 public function __construct(int $flags = 0)
37 {
38 $this->flags = $flags;
39 }
40
41 /**
42 * @return $this
43 */
44 public function setFlag(int $flag, bool $on): self
45 {
46 if ($on && !$this->hasFlag($flag)) {
47 $this->flags += $flag;
48 }
49
50 if (!$on && $this->hasFlag($flag)) {
51 $this->flags -= $flag;
52 }
53
54 return $this;
55 }
56
57 public function hasFlag(int $flag): bool
58 {
59 return (bool) ($this->flags & $flag);
60 }
61
62 /**
63 * {@inheritdoc}
64 */
65 public function getNodeTranslators(): array
66 {
67 return [
68 'Selector' => [$this, 'translateSelector'],
69 'CombinedSelector' => [$this, 'translateCombinedSelector'],
70 'Negation' => [$this, 'translateNegation'],
71 'Function' => [$this, 'translateFunction'],
72 'Pseudo' => [$this, 'translatePseudo'],
73 'Attribute' => [$this, 'translateAttribute'],
74 'Class' => [$this, 'translateClass'],
75 'Hash' => [$this, 'translateHash'],
76 'Element' => [$this, 'translateElement'],
77 ];
78 }
79
80 public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr
81 {
82 return $translator->nodeToXPath($node->getTree());
83 }
84
85 public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr
86 {
87 return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector());
88 }
89
90 public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr
91 {
92 $xpath = $translator->nodeToXPath($node->getSelector());
93 $subXpath = $translator->nodeToXPath($node->getSubSelector());
94 $subXpath->addNameTest();
95
96 if ($subXpath->getCondition()) {
97 return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition()));
98 }
99
100 return $xpath->addCondition('0');
101 }
102
103 public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr
104 {
105 $xpath = $translator->nodeToXPath($node->getSelector());
106
107 return $translator->addFunction($xpath, $node);
108 }
109
110 public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr
111 {
112 $xpath = $translator->nodeToXPath($node->getSelector());
113
114 return $translator->addPseudoClass($xpath, $node->getIdentifier());
115 }
116
117 public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr
118 {
119 $name = $node->getAttribute();
120 $safe = $this->isSafeName($name);
121
122 if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) {
123 $name = strtolower($name);
124 }
125
126 if ($node->getNamespace()) {
127 $name = sprintf('%s:%s', $node->getNamespace(), $name);
128 $safe = $safe && $this->isSafeName($node->getNamespace());
129 }
130
131 $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name));
132 $value = $node->getValue();
133 $xpath = $translator->nodeToXPath($node->getSelector());
134
135 if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) {
136 $value = strtolower($value);
137 }
138
139 return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value);
140 }
141
142 public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr
143 {
144 $xpath = $translator->nodeToXPath($node->getSelector());
145
146 return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName());
147 }
148
149 public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr
150 {
151 $xpath = $translator->nodeToXPath($node->getSelector());
152
153 return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId());
154 }
155
156 public function translateElement(Node\ElementNode $node): XPathExpr
157 {
158 $element = $node->getElement();
159
160 if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) {
161 $element = strtolower($element);
162 }
163
164 if ($element) {
165 $safe = $this->isSafeName($element);
166 } else {
167 $element = '*';
168 $safe = true;
169 }
170
171 if ($node->getNamespace()) {
172 $element = sprintf('%s:%s', $node->getNamespace(), $element);
173 $safe = $safe && $this->isSafeName($node->getNamespace());
174 }
175
176 $xpath = new XPathExpr('', $element);
177
178 if (!$safe) {
179 $xpath->addNameTest();
180 }
181
182 return $xpath;
183 }
184
185 /**
186 * {@inheritdoc}
187 */
188 public function getName(): string
189 {
190 return 'node';
191 }
192
193 private function isSafeName(string $name): bool
194 {
195 return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name);
196 }
197 }
198