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\XPath;
13
14/**
15 * XPath expression translator interface.
16 *
17 * This component is a port of the Python cssselect library,
18 * which is copyright Ian Bicking, @see https://github.com/SimonSapin/cssselect.
19 *
20 * @author Jean-François Simon <jeanfrancois.simon@sensiolabs.com>
21 *
22 * @internal
23 */
24class XPathExpr
25{
26    private $path;
27    private $element;
28    private $condition;
29
30    public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false)
31    {
32        $this->path = $path;
33        $this->element = $element;
34        $this->condition = $condition;
35
36        if ($starPrefix) {
37            $this->addStarPrefix();
38        }
39    }
40
41    public function getElement(): string
42    {
43        return $this->element;
44    }
45
46    /**
47     * @return $this
48     */
49    public function addCondition(string $condition): self
50    {
51        $this->condition = $this->condition ? sprintf('(%s) and (%s)', $this->condition, $condition) : $condition;
52
53        return $this;
54    }
55
56    public function getCondition(): string
57    {
58        return $this->condition;
59    }
60
61    /**
62     * @return $this
63     */
64    public function addNameTest(): self
65    {
66        if ('*' !== $this->element) {
67            $this->addCondition('name() = '.Translator::getXpathLiteral($this->element));
68            $this->element = '*';
69        }
70
71        return $this;
72    }
73
74    /**
75     * @return $this
76     */
77    public function addStarPrefix(): self
78    {
79        $this->path .= '*/';
80
81        return $this;
82    }
83
84    /**
85     * Joins another XPathExpr with a combiner.
86     *
87     * @return $this
88     */
89    public function join(string $combiner, self $expr): self
90    {
91        $path = $this->__toString().$combiner;
92
93        if ('*/' !== $expr->path) {
94            $path .= $expr->path;
95        }
96
97        $this->path = $path;
98        $this->element = $expr->element;
99        $this->condition = $expr->condition;
100
101        return $this;
102    }
103
104    public function __toString(): string
105    {
106        $path = $this->path.$this->element;
107        $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']';
108
109        return $path.$condition;
110    }
111}
112