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 / FunctionExtension.php

FunctionExtension.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/FunctionExtension.php

172 lines 5.1 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\Exception\ExpressionErrorException;
15 use Symfony\Component\CssSelector\Exception\SyntaxErrorException;
16 use Symfony\Component\CssSelector\Node\FunctionNode;
17 use Symfony\Component\CssSelector\Parser\Parser;
18 use Symfony\Component\CssSelector\XPath\Translator;
19 use Symfony\Component\CssSelector\XPath\XPathExpr;
20
21 /**
22 * XPath expression translator function extension.
23 *
24 * This component is a port of the Python cssselect library,
25 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
26 *
27 * @author Jean-François Simon <[email protected]>
28 *
29 * @internal
30 */
31 class FunctionExtension extends AbstractExtension
32 {
33 /**
34 * {@inheritdoc}
35 */
36 public function getFunctionTranslators(): array
37 {
38 return [
39 'nth-child' => [$this, 'translateNthChild'],
40 'nth-last-child' => [$this, 'translateNthLastChild'],
41 'nth-of-type' => [$this, 'translateNthOfType'],
42 'nth-last-of-type' => [$this, 'translateNthLastOfType'],
43 'contains' => [$this, 'translateContains'],
44 'lang' => [$this, 'translateLang'],
45 ];
46 }
47
48 /**
49 * @throws ExpressionErrorException
50 */
51 public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr
52 {
53 try {
54 [$a, $b] = Parser::parseSeries($function->getArguments());
55 } catch (SyntaxErrorException $e) {
56 throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e);
57 }
58
59 $xpath->addStarPrefix();
60 if ($addNameTest) {
61 $xpath->addNameTest();
62 }
63
64 if (0 === $a) {
65 return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b));
66 }
67
68 if ($a < 0) {
69 if ($b < 1) {
70 return $xpath->addCondition('false()');
71 }
72
73 $sign = '<=';
74 } else {
75 $sign = '>=';
76 }
77
78 $expr = 'position()';
79
80 if ($last) {
81 $expr = 'last() - '.$expr;
82 --$b;
83 }
84
85 if (0 !== $b) {
86 $expr .= ' - '.$b;
87 }
88
89 $conditions = [sprintf('%s %s 0', $expr, $sign)];
90
91 if (1 !== $a && -1 !== $a) {
92 $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a);
93 }
94
95 return $xpath->addCondition(implode(' and ', $conditions));
96
97 // todo: handle an+b, odd, even
98 // an+b means every-a, plus b, e.g., 2n+1 means odd
99 // 0n+b means b
100 // n+0 means a=1, i.e., all elements
101 // an means every a elements, i.e., 2n means even
102 // -n means -1n
103 // -1n+6 means elements 6 and previous
104 }
105
106 public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr
107 {
108 return $this->translateNthChild($xpath, $function, true);
109 }
110
111 public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr
112 {
113 return $this->translateNthChild($xpath, $function, false, false);
114 }
115
116 /**
117 * @throws ExpressionErrorException
118 */
119 public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr
120 {
121 if ('*' === $xpath->getElement()) {
122 throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.');
123 }
124
125 return $this->translateNthChild($xpath, $function, true, false);
126 }
127
128 /**
129 * @throws ExpressionErrorException
130 */
131 public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr
132 {
133 $arguments = $function->getArguments();
134 foreach ($arguments as $token) {
135 if (!($token->isString() || $token->isIdentifier())) {
136 throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments));
137 }
138 }
139
140 return $xpath->addCondition(sprintf(
141 'contains(string(.), %s)',
142 Translator::getXpathLiteral($arguments[0]->getValue())
143 ));
144 }
145
146 /**
147 * @throws ExpressionErrorException
148 */
149 public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr
150 {
151 $arguments = $function->getArguments();
152 foreach ($arguments as $token) {
153 if (!($token->isString() || $token->isIdentifier())) {
154 throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments));
155 }
156 }
157
158 return $xpath->addCondition(sprintf(
159 'lang(%s)',
160 Translator::getXpathLiteral($arguments[0]->getValue())
161 ));
162 }
163
164 /**
165 * {@inheritdoc}
166 */
167 public function getName(): string
168 {
169 return 'function';
170 }
171 }
172