[ Index ] |
PHP Cross Reference of DokuWiki |
[Summary view] [Print] [Text view]
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(): array 43 { 44 return [ 45 'checked' => [$this, 'translateChecked'], 46 'link' => [$this, 'translateLink'], 47 'disabled' => [$this, 'translateDisabled'], 48 'enabled' => [$this, 'translateEnabled'], 49 'selected' => [$this, 'translateSelected'], 50 'invalid' => [$this, 'translateInvalid'], 51 'hover' => [$this, 'translateHover'], 52 'visited' => [$this, 'translateVisited'], 53 ]; 54 } 55 56 /** 57 * {@inheritdoc} 58 */ 59 public function getFunctionTranslators(): array 60 { 61 return [ 62 'lang' => [$this, 'translateLang'], 63 ]; 64 } 65 66 public function translateChecked(XPathExpr $xpath): XPathExpr 67 { 68 return $xpath->addCondition( 69 '(@checked ' 70 ."and (name(.) = 'input' or name(.) = 'command')" 71 ."and (@type = 'checkbox' or @type = 'radio'))" 72 ); 73 } 74 75 public function translateLink(XPathExpr $xpath): XPathExpr 76 { 77 return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); 78 } 79 80 public function translateDisabled(XPathExpr $xpath): XPathExpr 81 { 82 return $xpath->addCondition( 83 '(' 84 .'@disabled and' 85 .'(' 86 ."(name(.) = 'input' and @type != 'hidden')" 87 ." or name(.) = 'button'" 88 ." or name(.) = 'select'" 89 ." or name(.) = 'textarea'" 90 ." or name(.) = 'command'" 91 ." or name(.) = 'fieldset'" 92 ." or name(.) = 'optgroup'" 93 ." or name(.) = 'option'" 94 .')' 95 .') or (' 96 ."(name(.) = 'input' and @type != 'hidden')" 97 ." or name(.) = 'button'" 98 ." or name(.) = 'select'" 99 ." or name(.) = 'textarea'" 100 .')' 101 .' and ancestor::fieldset[@disabled]' 102 ); 103 // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." 104 } 105 106 public function translateEnabled(XPathExpr $xpath): XPathExpr 107 { 108 return $xpath->addCondition( 109 '(' 110 .'@href and (' 111 ."name(.) = 'a'" 112 ." or name(.) = 'link'" 113 ." or name(.) = 'area'" 114 .')' 115 .') or (' 116 .'(' 117 ."name(.) = 'command'" 118 ." or name(.) = 'fieldset'" 119 ." or name(.) = 'optgroup'" 120 .')' 121 .' and not(@disabled)' 122 .') or (' 123 .'(' 124 ."(name(.) = 'input' and @type != 'hidden')" 125 ." or name(.) = 'button'" 126 ." or name(.) = 'select'" 127 ." or name(.) = 'textarea'" 128 ." or name(.) = 'keygen'" 129 .')' 130 .' and not (@disabled or ancestor::fieldset[@disabled])' 131 .') or (' 132 ."name(.) = 'option' and not(" 133 .'@disabled or ancestor::optgroup[@disabled]' 134 .')' 135 .')' 136 ); 137 } 138 139 /** 140 * @throws ExpressionErrorException 141 */ 142 public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr 143 { 144 $arguments = $function->getArguments(); 145 foreach ($arguments as $token) { 146 if (!($token->isString() || $token->isIdentifier())) { 147 throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); 148 } 149 } 150 151 return $xpath->addCondition(sprintf( 152 'ancestor-or-self::*[@lang][1][starts-with(concat(' 153 ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" 154 .', %s)]', 155 'lang', 156 Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') 157 )); 158 } 159 160 public function translateSelected(XPathExpr $xpath): XPathExpr 161 { 162 return $xpath->addCondition("(@selected and name(.) = 'option')"); 163 } 164 165 public function translateInvalid(XPathExpr $xpath): XPathExpr 166 { 167 return $xpath->addCondition('0'); 168 } 169 170 public function translateHover(XPathExpr $xpath): XPathExpr 171 { 172 return $xpath->addCondition('0'); 173 } 174 175 public function translateVisited(XPathExpr $xpath): XPathExpr 176 { 177 return $xpath->addCondition('0'); 178 } 179 180 /** 181 * {@inheritdoc} 182 */ 183 public function getName(): string 184 { 185 return 'html'; 186 } 187 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body