Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 * This file is part of the Symfony package.
|
Chris@0
|
5 *
|
Chris@0
|
6 * (c) Fabien Potencier <fabien@symfony.com>
|
Chris@0
|
7 *
|
Chris@0
|
8 * For the full copyright and license information, please view the LICENSE
|
Chris@0
|
9 * file that was distributed with this source code.
|
Chris@0
|
10 */
|
Chris@0
|
11
|
Chris@0
|
12 namespace Symfony\Component\CssSelector\XPath\Extension;
|
Chris@0
|
13
|
Chris@0
|
14 use Symfony\Component\CssSelector\Exception\ExpressionErrorException;
|
Chris@0
|
15 use Symfony\Component\CssSelector\XPath\XPathExpr;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * XPath expression translator pseudo-class extension.
|
Chris@0
|
19 *
|
Chris@0
|
20 * This component is a port of the Python cssselect library,
|
Chris@0
|
21 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
|
Chris@0
|
24 *
|
Chris@0
|
25 * @internal
|
Chris@0
|
26 */
|
Chris@0
|
27 class PseudoClassExtension extends AbstractExtension
|
Chris@0
|
28 {
|
Chris@0
|
29 /**
|
Chris@0
|
30 * {@inheritdoc}
|
Chris@0
|
31 */
|
Chris@0
|
32 public function getPseudoClassTranslators()
|
Chris@0
|
33 {
|
Chris@0
|
34 return array(
|
Chris@0
|
35 'root' => array($this, 'translateRoot'),
|
Chris@0
|
36 'first-child' => array($this, 'translateFirstChild'),
|
Chris@0
|
37 'last-child' => array($this, 'translateLastChild'),
|
Chris@0
|
38 'first-of-type' => array($this, 'translateFirstOfType'),
|
Chris@0
|
39 'last-of-type' => array($this, 'translateLastOfType'),
|
Chris@0
|
40 'only-child' => array($this, 'translateOnlyChild'),
|
Chris@0
|
41 'only-of-type' => array($this, 'translateOnlyOfType'),
|
Chris@0
|
42 'empty' => array($this, 'translateEmpty'),
|
Chris@0
|
43 );
|
Chris@0
|
44 }
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * @param XPathExpr $xpath
|
Chris@0
|
48 *
|
Chris@0
|
49 * @return XPathExpr
|
Chris@0
|
50 */
|
Chris@0
|
51 public function translateRoot(XPathExpr $xpath)
|
Chris@0
|
52 {
|
Chris@0
|
53 return $xpath->addCondition('not(parent::*)');
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 /**
|
Chris@0
|
57 * @param XPathExpr $xpath
|
Chris@0
|
58 *
|
Chris@0
|
59 * @return XPathExpr
|
Chris@0
|
60 */
|
Chris@0
|
61 public function translateFirstChild(XPathExpr $xpath)
|
Chris@0
|
62 {
|
Chris@0
|
63 return $xpath
|
Chris@0
|
64 ->addStarPrefix()
|
Chris@0
|
65 ->addNameTest()
|
Chris@0
|
66 ->addCondition('position() = 1');
|
Chris@0
|
67 }
|
Chris@0
|
68
|
Chris@0
|
69 /**
|
Chris@0
|
70 * @param XPathExpr $xpath
|
Chris@0
|
71 *
|
Chris@0
|
72 * @return XPathExpr
|
Chris@0
|
73 */
|
Chris@0
|
74 public function translateLastChild(XPathExpr $xpath)
|
Chris@0
|
75 {
|
Chris@0
|
76 return $xpath
|
Chris@0
|
77 ->addStarPrefix()
|
Chris@0
|
78 ->addNameTest()
|
Chris@0
|
79 ->addCondition('position() = last()');
|
Chris@0
|
80 }
|
Chris@0
|
81
|
Chris@0
|
82 /**
|
Chris@0
|
83 * @param XPathExpr $xpath
|
Chris@0
|
84 *
|
Chris@0
|
85 * @return XPathExpr
|
Chris@0
|
86 *
|
Chris@0
|
87 * @throws ExpressionErrorException
|
Chris@0
|
88 */
|
Chris@0
|
89 public function translateFirstOfType(XPathExpr $xpath)
|
Chris@0
|
90 {
|
Chris@0
|
91 if ('*' === $xpath->getElement()) {
|
Chris@0
|
92 throw new ExpressionErrorException('"*:first-of-type" is not implemented.');
|
Chris@0
|
93 }
|
Chris@0
|
94
|
Chris@0
|
95 return $xpath
|
Chris@0
|
96 ->addStarPrefix()
|
Chris@0
|
97 ->addCondition('position() = 1');
|
Chris@0
|
98 }
|
Chris@0
|
99
|
Chris@0
|
100 /**
|
Chris@0
|
101 * @param XPathExpr $xpath
|
Chris@0
|
102 *
|
Chris@0
|
103 * @return XPathExpr
|
Chris@0
|
104 *
|
Chris@0
|
105 * @throws ExpressionErrorException
|
Chris@0
|
106 */
|
Chris@0
|
107 public function translateLastOfType(XPathExpr $xpath)
|
Chris@0
|
108 {
|
Chris@0
|
109 if ('*' === $xpath->getElement()) {
|
Chris@0
|
110 throw new ExpressionErrorException('"*:last-of-type" is not implemented.');
|
Chris@0
|
111 }
|
Chris@0
|
112
|
Chris@0
|
113 return $xpath
|
Chris@0
|
114 ->addStarPrefix()
|
Chris@0
|
115 ->addCondition('position() = last()');
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 /**
|
Chris@0
|
119 * @param XPathExpr $xpath
|
Chris@0
|
120 *
|
Chris@0
|
121 * @return XPathExpr
|
Chris@0
|
122 */
|
Chris@0
|
123 public function translateOnlyChild(XPathExpr $xpath)
|
Chris@0
|
124 {
|
Chris@0
|
125 return $xpath
|
Chris@0
|
126 ->addStarPrefix()
|
Chris@0
|
127 ->addNameTest()
|
Chris@0
|
128 ->addCondition('last() = 1');
|
Chris@0
|
129 }
|
Chris@0
|
130
|
Chris@0
|
131 /**
|
Chris@0
|
132 * @param XPathExpr $xpath
|
Chris@0
|
133 *
|
Chris@0
|
134 * @return XPathExpr
|
Chris@0
|
135 *
|
Chris@0
|
136 * @throws ExpressionErrorException
|
Chris@0
|
137 */
|
Chris@0
|
138 public function translateOnlyOfType(XPathExpr $xpath)
|
Chris@0
|
139 {
|
Chris@0
|
140 if ('*' === $xpath->getElement()) {
|
Chris@0
|
141 throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
|
Chris@0
|
142 }
|
Chris@0
|
143
|
Chris@0
|
144 return $xpath->addCondition('last() = 1');
|
Chris@0
|
145 }
|
Chris@0
|
146
|
Chris@0
|
147 /**
|
Chris@0
|
148 * @param XPathExpr $xpath
|
Chris@0
|
149 *
|
Chris@0
|
150 * @return XPathExpr
|
Chris@0
|
151 */
|
Chris@0
|
152 public function translateEmpty(XPathExpr $xpath)
|
Chris@0
|
153 {
|
Chris@0
|
154 return $xpath->addCondition('not(*) and not(string-length())');
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 /**
|
Chris@0
|
158 * {@inheritdoc}
|
Chris@0
|
159 */
|
Chris@0
|
160 public function getName()
|
Chris@0
|
161 {
|
Chris@0
|
162 return 'pseudo-class';
|
Chris@0
|
163 }
|
Chris@0
|
164 }
|