One Hat Cyber Team
Your IP:
216.73.216.30
Server IP:
198.54.114.155
Server:
Linux server71.web-hosting.com 4.18.0-513.18.1.lve.el8.x86_64 #1 SMP Thu Feb 22 12:55:50 UTC 2024 x86_64
Server Software:
LiteSpeed
PHP Version:
5.6.40
Create File
|
Create Folder
Execute
Dir :
~
/
proc
/
self
/
cwd
/
Edit File:
XPath.tar
TranslatorInterface.php 0000644 00000001773 15111341744 0011240 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Node\SelectorNode; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ interface TranslatorInterface { /** * Translates a CSS selector to an XPath expression. */ public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string; /** * Translates a parsed selector node to an XPath expression. */ public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string; } XPathExpr.php 0000644 00000004725 15111341744 0007151 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class XPathExpr { private string $path; private string $element; private string $condition; public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false) { $this->path = $path; $this->element = $element; $this->condition = $condition; if ($starPrefix) { $this->addStarPrefix(); } } public function getElement(): string { return $this->element; } /** * @return $this */ public function addCondition(string $condition): static { $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition; return $this; } public function getCondition(): string { return $this->condition; } /** * @return $this */ public function addNameTest(): static { if ('*' !== $this->element) { $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); $this->element = '*'; } return $this; } /** * @return $this */ public function addStarPrefix(): static { $this->path .= '*/'; return $this; } /** * Joins another XPathExpr with a combiner. * * @return $this */ public function join(string $combiner, self $expr): static { $path = $this->__toString().$combiner; if ('*/' !== $expr->path) { $path .= $expr->path; } $this->path = $path; $this->element = $expr->element; $this->condition = $expr->condition; return $this; } public function __toString(): string { $path = $this->path.$this->element; $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; return $path.$condition; } } Extension/HtmlExtension.php 0000644 00000013260 15111341744 0012035 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator HTML extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class HtmlExtension extends AbstractExtension { public function __construct(Translator $translator) { $translator ->getExtension('node') ->setFlag(NodeExtension::ELEMENT_NAME_IN_LOWER_CASE, true) ->setFlag(NodeExtension::ATTRIBUTE_NAME_IN_LOWER_CASE, true); } public function getPseudoClassTranslators(): array { return [ 'checked' => $this->translateChecked(...), 'link' => $this->translateLink(...), 'disabled' => $this->translateDisabled(...), 'enabled' => $this->translateEnabled(...), 'selected' => $this->translateSelected(...), 'invalid' => $this->translateInvalid(...), 'hover' => $this->translateHover(...), 'visited' => $this->translateVisited(...), ]; } public function getFunctionTranslators(): array { return [ 'lang' => $this->translateLang(...), ]; } public function translateChecked(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(@checked ' ."and (name(.) = 'input' or name(.) = 'command')" ."and (@type = 'checkbox' or @type = 'radio'))" ); } public function translateLink(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("@href and (name(.) = 'a' or name(.) = 'link' or name(.) = 'area')"); } public function translateDisabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@disabled and' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" ." or name(.) = 'option'" .')' .') or (' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" .')' .' and ancestor::fieldset[@disabled]' ); // todo: in the second half, add "and is not a descendant of that fieldset element's first legend element child, if any." } public function translateEnabled(XPathExpr $xpath): XPathExpr { return $xpath->addCondition( '(' .'@href and (' ."name(.) = 'a'" ." or name(.) = 'link'" ." or name(.) = 'area'" .')' .') or (' .'(' ."name(.) = 'command'" ." or name(.) = 'fieldset'" ." or name(.) = 'optgroup'" .')' .' and not(@disabled)' .') or (' .'(' ."(name(.) = 'input' and @type != 'hidden')" ." or name(.) = 'button'" ." or name(.) = 'select'" ." or name(.) = 'textarea'" ." or name(.) = 'keygen'" .')' .' and not (@disabled or ancestor::fieldset[@disabled])' .') or (' ."name(.) = 'option' and not(" .'@disabled or ancestor::optgroup[@disabled]' .')' .')' ); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'ancestor-or-self::*[@lang][1][starts-with(concat(' ."translate(@%s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'), '-')" .', %s)]', 'lang', Translator::getXpathLiteral(strtolower($arguments[0]->getValue()).'-') )); } public function translateSelected(XPathExpr $xpath): XPathExpr { return $xpath->addCondition("(@selected and name(.) = 'option')"); } public function translateInvalid(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateHover(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function translateVisited(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('0'); } public function getName(): string { return 'html'; } } Extension/CombinationExtension.php 0000644 00000003517 15111341744 0013377 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator combination extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class CombinationExtension extends AbstractExtension { public function getCombinationTranslators(): array { return [ ' ' => $this->translateDescendant(...), '>' => $this->translateChild(...), '+' => $this->translateDirectAdjacent(...), '~' => $this->translateIndirectAdjacent(...), ]; } public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } public function translateChild(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/', $combinedXpath); } public function translateDirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath ->join('/following-sibling::', $combinedXpath) ->addNameTest() ->addCondition('position() = 1'); } public function translateIndirectAdjacent(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/following-sibling::', $combinedXpath); } public function getName(): string { return 'combination'; } } Extension/PseudoClassExtension.php 0000644 00000006711 15111341744 0013361 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator pseudo-class extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class PseudoClassExtension extends AbstractExtension { public function getPseudoClassTranslators(): array { return [ 'root' => $this->translateRoot(...), 'scope' => $this->translateScopePseudo(...), 'first-child' => $this->translateFirstChild(...), 'last-child' => $this->translateLastChild(...), 'first-of-type' => $this->translateFirstOfType(...), 'last-of-type' => $this->translateLastOfType(...), 'only-child' => $this->translateOnlyChild(...), 'only-of-type' => $this->translateOnlyOfType(...), 'empty' => $this->translateEmpty(...), ]; } public function translateRoot(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(parent::*)'); } public function translateScopePseudo(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('1'); } public function translateFirstChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = 1'); } public function translateLastChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('position() = last()'); } /** * @throws ExpressionErrorException */ public function translateFirstOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = 1'); } /** * @throws ExpressionErrorException */ public function translateLastOfType(XPathExpr $xpath): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); } return $xpath ->addStarPrefix() ->addCondition('position() = last()'); } public function translateOnlyChild(XPathExpr $xpath): XPathExpr { return $xpath ->addStarPrefix() ->addNameTest() ->addCondition('last() = 1'); } public function translateOnlyOfType(XPathExpr $xpath): XPathExpr { $element = $xpath->getElement(); return $xpath->addCondition(sprintf('count(preceding-sibling::%s)=0 and count(following-sibling::%s)=0', $element, $element)); } public function translateEmpty(XPathExpr $xpath): XPathExpr { return $xpath->addCondition('not(*) and not(string-length())'); } public function getName(): string { return 'pseudo-class'; } } Extension/AbstractExtension.php 0000644 00000002074 15111341744 0012675 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator abstract extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ abstract class AbstractExtension implements ExtensionInterface { public function getNodeTranslators(): array { return []; } public function getCombinationTranslators(): array { return []; } public function getFunctionTranslators(): array { return []; } public function getPseudoClassTranslators(): array { return []; } public function getAttributeMatchingTranslators(): array { return []; } } Extension/ExtensionInterface.php 0000644 00000003005 15111341744 0013025 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; /** * XPath expression translator extension interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ interface ExtensionInterface { /** * Returns node translators. * * These callables will receive the node as first argument and the translator as second argument. * * @return callable[] */ public function getNodeTranslators(): array; /** * Returns combination translators. * * @return callable[] */ public function getCombinationTranslators(): array; /** * Returns function translators. * * @return callable[] */ public function getFunctionTranslators(): array; /** * Returns pseudo-class translators. * * @return callable[] */ public function getPseudoClassTranslators(): array; /** * Returns attribute operation translators. * * @return callable[] */ public function getAttributeMatchingTranslators(): array; /** * Returns extension name. */ public function getName(): string; } Extension/FunctionExtension.php 0000644 00000012050 15111341744 0012712 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Exception\SyntaxErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator function extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class FunctionExtension extends AbstractExtension { public function getFunctionTranslators(): array { return [ 'nth-child' => $this->translateNthChild(...), 'nth-last-child' => $this->translateNthLastChild(...), 'nth-of-type' => $this->translateNthOfType(...), 'nth-last-of-type' => $this->translateNthLastOfType(...), 'contains' => $this->translateContains(...), 'lang' => $this->translateLang(...), ]; } /** * @throws ExpressionErrorException */ public function translateNthChild(XPathExpr $xpath, FunctionNode $function, bool $last = false, bool $addNameTest = true): XPathExpr { try { [$a, $b] = Parser::parseSeries($function->getArguments()); } catch (SyntaxErrorException $e) { throw new ExpressionErrorException(sprintf('Invalid series: "%s".', implode('", "', $function->getArguments())), 0, $e); } $xpath->addStarPrefix(); if ($addNameTest) { $xpath->addNameTest(); } if (0 === $a) { return $xpath->addCondition('position() = '.($last ? 'last() - '.($b - 1) : $b)); } if ($a < 0) { if ($b < 1) { return $xpath->addCondition('false()'); } $sign = '<='; } else { $sign = '>='; } $expr = 'position()'; if ($last) { $expr = 'last() - '.$expr; --$b; } if (0 !== $b) { $expr .= ' - '.$b; } $conditions = [sprintf('%s %s 0', $expr, $sign)]; if (1 !== $a && -1 !== $a) { $conditions[] = sprintf('(%s) mod %d = 0', $expr, $a); } return $xpath->addCondition(implode(' and ', $conditions)); // todo: handle an+b, odd, even // an+b means every-a, plus b, e.g., 2n+1 means odd // 0n+b means b // n+0 means a=1, i.e., all elements // an means every a elements, i.e., 2n means even // -n means -1n // -1n+6 means elements 6 and previous } public function translateNthLastChild(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, true); } public function translateNthOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { return $this->translateNthChild($xpath, $function, false, false); } /** * @throws ExpressionErrorException */ public function translateNthLastOfType(XPathExpr $xpath, FunctionNode $function): XPathExpr { if ('*' === $xpath->getElement()) { throw new ExpressionErrorException('"*:nth-of-type()" is not implemented.'); } return $this->translateNthChild($xpath, $function, true, false); } /** * @throws ExpressionErrorException */ public function translateContains(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :contains(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'contains(string(.), %s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } /** * @throws ExpressionErrorException */ public function translateLang(XPathExpr $xpath, FunctionNode $function): XPathExpr { $arguments = $function->getArguments(); foreach ($arguments as $token) { if (!($token->isString() || $token->isIdentifier())) { throw new ExpressionErrorException('Expected a single string or identifier for :lang(), got '.implode(', ', $arguments)); } } return $xpath->addCondition(sprintf( 'lang(%s)', Translator::getXpathLiteral($arguments[0]->getValue()) )); } public function getName(): string { return 'function'; } } Extension/NodeExtension.php 0000644 00000013300 15111341744 0012011 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\Node; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator node extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class NodeExtension extends AbstractExtension { public const ELEMENT_NAME_IN_LOWER_CASE = 1; public const ATTRIBUTE_NAME_IN_LOWER_CASE = 2; public const ATTRIBUTE_VALUE_IN_LOWER_CASE = 4; private int $flags; public function __construct(int $flags = 0) { $this->flags = $flags; } /** * @return $this */ public function setFlag(int $flag, bool $on): static { if ($on && !$this->hasFlag($flag)) { $this->flags += $flag; } if (!$on && $this->hasFlag($flag)) { $this->flags -= $flag; } return $this; } public function hasFlag(int $flag): bool { return (bool) ($this->flags & $flag); } public function getNodeTranslators(): array { return [ 'Selector' => $this->translateSelector(...), 'CombinedSelector' => $this->translateCombinedSelector(...), 'Negation' => $this->translateNegation(...), 'Function' => $this->translateFunction(...), 'Pseudo' => $this->translatePseudo(...), 'Attribute' => $this->translateAttribute(...), 'Class' => $this->translateClass(...), 'Hash' => $this->translateHash(...), 'Element' => $this->translateElement(...), ]; } public function translateSelector(Node\SelectorNode $node, Translator $translator): XPathExpr { return $translator->nodeToXPath($node->getTree()); } public function translateCombinedSelector(Node\CombinedSelectorNode $node, Translator $translator): XPathExpr { return $translator->addCombination($node->getCombinator(), $node->getSelector(), $node->getSubSelector()); } public function translateNegation(Node\NegationNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); $subXpath = $translator->nodeToXPath($node->getSubSelector()); $subXpath->addNameTest(); if ($subXpath->getCondition()) { return $xpath->addCondition(sprintf('not(%s)', $subXpath->getCondition())); } return $xpath->addCondition('0'); } public function translateFunction(Node\FunctionNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addFunction($xpath, $node); } public function translatePseudo(Node\PseudoNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addPseudoClass($xpath, $node->getIdentifier()); } public function translateAttribute(Node\AttributeNode $node, Translator $translator): XPathExpr { $name = $node->getAttribute(); $safe = $this->isSafeName($name); if ($this->hasFlag(self::ATTRIBUTE_NAME_IN_LOWER_CASE)) { $name = strtolower($name); } if ($node->getNamespace()) { $name = sprintf('%s:%s', $node->getNamespace(), $name); $safe = $safe && $this->isSafeName($node->getNamespace()); } $attribute = $safe ? '@'.$name : sprintf('attribute::*[name() = %s]', Translator::getXpathLiteral($name)); $value = $node->getValue(); $xpath = $translator->nodeToXPath($node->getSelector()); if ($this->hasFlag(self::ATTRIBUTE_VALUE_IN_LOWER_CASE)) { $value = strtolower($value); } return $translator->addAttributeMatching($xpath, $node->getOperator(), $attribute, $value); } public function translateClass(Node\ClassNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '~=', '@class', $node->getName()); } public function translateHash(Node\HashNode $node, Translator $translator): XPathExpr { $xpath = $translator->nodeToXPath($node->getSelector()); return $translator->addAttributeMatching($xpath, '=', '@id', $node->getId()); } public function translateElement(Node\ElementNode $node): XPathExpr { $element = $node->getElement(); if ($element && $this->hasFlag(self::ELEMENT_NAME_IN_LOWER_CASE)) { $element = strtolower($element); } if ($element) { $safe = $this->isSafeName($element); } else { $element = '*'; $safe = true; } if ($node->getNamespace()) { $element = sprintf('%s:%s', $node->getNamespace(), $element); $safe = $safe && $this->isSafeName($node->getNamespace()); } $xpath = new XPathExpr('', $element); if (!$safe) { $xpath->addNameTest(); } return $xpath; } public function getName(): string { return 'node'; } private function isSafeName(string $name): bool { return 0 < preg_match('~^[a-zA-Z_][a-zA-Z0-9_.-]*$~', $name); } } Extension/AttributeMatchingExtension.php 0000644 00000007254 15111341744 0014555 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath\Extension; use Symfony\Component\CssSelector\XPath\Translator; use Symfony\Component\CssSelector\XPath\XPathExpr; /** * XPath expression translator attribute extension. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class AttributeMatchingExtension extends AbstractExtension { public function getAttributeMatchingTranslators(): array { return [ 'exists' => $this->translateExists(...), '=' => $this->translateEquals(...), '~=' => $this->translateIncludes(...), '|=' => $this->translateDashMatch(...), '^=' => $this->translatePrefixMatch(...), '$=' => $this->translateSuffixMatch(...), '*=' => $this->translateSubstringMatch(...), '!=' => $this->translateDifferent(...), ]; } public function translateExists(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($attribute); } public function translateEquals(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf('%s = %s', $attribute, Translator::getXpathLiteral($value))); } public function translateIncludes(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(concat(\' \', normalize-space(%1$s), \' \'), %2$s)', $attribute, Translator::getXpathLiteral(' '.$value.' ') ) : '0'); } public function translateDashMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( '%1$s and (%1$s = %2$s or starts-with(%1$s, %3$s))', $attribute, Translator::getXpathLiteral($value), Translator::getXpathLiteral($value.'-') )); } public function translatePrefixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and starts-with(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateSuffixMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and substring(%1$s, string-length(%1$s)-%2$s) = %3$s', $attribute, \strlen($value) - 1, Translator::getXpathLiteral($value) ) : '0'); } public function translateSubstringMatch(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition($value ? sprintf( '%1$s and contains(%1$s, %2$s)', $attribute, Translator::getXpathLiteral($value) ) : '0'); } public function translateDifferent(XPathExpr $xpath, string $attribute, ?string $value): XPathExpr { return $xpath->addCondition(sprintf( $value ? 'not(%1$s) or %1$s != %2$s' : '%s != %s', $attribute, Translator::getXpathLiteral($value) )); } public function getName(): string { return 'attribute-matching'; } } error_log 0000644 00000000547 15111341744 0006470 0 ustar 00 [25-Nov-2025 06:30:06 UTC] PHP Fatal error: Uncaught Error: Interface "Symfony\Component\CssSelector\XPath\TranslatorInterface" not found in /home/fluxyjvi/public_html/project/vendor/symfony/css-selector/XPath/Translator.php:31 Stack trace: #0 {main} thrown in /home/fluxyjvi/public_html/project/vendor/symfony/css-selector/XPath/Translator.php on line 31 Translator.php 0000644 00000016213 15111341744 0007412 0 ustar 00 <?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\CssSelector\XPath; use Symfony\Component\CssSelector\Exception\ExpressionErrorException; use Symfony\Component\CssSelector\Node\FunctionNode; use Symfony\Component\CssSelector\Node\NodeInterface; use Symfony\Component\CssSelector\Node\SelectorNode; use Symfony\Component\CssSelector\Parser\Parser; use Symfony\Component\CssSelector\Parser\ParserInterface; /** * XPath expression translator interface. * * This component is a port of the Python cssselect library, * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. * * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com> * * @internal */ class Translator implements TranslatorInterface { private ParserInterface $mainParser; /** * @var ParserInterface[] */ private array $shortcutParsers = []; /** * @var Extension\ExtensionInterface[] */ private array $extensions = []; private array $nodeTranslators = []; private array $combinationTranslators = []; private array $functionTranslators = []; private array $pseudoClassTranslators = []; private array $attributeMatchingTranslators = []; public function __construct(ParserInterface $parser = null) { $this->mainParser = $parser ?? new Parser(); $this ->registerExtension(new Extension\NodeExtension()) ->registerExtension(new Extension\CombinationExtension()) ->registerExtension(new Extension\FunctionExtension()) ->registerExtension(new Extension\PseudoClassExtension()) ->registerExtension(new Extension\AttributeMatchingExtension()) ; } public static function getXpathLiteral(string $element): string { if (!str_contains($element, "'")) { return "'".$element."'"; } if (!str_contains($element, '"')) { return '"'.$element.'"'; } $string = $element; $parts = []; while (true) { if (false !== $pos = strpos($string, "'")) { $parts[] = sprintf("'%s'", substr($string, 0, $pos)); $parts[] = "\"'\""; $string = substr($string, $pos + 1); } else { $parts[] = "'$string'"; break; } } return sprintf('concat(%s)', implode(', ', $parts)); } public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string { $selectors = $this->parseSelectors($cssExpr); /** @var SelectorNode $selector */ foreach ($selectors as $index => $selector) { if (null !== $selector->getPseudoElement()) { throw new ExpressionErrorException('Pseudo-elements are not supported.'); } $selectors[$index] = $this->selectorToXPath($selector, $prefix); } return implode(' | ', $selectors); } public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string { return ($prefix ?: '').$this->nodeToXPath($selector); } /** * @return $this */ public function registerExtension(Extension\ExtensionInterface $extension): static { $this->extensions[$extension->getName()] = $extension; $this->nodeTranslators = array_merge($this->nodeTranslators, $extension->getNodeTranslators()); $this->combinationTranslators = array_merge($this->combinationTranslators, $extension->getCombinationTranslators()); $this->functionTranslators = array_merge($this->functionTranslators, $extension->getFunctionTranslators()); $this->pseudoClassTranslators = array_merge($this->pseudoClassTranslators, $extension->getPseudoClassTranslators()); $this->attributeMatchingTranslators = array_merge($this->attributeMatchingTranslators, $extension->getAttributeMatchingTranslators()); return $this; } /** * @throws ExpressionErrorException */ public function getExtension(string $name): Extension\ExtensionInterface { if (!isset($this->extensions[$name])) { throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); } return $this->extensions[$name]; } /** * @return $this */ public function registerParserShortcut(ParserInterface $shortcut): static { $this->shortcutParsers[] = $shortcut; return $this; } /** * @throws ExpressionErrorException */ public function nodeToXPath(NodeInterface $node): XPathExpr { if (!isset($this->nodeTranslators[$node->getNodeName()])) { throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); } return $this->nodeTranslators[$node->getNodeName()]($node, $this); } /** * @throws ExpressionErrorException */ public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr { if (!isset($this->combinationTranslators[$combiner])) { throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); } return $this->combinationTranslators[$combiner]($this->nodeToXPath($xpath), $this->nodeToXPath($combinedXpath)); } /** * @throws ExpressionErrorException */ public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr { if (!isset($this->functionTranslators[$function->getName()])) { throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); } return $this->functionTranslators[$function->getName()]($xpath, $function); } /** * @throws ExpressionErrorException */ public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr { if (!isset($this->pseudoClassTranslators[$pseudoClass])) { throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); } return $this->pseudoClassTranslators[$pseudoClass]($xpath); } /** * @throws ExpressionErrorException */ public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, ?string $value): XPathExpr { if (!isset($this->attributeMatchingTranslators[$operator])) { throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); } return $this->attributeMatchingTranslators[$operator]($xpath, $attribute, $value); } /** * @return SelectorNode[] */ private function parseSelectors(string $css): array { foreach ($this->shortcutParsers as $shortcut) { $tokens = $shortcut->parse($css); if ($tokens) { return $tokens; } } return $this->mainParser->parse($css); } }
Simpan