Completed
Push — master ( a35b70...1dd31e )
by Tim
13:48
created

Specificity::fromSelector()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 35
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

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