cd8e0d5fd86774f17d66fbe175f3cf0de59677d9
[yaffs-website] / vendor / symfony / css-selector / XPath / Extension / HtmlExtension.php
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\Node\FunctionNode;
16 use Symfony\Component\CssSelector\XPath\Translator;
17 use Symfony\Component\CssSelector\XPath\XPathExpr;
18
19 /**
20  * XPath expression translator HTML extension.
21  *
22  * This component is a port of the Python cssselect library,
23  * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
24  *
25  * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
26  *
27  * @internal
28  */
29 class HtmlExtension extends AbstractExtension
30 {
31     public function __construct(Translator $translator)
32     {
33         $translator
34             ->getExtension('node')
35             ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true)
36             ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true);
37     }
38
39     /**
40      * {@inheritdoc}
41      */
42     public function getPseudoClassTranslators()
43     {
44         return array(
45             'checked' => array($this, 'translateChecked'),
46             'link' => array($this, 'translateLink'),
47             'disabled' => array($this, 'translateDisabled'),
48             'enabled' => array($this, 'translateEnabled'),
49             'selected' => array($this, 'translateSelected'),
50             'invalid' => array($this, 'translateInvalid'),
51             'hover' => array($this, 'translateHover'),
52             'visited' => array($this, 'translateVisited'),
53         );
54     }
55
56     /**
57      * {@inheritdoc}
58      */
59     public function getFunctionTranslators()
60     {
61         return array(
62             'lang' => array($this, 'translateLang'),
63         );
64     }
65
66     /**
67      * @return XPathExpr
68      */
69     public function translateChecked(XPathExpr $xpath)
70     {
71         return $xpath->addCondition(
72             '(@checked '
73             ."and (name(.) = 'input' or name(.) = 'command')"
74             ."and (@type = 'checkbox' or @type = 'radio'))"
75         );
76     }
77
78     /**
79      * @return XPathExpr
80      */
81     public function translateLink(XPathExpr $xpath)
82     {
83         return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')");
84     }
85
86     /**
87      * @return XPathExpr
88      */
89     public function translateDisabled(XPathExpr $xpath)
90     {
91         return $xpath->addCondition(
92             '('
93                 .'@disabled and'
94                 .'('
95                     ."(name(.) = 'input' and @type != 'hidden')"
96                     ." or name(.) = 'button'"
97                     ." or name(.) = 'select'"
98                     ." or name(.) = 'textarea'"
99                     ." or name(.) = 'command'"
100                     ." or name(.) = 'fieldset'"
101                     ." or name(.) = 'optgroup'"
102                     ." or name(.) = 'option'"
103                 .')'
104             .') or ('
105                 ."(name(.) = 'input' and @type != 'hidden')"
106                 ." or name(.) = 'button'"
107                 ." or name(.) = 'select'"
108                 ." or name(.) = 'textarea'"
109             .')'
110             .' and ancestor::fieldset[@disabled]'
111         );
112         // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any."
113     }
114
115     /**
116      * @return XPathExpr
117      */
118     public function translateEnabled(XPathExpr $xpath)
119     {
120         return $xpath->addCondition(
121             '('
122                 .'@href and ('
123                     ."name(.) = 'a'"
124                     ." or name(.) = 'link'"
125                     ." or name(.) = 'area'"
126                 .')'
127             .') or ('
128                 .'('
129                     ."name(.) = 'command'"
130                     ." or name(.) = 'fieldset'"
131                     ." or name(.) = 'optgroup'"
132                 .')'
133                 .' and not(@disabled)'
134             .') or ('
135                 .'('
136                     ."(name(.) = 'input' and @type != 'hidden')"
137                     ." or name(.) = 'button'"
138                     ." or name(.) = 'select'"
139                     ." or name(.) = 'textarea'"
140                     ." or name(.) = 'keygen'"
141                 .')'
142                 .' and not (@disabled or ancestor::fieldset[@disabled])'
143             .') or ('
144                 ."name(.) = 'option' and not("
145                     .'@disabled or ancestor::optgroup[@disabled]'
146                 .')'
147             .')'
148         );
149     }
150
151     /**
152      * @return XPathExpr
153      *
154      * @throws ExpressionErrorException
155      */
156     public function translateLang(XPathExpr $xpath, FunctionNode $function)
157     {
158         $arguments = $function->getArguments();
159         foreach ($arguments as $token) {
160             if (!($token->isString() || $token->isIdentifier())) {
161                 throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments));
162             }
163         }
164
165         return $xpath->addCondition(sprintf(
166             'ancestor-or-self::*[@lang][1][starts-with(concat('
167             ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')"
168             .', %s)]',
169             'lang',
170             Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-')
171         ));
172     }
173
174     /**
175      * @return XPathExpr
176      */
177     public function translateSelected(XPathExpr $xpath)
178     {
179         return $xpath->addCondition("(@selected and name(.) = 'option')");
180     }
181
182     /**
183      * @return XPathExpr
184      */
185     public function translateInvalid(XPathExpr $xpath)
186     {
187         return $xpath->addCondition('0');
188     }
189
190     /**
191      * @return XPathExpr
192      */
193     public function translateHover(XPathExpr $xpath)
194     {
195         return $xpath->addCondition('0');
196     }
197
198     /**
199      * @return XPathExpr
200      */
201     public function translateVisited(XPathExpr $xpath)
202     {
203         return $xpath->addCondition('0');
204     }
205
206     /**
207      * {@inheritdoc}
208      */
209     public function getName()
210     {
211         return 'html';
212     }
213 }