Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
 
3
namespace Sabberworm\CSS\Property;
4
 
5
/**
6
 * Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this
7
 * class.
8
 */
9
class Selector
10
{
11
    /**
12
     * regexp for specificity calculations
13
     *
14
     * @var string
15
     *
16
     * @internal
17
     */
18
    const NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX = '/
19
        (\.[\w]+)                   # classes
20
        |
21
        \[(\w+)                     # attributes
22
        |
23
        (\:(                        # pseudo classes
24
            link|visited|active
25
            |hover|focus
26
            |lang
27
            |target
28
            |enabled|disabled|checked|indeterminate
29
            |root
30
            |nth-child|nth-last-child|nth-of-type|nth-last-of-type
31
            |first-child|last-child|first-of-type|last-of-type
32
            |only-child|only-of-type
33
            |empty|contains
34
        ))
35
        /ix';
36
 
37
    /**
38
     * regexp for specificity calculations
39
     *
40
     * @var string
41
     *
42
     * @internal
43
     */
44
    const ELEMENTS_AND_PSEUDO_ELEMENTS_RX = '/
45
        ((^|[\s\+\>\~]+)[\w]+   # elements
46
        |
47
        \:{1,2}(                # pseudo-elements
48
            after|before|first-letter|first-line|selection
49
        ))
50
        /ix';
51
 
52
    /**
53
     * regexp for specificity calculations
54
     *
55
     * @var string
56
     *
57
     * @internal since 8.5.2
58
     */
59
    const SELECTOR_VALIDATION_RX = '/
60
        ^(
61
            (?:
62
                [a-zA-Z0-9\x{00A0}-\x{FFFF}_^$|*="\'~\[\]()\-\s\.:#+>]* # any sequence of valid unescaped characters
63
                (?:\\\\.)?                                              # a single escaped character
64
                (?:([\'"]).*?(?<!\\\\)\2)?                              # a quoted text like [id="example"]
65
            )*
66
        )$
67
        /ux';
68
 
69
    /**
70
     * @var string
71
     */
72
    private $sSelector;
73
 
74
    /**
75
     * @var int|null
76
     */
77
    private $iSpecificity;
78
 
79
    /**
80
     * @param string $sSelector
81
     *
82
     * @return bool
83
     */
84
    public static function isValid($sSelector)
85
    {
86
        return preg_match(static::SELECTOR_VALIDATION_RX, $sSelector);
87
    }
88
 
89
    /**
90
     * @param string $sSelector
91
     * @param bool $bCalculateSpecificity
92
     */
93
    public function __construct($sSelector, $bCalculateSpecificity = false)
94
    {
95
        $this->setSelector($sSelector);
96
        if ($bCalculateSpecificity) {
97
            $this->getSpecificity();
98
        }
99
    }
100
 
101
    /**
102
     * @return string
103
     */
104
    public function getSelector()
105
    {
106
        return $this->sSelector;
107
    }
108
 
109
    /**
110
     * @param string $sSelector
111
     *
112
     * @return void
113
     */
114
    public function setSelector($sSelector)
115
    {
116
        $this->sSelector = trim($sSelector);
117
        $this->iSpecificity = null;
118
    }
119
 
120
    /**
121
     * @return string
122
     */
123
    public function __toString()
124
    {
125
        return $this->getSelector();
126
    }
127
 
128
    /**
129
     * @return int
130
     */
131
    public function getSpecificity()
132
    {
133
        if ($this->iSpecificity === null) {
134
            $a = 0;
135
            /// @todo should exclude \# as well as "#"
136
            $aMatches = null;
137
            $b = substr_count($this->sSelector, '#');
138
            $c = preg_match_all(self::NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX, $this->sSelector, $aMatches);
139
            $d = preg_match_all(self::ELEMENTS_AND_PSEUDO_ELEMENTS_RX, $this->sSelector, $aMatches);
140
            $this->iSpecificity = ($a * 1000) + ($b * 100) + ($c * 10) + $d;
141
        }
142
        return $this->iSpecificity;
143
    }
144
}