Mercurial > hg > isophonics-drupal-site
comparison vendor/symfony/css-selector/XPath/Extension/FunctionExtension.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 1fec387a4317 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 /* | |
4 * This file is part of the Symfony package. | |
5 * | |
6 * (c) Fabien Potencier <fabien@symfony.com> | |
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 <jeanfrancois.simon@sensiolabs.com> | |
28 * | |
29 * @internal | |
30 */ | |
31 class FunctionExtension extends AbstractExtension | |
32 { | |
33 /** | |
34 * {@inheritdoc} | |
35 */ | |
36 public function getFunctionTranslators() | |
37 { | |
38 return array( | |
39 'nth-child' => array($this, 'translateNthChild'), | |
40 'nth-last-child' => array($this, 'translateNthLastChild'), | |
41 'nth-of-type' => array($this, 'translateNthOfType'), | |
42 'nth-last-of-type' => array($this, 'translateNthLastOfType'), | |
43 'contains' => array($this, 'translateContains'), | |
44 'lang' => array($this, 'translateLang'), | |
45 ); | |
46 } | |
47 | |
48 /** | |
49 * @param XPathExpr $xpath | |
50 * @param FunctionNode $function | |
51 * @param bool $last | |
52 * @param bool $addNameTest | |
53 * | |
54 * @return XPathExpr | |
55 * | |
56 * @throws ExpressionErrorException | |
57 */ | |
58 public function translateNthChild(XPathExpr $xpath, FunctionNode $function, $last = false, $addNameTest = true) | |
59 { | |
60 try { | |
61 list($a, $b) = Parser::parseSeries($function->getArguments()); | |
62 } catch (SyntaxErrorException $e) { | |
63 throw new ExpressionErrorException(sprintf('Invalid series: %s', implode(', ', $function->getArguments())), 0, $e); | |
64 } | |
65 | |
66 $xpath->addStarPrefix(); | |
67 if ($addNameTest) { | |
68 $xpath->addNameTest(); | |
69 } | |
70 | |
71 if (0 === $a) { | |
72 return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); | |
73 } | |
74 | |
75 if ($a < 0) { | |
76 if ($b < 1) { | |
77 return $xpath->addCondition('false()'); | |
78 } | |
79 | |
80 $sign = '<='; | |
81 } else { | |
82 $sign = '>='; | |
83 } | |
84 | |
85 $expr = 'position()'; | |
86 | |
87 if ($last) { | |
88 $expr = 'last() - '.$expr; | |
89 --$b; | |
90 } | |
91 | |
92 if (0 !== $b) { | |
93 $expr .= ' - '.$b; | |
94 } | |
95 | |
96 $conditions = array(sprintf('%s %s 0', $expr, $sign)); | |
97 | |
98 if (1 !== $a && -1 !== $a) { | |
99 $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); | |
100 } | |
101 | |
102 return $xpath->addCondition(implode(' and ', $conditions)); | |
103 | |
104 // todo: handle an+b, odd, even | |
105 // an+b means every-a, plus b, e.g., 2n+1 means odd | |
106 // 0n+b means b | |
107 // n+0 means a=1, i.e., all elements | |
108 // an means every a elements, i.e., 2n means even | |
109 // -n means -1n | |
110 // -1n+6 means elements 6 and previous | |
111 } | |
112 | |
113 /** | |
114 * @param XPathExpr $xpath | |
115 * @param FunctionNode $function | |
116 * | |
117 * @return XPathExpr | |
118 */ | |
119 public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function) | |
120 { | |
121 return $this->translateNthChild($xpath, $function, true); | |
122 } | |
123 | |
124 /** | |
125 * @param XPathExpr $xpath | |
126 * @param FunctionNode $function | |
127 * | |
128 * @return XPathExpr | |
129 */ | |
130 public function translateNthOfType(XPathExpr $xpath, FunctionNode $function) | |
131 { | |
132 return $this->translateNthChild($xpath, $function, false, false); | |
133 } | |
134 | |
135 /** | |
136 * @param XPathExpr $xpath | |
137 * @param FunctionNode $function | |
138 * | |
139 * @return XPathExpr | |
140 * | |
141 * @throws ExpressionErrorException | |
142 */ | |
143 public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function) | |
144 { | |
145 if ('*' === $xpath->getElement()) { | |
146 throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); | |
147 } | |
148 | |
149 return $this->translateNthChild($xpath, $function, true, false); | |
150 } | |
151 | |
152 /** | |
153 * @param XPathExpr $xpath | |
154 * @param FunctionNode $function | |
155 * | |
156 * @return XPathExpr | |
157 * | |
158 * @throws ExpressionErrorException | |
159 */ | |
160 public function translateContains(XPathExpr $xpath, FunctionNode $function) | |
161 { | |
162 $arguments = $function->getArguments(); | |
163 foreach ($arguments as $token) { | |
164 if (!($token->isString() || $token->isIdentifier())) { | |
165 throw new ExpressionErrorException( | |
166 'Expected a single string or identifier for :contains(), got ' | |
167 .implode(', ', $arguments) | |
168 ); | |
169 } | |
170 } | |
171 | |
172 return $xpath->addCondition(sprintf( | |
173 'contains(string(.), %s)', | |
174 Translator::getXpathLiteral($arguments[0]->getValue()) | |
175 )); | |
176 } | |
177 | |
178 /** | |
179 * @param XPathExpr $xpath | |
180 * @param FunctionNode $function | |
181 * | |
182 * @return XPathExpr | |
183 * | |
184 * @throws ExpressionErrorException | |
185 */ | |
186 public function translateLang(XPathExpr $xpath, FunctionNode $function) | |
187 { | |
188 $arguments = $function->getArguments(); | |
189 foreach ($arguments as $token) { | |
190 if (!($token->isString() || $token->isIdentifier())) { | |
191 throw new ExpressionErrorException( | |
192 'Expected a single string or identifier for :lang(), got ' | |
193 .implode(', ', $arguments) | |
194 ); | |
195 } | |
196 } | |
197 | |
198 return $xpath->addCondition(sprintf( | |
199 'lang(%s)', | |
200 Translator::getXpathLiteral($arguments[0]->getValue()) | |
201 )); | |
202 } | |
203 | |
204 /** | |
205 * {@inheritdoc} | |
206 */ | |
207 public function getName() | |
208 { | |
209 return 'function'; | |
210 } | |
211 } |