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
12namespace Symfony\Component\CssSelector;
13
14use Symfony\Component\CssSelector\Parser\Shortcut\ClassParser;
15use Symfony\Component\CssSelector\Parser\Shortcut\ElementParser;
16use Symfony\Component\CssSelector\Parser\Shortcut\EmptyStringParser;
17use Symfony\Component\CssSelector\Parser\Shortcut\HashParser;
18use Symfony\Component\CssSelector\XPath\Extension\HtmlExtension;
19use Symfony\Component\CssSelector\XPath\Translator;
20
21/**
22 * CssSelectorConverter is the main entry point of the component and can convert CSS
23 * selectors to XPath expressions.
24 *
25 * @author Christophe Coevoet <stof@notk.org>
26 */
27class CssSelectorConverter
28{
29    private $translator;
30    private $cache;
31
32    private static $xmlCache = [];
33    private static $htmlCache = [];
34
35    /**
36     * @param bool $html Whether HTML support should be enabled. Disable it for XML documents
37     */
38    public function __construct(bool $html = true)
39    {
40        $this->translator = new Translator();
41
42        if ($html) {
43            $this->translator->registerExtension(new HtmlExtension($this->translator));
44            $this->cache = &self::$htmlCache;
45        } else {
46            $this->cache = &self::$xmlCache;
47        }
48
49        $this->translator
50            ->registerParserShortcut(new EmptyStringParser())
51            ->registerParserShortcut(new ElementParser())
52            ->registerParserShortcut(new ClassParser())
53            ->registerParserShortcut(new HashParser())
54        ;
55    }
56
57    /**
58     * Translates a CSS expression to its XPath equivalent.
59     *
60     * Optionally, a prefix can be added to the resulting XPath
61     * expression with the $prefix parameter.
62     *
63     * @return string
64     */
65    public function toXPath(string $cssExpr, string $prefix = 'descendant-or-self::')
66    {
67        return $this->cache[$prefix][$cssExpr] ?? $this->cache[$prefix][$cssExpr] = $this->translator->cssToXPath($cssExpr, $prefix);
68    }
69}
70