Issues (146)

src/CSS/SimpleSelector.php (1 issue)

Severity
1
<?php
2
/** @file
3
 *
4
 * A simple selector.
5
 *
6
 */
7
8
namespace QueryPath\CSS;
9
10
/**
11
 * Models a simple selector.
12
 *
13
 * CSS Selectors are composed of one or more simple selectors, where
14
 * each simple selector may have any of the following components:
15
 *
16
 * - An element name (or wildcard *)
17
 * - An ID (#foo)
18
 * - One or more classes (.foo.bar)
19
 * - One or more attribute matchers ([foo=bar])
20
 * - One or more pseudo-classes (:foo)
21
 * - One or more pseudo-elements (::first)
22
 *
23
 * For performance reasons, this object has been kept as sparse as
24
 * possible.
25
 *
26
 * @since  QueryPath 3.x
27
 * @author M Butcher
28
 *
29
 */
30
class SimpleSelector
31
{
32
33
    public const ADJACENT          = 0x1;
34
    public const DIRECT_DESCENDANT = 0x2;
35
    public const ANOTHER_SELECTOR  = 0x4;
36
    public const SIBLING           = 0x8;
37
    public const ANY_DESCENDANT    = 0x10;
38
39
    public $element;
40
    public $ns;
41
    public $id;
42
    public $classes = [];
43
    public $attributes = [];
44
    public $pseudoClasses = [];
45
    public $pseudoElements = [];
46
    public $combinator;
47
48
    /**
49
     * @param $code
50
     * @return string
51
     */
52
    public static function attributeOperator($code): string
53
    {
54
        switch ($code) {
55
            case EventHandler::CONTAINS_WITH_SPACE:
56
                return '~=';
57
            case EventHandler::CONTAINS_WITH_HYPHEN:
58
                return '|=';
59
            case EventHandler::CONTAINS_IN_STRING:
60
                return '*=';
61
            case EventHandler::BEGINS_WITH:
62
                return '^=';
63
            case EventHandler::ENDS_WITH:
64
                return '$=';
65
            default:
66
                return '=';
67
        }
68
    }
69
70
    /**
71
     * @param $code
72
     * @return string
73
     */
74
    public static function combinatorOperator($code): string
75
    {
76
        switch ($code) {
77
            case self::ADJACENT:
78
                return '+';
79
            case self::DIRECT_DESCENDANT:
80
                return '>';
81
            case self::SIBLING:
82
                return '~';
83
            case self::ANOTHER_SELECTOR:
84
                return ', ';
85
            case self::ANY_DESCENDANT:
86
                return '   ';
87
            default:
88
                return '';
89
                break;
0 ignored issues
show
break is not strictly necessary here and could be removed.

The break statement is not necessary if it is preceded for example by a return statement:

switch ($x) {
    case 1:
        return 'foo';
        break; // This break is not necessary and can be left off.
}

If you would like to keep this construct to be consistent with other case statements, you can safely mark this issue as a false-positive.

Loading history...
90
        }
91
    }
92
93
    public function __construct()
94
    {
95
    }
96
97
    /**
98
     * @return bool
99
     */
100
    public function notEmpty(): bool
101
    {
102
        return !empty($this->element)
103
            && !empty($this->id)
104
            && !empty($this->classes)
105
            && !empty($this->combinator)
106
            && !empty($this->attributes)
107
            && !empty($this->pseudoClasses)
108
            && !empty($this->pseudoElements);
109
    }
110
111
    public function __toString()
112
    {
113
        $buffer = [];
114
        try {
115
116
            if (!empty($this->ns)) {
117
                $buffer[] = $this->ns;
118
                $buffer[] = '|';
119
            }
120
            if (!empty($this->element)) {
121
                $buffer[] = $this->element;
122
            }
123
            if (!empty($this->id)) {
124
                $buffer[] = '#' . $this->id;
125
            }
126
            if (!empty($this->attributes)) {
127
                foreach ($this->attributes as $attr) {
128
                    $buffer[] = '[';
129
                    if (!empty($attr['ns'])) {
130
                        $buffer[] = $attr['ns'] . '|';
131
                    }
132
                    $buffer[] = $attr['name'];
133
                    if (!empty($attr['value'])) {
134
                        $buffer[] = self::attributeOperator($attr['op']);
135
                        $buffer[] = $attr['value'];
136
                    }
137
                    $buffer[] = ']';
138
                }
139
            }
140
            if (!empty($this->pseudoClasses)) {
141
                foreach ($this->pseudoClasses as $ps) {
142
                    $buffer[] = ':' . $ps['name'];
143
                    if (isset($ps['value'])) {
144
                        $buffer[] = '(' . $ps['value'] . ')';
145
                    }
146
                }
147
            }
148
            foreach ($this->pseudoElements as $pe) {
149
                $buffer[] = '::' . $pe;
150
            }
151
152
            if (!empty($this->combinator)) {
153
                $buffer[] = self::combinatorOperator($this->combinator);
154
            }
155
156
        } catch (\Exception $e) {
157
            return $e->getMessage();
158
        }
159
160
        return implode('', $buffer);
161
    }
162
163
}
164