woocommerce
/
lib
/
packages
/
Symfony
/
Component
/
CssSelector
/
XPath
/
Extension
/
HtmlExtension.php
woocommerce
/
lib
/
packages
/
Symfony
/
Component
/
CssSelector
/
XPath
/
Extension
Last commit date
AbstractExtension.php
7 months ago
AttributeMatchingExtension.php
7 months ago
CombinationExtension.php
7 months ago
ExtensionInterface.php
7 months ago
FunctionExtension.php
7 months ago
HtmlExtension.php
7 months ago
NodeExtension.php
7 months ago
PseudoClassExtension.php
7 months ago
HtmlExtension.php
188 lines
| 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 Automattic\WooCommerce\Vendor\Symfony\Component\CssSelector\XPath\Extension; |
| 13 | |
| 14 | use Automattic\WooCommerce\Vendor\Symfony\Component\CssSelector\Exception\ExpressionErrorException; |
| 15 | use Automattic\WooCommerce\Vendor\Symfony\Component\CssSelector\Node\FunctionNode; |
| 16 | use Automattic\WooCommerce\Vendor\Symfony\Component\CssSelector\XPath\Translator; |
| 17 | use Automattic\WooCommerce\Vendor\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 | } |
| 188 |