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@17
|
34 return [
|
Chris@17
|
35 'root' => [$this, 'translateRoot'],
|
Chris@17
|
36 'first-child' => [$this, 'translateFirstChild'],
|
Chris@17
|
37 'last-child' => [$this, 'translateLastChild'],
|
Chris@17
|
38 'first-of-type' => [$this, 'translateFirstOfType'],
|
Chris@17
|
39 'last-of-type' => [$this, 'translateLastOfType'],
|
Chris@17
|
40 'only-child' => [$this, 'translateOnlyChild'],
|
Chris@17
|
41 'only-of-type' => [$this, 'translateOnlyOfType'],
|
Chris@17
|
42 'empty' => [$this, 'translateEmpty'],
|
Chris@17
|
43 ];
|
Chris@0
|
44 }
|
Chris@0
|
45
|
Chris@0
|
46 /**
|
Chris@0
|
47 * @return XPathExpr
|
Chris@0
|
48 */
|
Chris@0
|
49 public function translateRoot(XPathExpr $xpath)
|
Chris@0
|
50 {
|
Chris@0
|
51 return $xpath->addCondition('not(parent::*)');
|
Chris@0
|
52 }
|
Chris@0
|
53
|
Chris@0
|
54 /**
|
Chris@0
|
55 * @return XPathExpr
|
Chris@0
|
56 */
|
Chris@0
|
57 public function translateFirstChild(XPathExpr $xpath)
|
Chris@0
|
58 {
|
Chris@0
|
59 return $xpath
|
Chris@0
|
60 ->addStarPrefix()
|
Chris@0
|
61 ->addNameTest()
|
Chris@0
|
62 ->addCondition('position() = 1');
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 /**
|
Chris@0
|
66 * @return XPathExpr
|
Chris@0
|
67 */
|
Chris@0
|
68 public function translateLastChild(XPathExpr $xpath)
|
Chris@0
|
69 {
|
Chris@0
|
70 return $xpath
|
Chris@0
|
71 ->addStarPrefix()
|
Chris@0
|
72 ->addNameTest()
|
Chris@0
|
73 ->addCondition('position() = last()');
|
Chris@0
|
74 }
|
Chris@0
|
75
|
Chris@0
|
76 /**
|
Chris@0
|
77 * @return XPathExpr
|
Chris@0
|
78 *
|
Chris@0
|
79 * @throws ExpressionErrorException
|
Chris@0
|
80 */
|
Chris@0
|
81 public function translateFirstOfType(XPathExpr $xpath)
|
Chris@0
|
82 {
|
Chris@0
|
83 if ('*' === $xpath->getElement()) {
|
Chris@0
|
84 throw new ExpressionErrorException('"*:first-of-type" is not implemented.');
|
Chris@0
|
85 }
|
Chris@0
|
86
|
Chris@0
|
87 return $xpath
|
Chris@0
|
88 ->addStarPrefix()
|
Chris@0
|
89 ->addCondition('position() = 1');
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * @return XPathExpr
|
Chris@0
|
94 *
|
Chris@0
|
95 * @throws ExpressionErrorException
|
Chris@0
|
96 */
|
Chris@0
|
97 public function translateLastOfType(XPathExpr $xpath)
|
Chris@0
|
98 {
|
Chris@0
|
99 if ('*' === $xpath->getElement()) {
|
Chris@0
|
100 throw new ExpressionErrorException('"*:last-of-type" is not implemented.');
|
Chris@0
|
101 }
|
Chris@0
|
102
|
Chris@0
|
103 return $xpath
|
Chris@0
|
104 ->addStarPrefix()
|
Chris@0
|
105 ->addCondition('position() = last()');
|
Chris@0
|
106 }
|
Chris@0
|
107
|
Chris@0
|
108 /**
|
Chris@0
|
109 * @return XPathExpr
|
Chris@0
|
110 */
|
Chris@0
|
111 public function translateOnlyChild(XPathExpr $xpath)
|
Chris@0
|
112 {
|
Chris@0
|
113 return $xpath
|
Chris@0
|
114 ->addStarPrefix()
|
Chris@0
|
115 ->addNameTest()
|
Chris@0
|
116 ->addCondition('last() = 1');
|
Chris@0
|
117 }
|
Chris@0
|
118
|
Chris@0
|
119 /**
|
Chris@0
|
120 * @return XPathExpr
|
Chris@0
|
121 *
|
Chris@0
|
122 * @throws ExpressionErrorException
|
Chris@0
|
123 */
|
Chris@0
|
124 public function translateOnlyOfType(XPathExpr $xpath)
|
Chris@0
|
125 {
|
Chris@0
|
126 if ('*' === $xpath->getElement()) {
|
Chris@0
|
127 throw new ExpressionErrorException('"*:only-of-type" is not implemented.');
|
Chris@0
|
128 }
|
Chris@0
|
129
|
Chris@0
|
130 return $xpath->addCondition('last() = 1');
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 /**
|
Chris@0
|
134 * @return XPathExpr
|
Chris@0
|
135 */
|
Chris@0
|
136 public function translateEmpty(XPathExpr $xpath)
|
Chris@0
|
137 {
|
Chris@0
|
138 return $xpath->addCondition('not(*) and not(string-length())');
|
Chris@0
|
139 }
|
Chris@0
|
140
|
Chris@0
|
141 /**
|
Chris@0
|
142 * {@inheritdoc}
|
Chris@0
|
143 */
|
Chris@0
|
144 public function getName()
|
Chris@0
|
145 {
|
Chris@0
|
146 return 'pseudo-class';
|
Chris@0
|
147 }
|
Chris@0
|
148 }
|