protected function parseSelector($query)
{
// clean spaces
// TODO include this inside parsing ?
$query = trim(preg_replace('@\\s+@', ' ', preg_replace('@\\s*(>|\\+|~)\\s*@', '\\1', $query)));
$queries = array(array());
if (!$query) {
return $queries;
}
$return =& $queries[0];
$specialChars = array('>', ' ');
// $specialCharsMapping = array('/' => '>');
$specialCharsMapping = array();
$strlen = mb_strlen($query);
$classChars = array('.', '-');
$pseudoChars = array('-');
$tagChars = array('*', '|', '-');
// split multibyte string
// http://code.google.com/p/phpquery/issues/detail?id=76
$_query = array();
for ($i = 0; $i < $strlen; ++$i) {
$_query[] = mb_substr($query, $i, 1);
}
$query = $_query;
// it works, but i dont like it...
$i = 0;
while ($i < $strlen) {
$c = $query[$i];
$tmp = '';
// TAG
if ($this->isChar($c) || in_array($c, $tagChars)) {
while (isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $tagChars))) {
$tmp .= $query[$i];
++$i;
}
$return[] = $tmp;
// IDs
} elseif ($c == '#') {
++$i;
while (isset($query[$i]) && ($this->isChar($query[$i]) || $query[$i] == '-')) {
$tmp .= $query[$i];
++$i;
}
$return[] = '#' . $tmp;
// SPECIAL CHARS
} elseif (in_array($c, $specialChars)) {
$return[] = $c;
++$i;
// MAPPED SPECIAL MULTICHARS
// } else if ( $c.$query[$i+1] == '//') {
// $return[] = ' ';
// $i = $i+2;
// MAPPED SPECIAL CHARS
} elseif (isset($specialCharsMapping[$c])) {
$return[] = $specialCharsMapping[$c];
++$i;
// COMMA
} elseif ($c == ',') {
$queries[] = array();
$return =& $queries[count($queries) - 1];
++$i;
while (isset($query[$i]) && $query[$i] == ' ') {
$i++;
}
// CLASSES
} elseif ($c == '.') {
while (isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars))) {
$tmp .= $query[$i];
++$i;
}
$return[] = $tmp;
// ~ General Sibling Selector
} elseif ($c == '~') {
$spaceAllowed = true;
$tmp .= $query[$i++];
while (isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars) || $query[$i] == '*' || $query[$i] == ' ' && $spaceAllowed)) {
if ($query[$i] != ' ') {
$spaceAllowed = false;
}
$tmp .= $query[$i];
++$i;
}
$return[] = $tmp;
// + Adjacent sibling selectors
} elseif ($c == '+') {
$spaceAllowed = true;
$tmp .= $query[$i++];
while (isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $classChars) || $query[$i] == '*' || $spaceAllowed && $query[$i] == ' ')) {
if ($query[$i] != ' ') {
$spaceAllowed = false;
}
$tmp .= $query[$i];
++$i;
}
$return[] = $tmp;
// ATTRS
} elseif ($c == '[') {
$stack = 1;
$tmp .= $c;
while (isset($query[++$i])) {
$tmp .= $query[$i];
if ($query[$i] == '[') {
++$stack;
} elseif ($query[$i] == ']') {
--$stack;
if (!$stack) {
break;
}
}
}
$return[] = $tmp;
++$i;
// PSEUDO CLASSES
} elseif ($c == ':') {
$stack = 1;
$tmp .= $query[$i++];
while (isset($query[$i]) && ($this->isChar($query[$i]) || in_array($query[$i], $pseudoChars))) {
$tmp .= $query[$i];
++$i;
}
// with arguments ?
if (isset($query[$i]) && $query[$i] == '(') {
$tmp .= $query[$i];
$stack = 1;
while (isset($query[++$i])) {
$tmp .= $query[$i];
if ($query[$i] == '(') {
++$stack;
} elseif ($query[$i] == ')') {
--$stack;
if (!$stack) {
break;
}
}
}
$return[] = $tmp;
++$i;
} else {
$return[] = $tmp;
}
} else {
++$i;
}
}
foreach ($queries as $k => $q) {
if (isset($q[0])) {
if (isset($q[0][0]) && $q[0][0] == ':') {
array_unshift($queries[$k], '*');
}
if ($q[0] != '>') {
array_unshift($queries[$k], ' ');
}
}
}
return $queries;
}