<?php
namespace Sabberworm\CSS\Property;
/**
< * Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this class.
> * Class representing a single CSS selector. Selectors have to be split by the comma prior to being passed into this
> * class.
> */
> class Selector
> {
> /**
> * regexp for specificity calculations
> *
> * @var string
*/
< class Selector {
<
< //Regexes for specificity calculations
const NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX = '/
(\.[\w]+) # classes
|
\[(\w+) # attributes
|
(\:( # pseudo classes
link|visited|active
|hover|focus
|lang
|target
|enabled|disabled|checked|indeterminate
|root
|nth-child|nth-last-child|nth-of-type|nth-last-of-type
|first-child|last-child|first-of-type|last-of-type
|only-child|only-of-type
|empty|contains
))
/ix';
> /**
const ELEMENTS_AND_PSEUDO_ELEMENTS_RX = '/
> * regexp for specificity calculations
((^|[\s\+\>\~]+)[\w]+ # elements
> *
|
> * @var string
\:{1,2}( # pseudo-elements
> */
after|before|first-letter|first-line|selection
))
/ix';
> /**
private $sSelector;
> * regexp for specificity calculations
private $iSpecificity;
> *
> * @var string
public function __construct($sSelector, $bCalculateSpecificity = false) {
> */
$this->setSelector($sSelector);
> const SELECTOR_VALIDATION_RX = '/
if ($bCalculateSpecificity) {
> ^(
$this->getSpecificity();
> (?:
}
> [a-zA-Z0-9\x{00A0}-\x{FFFF}_^$|*="\'~\[\]()\-\s\.:#+>]* # any sequence of valid unescaped characters
}
> (?:\\\\.)? # a single escaped character
> (?:([\'"]).*?(?<!\\\\)\2)? # a quoted text like [id="example"]
public function getSelector() {
> )*
return $this->sSelector;
> )$
}
> /ux';
>
public function setSelector($sSelector) {
> /**
$this->sSelector = trim($sSelector);
> * @var string
$this->iSpecificity = null;
> */
}
>
> /**
public function __toString() {
> * @var int|null
return $this->getSelector();
> */
< public function __construct($sSelector, $bCalculateSpecificity = false) {
> /**
> * @param string $sSelector
> *
> * @return bool
> */
> public static function isValid($sSelector)
> {
> return preg_match(static::SELECTOR_VALIDATION_RX, $sSelector);
> }
>
> /**
> * @param string $sSelector
> * @param bool $bCalculateSpecificity
> */
> public function __construct($sSelector, $bCalculateSpecificity = false)
> {
< public function getSelector() {
> /**
> * @return string
> */
> public function getSelector()
> {
< public function setSelector($sSelector) {
> /**
> * @param string $sSelector
> *
> * @return void
> */
> public function setSelector($sSelector)
> {
< public function __toString() {
> /**
> * @return string
> */
> public function __toString()
> {
< public function getSpecificity() {
> /**
> * @return int
> */
> public function getSpecificity()
> {
/// @todo should exclude \# as well as "#"
$aMatches = null;
$b = substr_count($this->sSelector, '#');
$c = preg_match_all(self::NON_ID_ATTRIBUTES_AND_PSEUDO_CLASSES_RX, $this->sSelector, $aMatches);
$d = preg_match_all(self::ELEMENTS_AND_PSEUDO_ELEMENTS_RX, $this->sSelector, $aMatches);
$this->iSpecificity = ($a * 1000) + ($b * 100) + ($c * 10) + $d;
}
return $this->iSpecificity;
}
<
}