<?php
require_once dirname(dirname(__DIR__)) . "/css-parser/filters/css-filter.php";
class CSSAttrFilter extends CSSFilter {
const EQUAL_SELECTOR = '=';
const NOT_EQUAL_SELECTOR = '!=';
const CONTAIN_SELECTOR = '*=';
const CONTAIN_WORD_SELECTOR = '~=';
const CONTAIN_PREFIX_SELECTOR = '|=';
const START_WITH_SELECTOR = '^=';
const END_WITH_SELECTOR = '$=';
/**
* List of operators
* @static
* @var array of strings
*/
private static $operators = array(
CSSAttrFilter::EQUAL_SELECTOR,
CSSAttrFilter::NOT_EQUAL_SELECTOR,
CSSAttrFilter::CONTAIN_SELECTOR,
CSSAttrFilter::CONTAIN_WORD_SELECTOR,
CSSAttrFilter::CONTAIN_PREFIX_SELECTOR,
CSSAttrFilter::START_WITH_SELECTOR,
CSSAttrFilter::END_WITH_SELECTOR
);
/**
* Attribute name.
* @var string
*/
private $attr_name;
/**
* Operator.
* @var string
*/
private $op;
/**
* Value.
* @var string
*/
private $value;
/**
* @param string $attr_name
* @param string $op
* @param string $value
*/
public function __construct($attr_name, $op, $value) {
$this->attr_name = $attr_name;
$this->op = $op;
$this->value = $value;
}
/**
* Gets the list of operators.
* @static
* @return array of strings
*/
public static function getOperators() {
return self::$operators;
}
/**
* Is the attribute exactly equal to a certain value? More info:
* http://api.jquery.com/attribute-equals-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isEqualSelector($node) {
return $node->hasAttribute($this->attr_name) && $node->getAttribute($this->attr_name) == $this->value;
}
/**
* Is the attribute not equal to a given value? More info:
* http://api.jquery.com/attribute-not-equal-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isNotEqualSelector($node) {
return !$node->hasAttribute($this->attr_name) || $node->getAttribute($this->attr_name) != $this->value;
}
/**
* Does the attribute contain the a given substring? More info:
* http://api.jquery.com/attribute-contains-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isContainSelector($node) {
if ($node->hasAttribute($this->attr_name)) {
$attr = $node->getAttribute($this->attr_name);
$len = strlen($this->value);
if ($len > 0) {
$pos = strpos($attr, $this->value);
return $pos !== FALSE;
}
}
return FALSE;
}
/**
* Does the attribute contain a given word, delimited by spaces? More info:
* http://api.jquery.com/attribute-contains-word-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isContainWordSelector($node) {
if ($node->hasAttribute($this->attr_name)) {
$items = explode(" ", trim($node->getAttribute($this->attr_name)));
foreach ($items as $item) {
if (preg_match("/^\w+$/", $item) && $this->value == $item) {
return TRUE;
}
}
}
return FALSE;
}
/**
* Is the attribute either equal to a given string or start with that string followed by a hyphen (-)? More info:
* http://api.jquery.com/attribute-contains-prefix-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isContainPrefixSelector($node) {
if ($node->hasAttribute($this->attr_name)) {
$attr = $node->getAttribute($this->attr_name);
$len = strlen($this->value);
if ($len > 0) {
$pos = stripos($attr, $this->value);
return $pos === 0 && (strlen($attr) <= $len || $attr[$len] == "-");
}
}
return FALSE;
}
/**
* Does the attribute start exactly with a given string? More info:
* http://api.jquery.com/attribute-starts-with-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isStartWithSelector($node) {
if ($node->hasAttribute($this->attr_name) && strlen($this->value) > 0) {
return strpos($node->getAttribute($this->attr_name), $this->value) === 0;
}
return FALSE;
}
/**
* Does the attribute end exactly with a given string?
* The comparison is case sensitive. More info:
* http://api.jquery.com/attribute-ends-with-selector/
*
* @param DOMElement $node
* @return boolean
*/
private function isEndWithSelector($node) {
if ($node->hasAttribute($this->attr_name)) {
$len = strlen($this->value);
if ($len > 0) {
$attr = $node->getAttribute($this->attr_name);
$attr_len = strlen($attr);
return $len <= $attr_len && strpos($attr, $this->value, $attr_len - $len) !== FALSE;
}
}
return FALSE;
}
private function isAttrSelector($node) {
$ret = FALSE;
if ($this->op == CSSAttrFilter::EQUAL_SELECTOR) {
$ret = $this->isEqualSelector($node);
} else
if ($this->op == CSSAttrFilter::NOT_EQUAL_SELECTOR) {
$ret = $this->isNotEqualSelector($node);
} else
if ($this->op == CSSAttrFilter::CONTAIN_SELECTOR) {
$ret = $this->isContainSelector($node);
} else
if ($this->op == CSSAttrFilter::CONTAIN_WORD_SELECTOR) {
$ret = $this->isContainWordSelector($node);
} else
if ($this->op == CSSAttrFilter::CONTAIN_PREFIX_SELECTOR) {
$ret = $this->isContainPrefixSelector($node);
} else
if ($this->op == CSSAttrFilter::START_WITH_SELECTOR) {
$ret = $this->isStartWithSelector($node);
} else
if ($this->op == CSSAttrFilter::END_WITH_SELECTOR) {
$ret = $this->isEndWithSelector($node);
}
return $ret;
}
/**
* Does the node match?
* @param DOMElement $node
* @return boolean
*/
public function match($node) {
return $ret = $this->isAttrSelector($node);
}
}
|