View source
<?php
class CSSCompression_Selectors {
private $Control;
private $token = '';
private $ridattr = "";
private $rclassattr = "";
private $options = array();
private $rmark = "/(?<!\\\\)(#|\\.|=)/";
private $ridclassend = "/(?<!\\\\)[:#>~\\[\\+\\*\\. ]/";
private $rquote = "/(?<!\\\\)(\"|')?\\]/";
private $rescapedspace = "/\\\\ /";
private $rcomma = "/(?<!\\\\),/";
private $rspace = "/(?<!\\\\)\\s/";
private $rid = "/(?<!\\\\)#/";
private $rpseudo = "/:first-(letter|line)(,|\$)/i";
public function __construct(CSSCompression_Control $control) {
$this->Control = $control;
$this->token = CSSCompression::TOKEN;
$this->ridattr = "/\\[id={$this->token}(.*?){$this->token}\\]/";
$this->rclassattr = "/\\[class={$this->token}(.*?){$this->token}\\]/";
$this->options =& $control->Option->options;
}
public function selectors(&$selectors = array()) {
foreach ($selectors as &$selector) {
if (strpos($selector, $this->token) === 0) {
continue;
}
$selector = $this
->parse($selector);
if ($this->options['attr2selector']) {
$selector = $this
->idAttribute($selector);
$selector = $this
->classAttribute($selector);
}
if ($this->options['strict-id']) {
$selector = $this
->strictid($selector);
}
$selector = $this
->repeats($selector);
if ($this->options['pseudo-space']) {
$selector = $this
->pseudoSpace($selector);
}
}
return $selectors;
}
private function parse($selector) {
$clean = '';
$substr = '';
$pos = 0;
while (preg_match($this->rmark, $selector, $match, PREG_OFFSET_CAPTURE, $pos)) {
$substr = substr($selector, $pos, $match[0][1] + 1 - $pos);
$clean .= $this->options['lowercase-selectors'] ? strtolower($substr) : $substr;
$pos = $match[0][1] + strlen($match[1][0]);
if ($match[1][0] == '#' || $match[1][0] == '.') {
if (preg_match($this->ridclassend, $selector, $m, PREG_OFFSET_CAPTURE, $pos)) {
$clean .= substr($selector, $pos, $m[0][1] - $pos);
$pos = $m[0][1];
}
else {
$clean .= substr($selector, $pos);
$pos = strlen($selector);
break;
}
}
else {
if (preg_match($this->rquote, $selector, $m, PREG_OFFSET_CAPTURE, $pos)) {
if ($selector[$pos] == "\"" || $selector[$pos] == "'") {
$pos++;
}
$clean .= $this->token . substr($selector, $pos, $m[0][1] - $pos) . $this->token . ']';
$pos = $m[0][1] + strlen($m[0][0]);
}
else {
$clean .= substr($selector, $pos);
$pos = strlen($selector);
break;
}
}
}
return $clean . ($this->options['lowercase-selectors'] ? strtolower(substr($selector, $pos)) : substr($selector, $pos));
}
private function idAttribute($selector) {
$pos = 0;
while (preg_match($this->ridattr, $selector, $match, PREG_OFFSET_CAPTURE, $pos)) {
if (strpos($match[1][0], ' ') !== false) {
$pos = $match[0][1] + strlen($match[0][0]);
continue;
}
$selector = substr_replace($selector, '#' . $match[1][0], $match[0][1], strlen($match[0][0]));
$pos = $match[0][1] + strlen($match[1][0]) + 1;
}
return $selector;
}
private function classAttribute($selector) {
$pos = 0;
while (preg_match($this->rclassattr, $selector, $match, PREG_OFFSET_CAPTURE, $pos)) {
if (strpos($match[1][0], '.') !== false) {
$pos = $match[0][1] + strlen($match[0][0]);
continue;
}
$replace = '.' . preg_replace($this->rescapedspace, ".", $match[1][0]);
$selector = substr_replace($selector, $replace, $match[0][1], strlen($match[0][0]));
$pos = $match[0][1] + strlen($match[1][0]) + 1;
}
return $selector;
}
private function strictid($selector) {
$parts = preg_split($this->rcomma, $selector);
foreach ($parts as &$s) {
if (preg_match($this->rid, $s)) {
$p = preg_split($this->rid, $s);
$s = '#' . array_pop($p);
}
}
return implode(',', $parts);
}
private function repeats($selector) {
$parts = preg_split($this->rcomma, $selector);
$parts = array_flip($parts);
$parts = array_flip($parts);
return implode(',', $parts);
}
private function pseudoSpace($selector) {
return preg_replace($this->rpseudo, ":first-\$1 \$2", $selector);
}
public function access($method, $args) {
if (method_exists($this, $method)) {
if ($method == 'selectors') {
return $this
->selectors($args[0]);
}
else {
return call_user_func_array(array(
$this,
$method,
), $args);
}
}
else {
throw new CSSCompression_Exception("Unknown method in Selectors Class - " . $method);
}
}
}