Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\CssSelector\XPath\Extension; Chris@0: Chris@0: use Symfony\Component\CssSelector\Exception\ExpressionErrorException; Chris@0: use Symfony\Component\CssSelector\XPath\XPathExpr; Chris@0: Chris@0: /** Chris@0: * XPath expression translator pseudo-class extension. Chris@0: * Chris@0: * This component is a port of the Python cssselect library, Chris@0: * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect. Chris@0: * Chris@0: * @author Jean-François Simon Chris@0: * Chris@0: * @internal Chris@0: */ Chris@0: class PseudoClassExtension extends AbstractExtension Chris@0: { Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getPseudoClassTranslators() Chris@0: { Chris@17: return [ Chris@17: 'root' => [$this, 'translateRoot'], Chris@17: 'first-child' => [$this, 'translateFirstChild'], Chris@17: 'last-child' => [$this, 'translateLastChild'], Chris@17: 'first-of-type' => [$this, 'translateFirstOfType'], Chris@17: 'last-of-type' => [$this, 'translateLastOfType'], Chris@17: 'only-child' => [$this, 'translateOnlyChild'], Chris@17: 'only-of-type' => [$this, 'translateOnlyOfType'], Chris@17: 'empty' => [$this, 'translateEmpty'], Chris@17: ]; Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: */ Chris@0: public function translateRoot(XPathExpr $xpath) Chris@0: { Chris@0: return $xpath->addCondition('not(parent::*)'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: */ Chris@0: public function translateFirstChild(XPathExpr $xpath) Chris@0: { Chris@0: return $xpath Chris@0: ->addStarPrefix() Chris@0: ->addNameTest() Chris@0: ->addCondition('position() = 1'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: */ Chris@0: public function translateLastChild(XPathExpr $xpath) Chris@0: { Chris@0: return $xpath Chris@0: ->addStarPrefix() Chris@0: ->addNameTest() Chris@0: ->addCondition('position() = last()'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: * Chris@0: * @throws ExpressionErrorException Chris@0: */ Chris@0: public function translateFirstOfType(XPathExpr $xpath) Chris@0: { Chris@0: if ('*' === $xpath->getElement()) { Chris@0: throw new ExpressionErrorException('"*:first-of-type" is not implemented.'); Chris@0: } Chris@0: Chris@0: return $xpath Chris@0: ->addStarPrefix() Chris@0: ->addCondition('position() = 1'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: * Chris@0: * @throws ExpressionErrorException Chris@0: */ Chris@0: public function translateLastOfType(XPathExpr $xpath) Chris@0: { Chris@0: if ('*' === $xpath->getElement()) { Chris@0: throw new ExpressionErrorException('"*:last-of-type" is not implemented.'); Chris@0: } Chris@0: Chris@0: return $xpath Chris@0: ->addStarPrefix() Chris@0: ->addCondition('position() = last()'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: */ Chris@0: public function translateOnlyChild(XPathExpr $xpath) Chris@0: { Chris@0: return $xpath Chris@0: ->addStarPrefix() Chris@0: ->addNameTest() Chris@0: ->addCondition('last() = 1'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: * Chris@0: * @throws ExpressionErrorException Chris@0: */ Chris@0: public function translateOnlyOfType(XPathExpr $xpath) Chris@0: { Chris@0: if ('*' === $xpath->getElement()) { Chris@0: throw new ExpressionErrorException('"*:only-of-type" is not implemented.'); Chris@0: } Chris@0: Chris@0: return $xpath->addCondition('last() = 1'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * @return XPathExpr Chris@0: */ Chris@0: public function translateEmpty(XPathExpr $xpath) Chris@0: { Chris@0: return $xpath->addCondition('not(*) and not(string-length())'); Chris@0: } Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function getName() Chris@0: { Chris@0: return 'pseudo-class'; Chris@0: } Chris@0: }