Specificity::getValues()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace voku\CssToInlineStyles;
6
7
/**
8
 * CSS to Inline Styles Specificity class.
9
 *
10
 * Compare specificity based on the CSS3 spec.
11
 *
12
 * @see http://www.w3.org/TR/selectors/#specificity
13
 */
14
class Specificity
15
{
16
    /**
17
     * The number of ID selectors in the selector
18
     *
19
     * @var int
20
     */
21
    private $a;
22
23
    /**
24
     * The number of class selectors, attributes selectors, and pseudo-classes in the selector
25
     *
26
     * @var int
27
     */
28
    private $b;
29
30
    /**
31
     * The number of type selectors and pseudo-elements in the selector
32
     *
33
     * @var int
34
     */
35
    private $c;
36
37
    /**
38
     * @param int $a The number of ID selectors in the selector
39
     * @param int $b The number of class selectors, attributes selectors, and pseudo-classes in the selector
40
     * @param int $c The number of type selectors and pseudo-elements in the selector
41
     */
42 52
    public function __construct($a = 0, $b = 0, $c = 0)
43
    {
44 52
        $this->a = $a;
45 52
        $this->b = $b;
46 52
        $this->c = $c;
47 52
    }
48
49
    /**
50
     * Increase the current specificity by adding the three values
51
     *
52
     * @param int $a The number of ID selectors in the selector
53
     * @param int $b The number of class selectors, attributes selectors, and pseudo-classes in the selector
54
     * @param int $c The number of type selectors and pseudo-elements in the selector
55
     *
56
     * @return void
57
     */
58 1
    public function increase($a, $b, $c)
59
    {
60 1
        $this->a += $a;
61 1
        $this->b += $b;
62 1
        $this->c += $c;
63 1
    }
64
65
    /**
66
     * Get the specificity values as an array
67
     *
68
     * @return array
69
     */
70 10
    public function getValues(): array
71
    {
72 10
        return [$this->a, $this->b, $this->c];
73
    }
74
75
    /**
76
     * Calculate the specificity based on a CSS Selector string,
77
     * Based on the patterns from premailer/css_parser by Alex Dunae
78
     *
79
     * @see https://github.com/premailer/css_parser/blob/master/lib/css_parser/regexps.rb
80
     *
81
     * @param string $selector
82
     *
83
     * @return static
84
     */
85 50
    public static function fromSelector(string $selector)
86
    {
87 50
        $pattern_a = "  \#";
88 50
        $pattern_b = "  (\.[\w]+)                     # classes
89
                        |
90
                        \[(\w+)                       # attributes
91
                        |
92
                        (\:(                          # pseudo classes
93
                          link|visited|active
94
                          |hover|focus
95
                          |lang
96
                          |target
97
                          |enabled|disabled|checked|indeterminate
98
                          |root
99
                          |nth-child|nth-last-child|nth-of-type|nth-last-of-type
100
                          |first-child|last-child|first-of-type|last-of-type
101
                          |only-child|only-of-type
102
                          |empty|contains
103
                        ))";
104
105 50
        $pattern_c = "  ((^|[\s\+\>\~]+)[\w]+       # elements
106
                        |
107
                        \:{1,2}(                    # pseudo-elements
108
                          after|before
109
                          |first-letter|first-line
110
                          |selection
111
                        )
112
                      )";
113
114 50
        return new static(
115 50
            (int)\preg_match_all("/{$pattern_a}/ix", $selector, $matches),
116 50
            (int)\preg_match_all("/{$pattern_b}/ix", $selector, $matches),
117 50
            (int)\preg_match_all("/{$pattern_c}/ix", $selector, $matches)
118
        );
119
    }
120
121
    /**
122
     * Returns <0 when $specificity is greater, 0 when equal, >0 when smaller
123
     *
124
     * @param Specificity $specificity
125
     *
126
     * @return int
127
     */
128 34
    public function compareTo(self $specificity): int
129
    {
130 34
        if ($this->a !== $specificity->a) {
131 15
            return $this->a - $specificity->a;
132
        }
133
134 30
        if ($this->b !== $specificity->b) {
135 20
            return $this->b - $specificity->b;
136
        }
137
138 25
        return $this->c - $specificity->c;
139
    }
140
}
141