pQuery\HtmlSelector::parse_conditions PHP Метод

parse_conditions() защищенный Метод

Get query conditions (tag, attribute and filter conditions)
См. также: DomNode::match()
protected parse_conditions ( ) : array
Результат array False on failure
    protected function parse_conditions()
    {
        $p =& $this->parser;
        $tok = $p->token;
        if ($tok === CSSQueryTokenizer::TOK_NULL) {
            $this->error('Invalid search pattern(1): Empty string!');
            return false;
        }
        $conditions_all = array();
        //Tags
        while ($tok !== CSSQueryTokenizer::TOK_NULL) {
            $conditions = array('tags' => array(), 'attributes' => array());
            if ($tok === CSSQueryTokenizer::TOK_ALL) {
                $tok = $p->next();
                if ($tok === CSSQueryTokenizer::TOK_PIPE && ($tok = $p->next()) && $tok !== CSSQueryTokenizer::TOK_ALL) {
                    if (($tag = $this->parse_getIdentifier()) === false) {
                        return false;
                    }
                    $conditions['tags'][] = array('tag' => $tag, 'compare' => 'name');
                    $tok = $p->next_no_whitespace();
                } else {
                    $conditions['tags'][''] = array('tag' => '', 'match' => false);
                    if ($tok === CSSQueryTokenizer::TOK_ALL) {
                        $tok = $p->next_no_whitespace();
                    }
                }
            } elseif ($tok === CSSQueryTokenizer::TOK_PIPE) {
                $tok = $p->next();
                if ($tok === CSSQueryTokenizer::TOK_ALL) {
                    $conditions['tags'][] = array('tag' => '', 'compare' => 'namespace');
                } elseif (($tag = $this->parse_getIdentifier()) !== false) {
                    $conditions['tags'][] = array('tag' => $tag, 'compare' => 'total');
                } else {
                    return false;
                }
                $tok = $p->next_no_whitespace();
            } elseif ($tok === CSSQueryTokenizer::TOK_BRACE_OPEN) {
                $tok = $p->next_no_whitespace();
                $last_mode = 'or';
                while (true) {
                    $match = true;
                    $compare = 'total';
                    if ($tok === CSSQueryTokenizer::TOK_NOT) {
                        $match = false;
                        $tok = $p->next_no_whitespace();
                    }
                    if ($tok === CSSQueryTokenizer::TOK_ALL) {
                        $tok = $p->next();
                        if ($tok === CSSQueryTokenizer::TOK_PIPE) {
                            $this->next();
                            $compare = 'name';
                            if (($tag = $this->parse_getIdentifier()) === false) {
                                return false;
                            }
                        }
                    } elseif ($tok === CSSQueryTokenizer::TOK_PIPE) {
                        $tok = $p->next();
                        if ($tok === CSSQueryTokenizer::TOK_ALL) {
                            $tag = '';
                            $compare = 'namespace';
                        } elseif (($tag = $this->parse_getIdentifier()) === false) {
                            return false;
                        }
                        $tok = $p->next_no_whitespace();
                    } else {
                        if (($tag = $this->parse_getIdentifier()) === false) {
                            return false;
                        }
                        $tok = $p->next();
                        if ($tok === CSSQueryTokenizer::TOK_PIPE) {
                            $tok = $p->next();
                            if ($tok === CSSQueryTokenizer::TOK_ALL) {
                                $compare = 'namespace';
                            } elseif (($tag_name = $this->parse_getIdentifier()) !== false) {
                                $tag = $tag . ':' . $tag_name;
                            } else {
                                return false;
                            }
                            $tok = $p->next_no_whitespace();
                        }
                    }
                    if ($tok === CSSQueryTokenizer::TOK_WHITESPACE) {
                        $tok = $p->next_no_whitespace();
                    }
                    $conditions['tags'][] = array('tag' => $tag, 'match' => $match, 'operator' => $last_mode, 'compare' => $compare);
                    switch ($tok) {
                        case CSSQueryTokenizer::TOK_COMMA:
                            $tok = $p->next_no_whitespace();
                            $last_mode = 'or';
                            continue 2;
                        case CSSQueryTokenizer::TOK_PLUS:
                            $tok = $p->next_no_whitespace();
                            $last_mode = 'and';
                            continue 2;
                        case CSSQueryTokenizer::TOK_BRACE_CLOSE:
                            $tok = $p->next();
                            break 2;
                        default:
                            $this->error('Expected closing brace or comma at pos %pos%!');
                            return false;
                    }
                }
            } elseif (($tag = $this->parse_getIdentifier(false)) !== false) {
                $tok = $p->next();
                if ($tok === CSSQueryTokenizer::TOK_PIPE) {
                    $tok = $p->next();
                    if ($tok === CSSQueryTokenizer::TOK_ALL) {
                        $conditions['tags'][] = array('tag' => $tag, 'compare' => 'namespace');
                    } elseif (($tag_name = $this->parse_getIdentifier()) !== false) {
                        $tag = $tag . ':' . $tag_name;
                        $conditions['tags'][] = array('tag' => $tag, 'match' => true);
                    } else {
                        return false;
                    }
                    $tok = $p->next();
                } elseif ($tag === 'text' && $tok === CSSQueryTokenizer::TOK_BRACE_OPEN) {
                    $pos = $p->getPos();
                    $tok = $p->next();
                    if ($tok === CSSQueryTokenizer::TOK_BRACE_CLOSE) {
                        $conditions['tags'][] = array('tag' => '~text~', 'match' => true);
                        $p->next();
                    } else {
                        $p->setPos($pos);
                    }
                } else {
                    $conditions['tags'][] = array('tag' => $tag, 'match' => true);
                }
            } else {
                unset($conditions['tags']);
            }
            //Class
            $last_mode = 'or';
            if ($tok === CSSQueryTokenizer::TOK_CLASS) {
                $p->next();
                if (($class = $this->parse_getIdentifier()) === false) {
                    return false;
                }
                $conditions['attributes'][] = array('attribute' => 'class', 'operator_value' => 'contains_word', 'value' => $class, 'operator_result' => $last_mode);
                $last_mode = 'and';
                $tok = $p->next();
            }
            //ID
            if ($tok === CSSQueryTokenizer::TOK_ID) {
                $p->next();
                if (($id = $this->parse_getIdentifier()) === false) {
                    return false;
                }
                $conditions['attributes'][] = array('attribute' => 'id', 'operator_value' => 'equals', 'value' => $id, 'operator_result' => $last_mode);
                $last_mode = 'and';
                $tok = $p->next();
            }
            //Attributes
            if ($tok === CSSQueryTokenizer::TOK_BRACKET_OPEN) {
                $tok = $p->next_no_whitespace();
                while (true) {
                    $match = true;
                    $compare = 'total';
                    if ($tok === CSSQueryTokenizer::TOK_NOT) {
                        $match = false;
                        $tok = $p->next_no_whitespace();
                    }
                    if ($tok === CSSQueryTokenizer::TOK_ALL) {
                        $tok = $p->next();
                        if ($tok === CSSQueryTokenizer::TOK_PIPE) {
                            $tok = $p->next();
                            if (($attribute = $this->parse_getIdentifier()) === false) {
                                return false;
                            }
                            $compare = 'name';
                            $tok = $p->next();
                        } else {
                            $this->error('Expected pipe at pos %pos%!');
                            return false;
                        }
                    } elseif ($tok === CSSQueryTokenizer::TOK_PIPE) {
                        $tok = $p->next();
                        if (($tag = $this->parse_getIdentifier()) === false) {
                            return false;
                        }
                        $tok = $p->next_no_whitespace();
                    } elseif (($attribute = $this->parse_getIdentifier()) !== false) {
                        $tok = $p->next();
                        if ($tok === CSSQueryTokenizer::TOK_PIPE) {
                            $tok = $p->next();
                            if (($attribute_name = $this->parse_getIdentifier()) !== false) {
                                $attribute = $attribute . ':' . $attribute_name;
                            } else {
                                return false;
                            }
                            $tok = $p->next();
                        }
                    } else {
                        return false;
                    }
                    if ($tok === CSSQueryTokenizer::TOK_WHITESPACE) {
                        $tok = $p->next_no_whitespace();
                    }
                    $operator_value = '';
                    $val = '';
                    switch ($tok) {
                        case CSSQueryTokenizer::TOK_COMPARE_PREFIX:
                        case CSSQueryTokenizer::TOK_COMPARE_CONTAINS:
                        case CSSQueryTokenizer::TOK_COMPARE_CONTAINS_WORD:
                        case CSSQueryTokenizer::TOK_COMPARE_ENDS:
                        case CSSQueryTokenizer::TOK_COMPARE_EQUALS:
                        case CSSQueryTokenizer::TOK_COMPARE_NOT_EQUAL:
                        case CSSQueryTokenizer::TOK_COMPARE_REGEX:
                        case CSSQueryTokenizer::TOK_COMPARE_STARTS:
                        case CSSQueryTokenizer::TOK_COMPARE_BIGGER_THAN:
                        case CSSQueryTokenizer::TOK_COMPARE_SMALLER_THAN:
                            $operator_value = $p->getTokenString($tok === CSSQueryTokenizer::TOK_COMPARE_EQUALS ? 0 : -1);
                            $p->next_no_whitespace();
                            if (($val = $this->parse_getIdentifier()) === false) {
                                return false;
                            }
                            $tok = $p->next_no_whitespace();
                            break;
                    }
                    if ($operator_value && $val) {
                        $conditions['attributes'][] = array('attribute' => $attribute, 'operator_value' => $operator_value, 'value' => $val, 'match' => $match, 'operator_result' => $last_mode, 'compare' => $compare);
                    } else {
                        $conditions['attributes'][] = array('attribute' => $attribute, 'value' => $match, 'operator_result' => $last_mode, 'compare' => $compare);
                    }
                    switch ($tok) {
                        case CSSQueryTokenizer::TOK_COMMA:
                            $tok = $p->next_no_whitespace();
                            $last_mode = 'or';
                            continue 2;
                        case CSSQueryTokenizer::TOK_PLUS:
                            $tok = $p->next_no_whitespace();
                            $last_mode = 'and';
                            continue 2;
                        case CSSQueryTokenizer::TOK_BRACKET_CLOSE:
                            $tok = $p->next();
                            break 2;
                        default:
                            $this->error('Expected closing bracket or comma at pos %pos%!');
                            return false;
                    }
                }
            }
            if (count($conditions['attributes']) < 1) {
                unset($conditions['attributes']);
            }
            while ($tok === CSSQueryTokenizer::TOK_COLON) {
                if (count($conditions) < 1) {
                    $conditions['tags'] = array(array('tag' => '', 'match' => false));
                }
                $tok = $p->next();
                if (($filter = $this->parse_getIdentifier()) === false) {
                    return false;
                }
                if (($tok = $p->next()) === CSSQueryTokenizer::TOK_BRACE_OPEN) {
                    $start = $p->pos;
                    $count = 1;
                    while (($tok = $p->next()) !== CSSQueryTokenizer::TOK_NULL && !($tok === CSSQueryTokenizer::TOK_BRACE_CLOSE && --$count === 0)) {
                        if ($tok === CSSQueryTokenizer::TOK_BRACE_OPEN) {
                            ++$count;
                        }
                    }
                    if ($tok !== CSSQueryTokenizer::TOK_BRACE_CLOSE) {
                        $this->error('Expected closing brace at pos %pos%!');
                        return false;
                    }
                    $len = $p->pos - 1 - $start;
                    $params = $len > 0 ? substr($p->doc, $start + 1, $len) : '';
                    $tok = $p->next();
                } else {
                    $params = '';
                }
                $conditions['filters'][] = array('filter' => $filter, 'params' => $params);
            }
            if (count($conditions) < 1) {
                $this->error('Invalid search pattern(2): No conditions found!');
                return false;
            }
            $conditions_all[] = $conditions;
            if ($tok === CSSQueryTokenizer::TOK_WHITESPACE) {
                $tok = $p->next_no_whitespace();
            }
            if ($tok === CSSQueryTokenizer::TOK_COMMA) {
                $tok = $p->next_no_whitespace();
                continue;
            } else {
                break;
            }
        }
        return $conditions_all;
    }