PHPHtmlParser\Selector::seek PHP Method

seek() protected method

Attempts to find all children that match the rule given.
protected seek ( array $nodes, array $rule, array $options ) : array
$nodes array
$rule array
$options array
return array
    protected function seek(array $nodes, array $rule, array $options)
    {
        // XPath index
        if (count($rule['tag']) > 0 && count($rule['key']) > 0 && is_numeric($rule['key'])) {
            $count = 0;
            /** @var AbstractNode $node */
            foreach ($nodes as $node) {
                if ($rule['tag'] == '*' || $rule['tag'] == $node->getTag()->name()) {
                    ++$count;
                    if ($count == $rule['key']) {
                        // found the node we wanted
                        return [$node];
                    }
                }
            }
            return [];
        }
        $options = $this->flattenOptions($options);
        $return = [];
        /** @var InnerNode $node */
        foreach ($nodes as $node) {
            // check if we are a leaf
            if ($node instanceof LeafNode || !$node->hasChildren()) {
                continue;
            }
            $children = [];
            $child = $node->firstChild();
            while (!is_null($child)) {
                // wild card, grab all
                if ($rule['tag'] == '*' && is_null($rule['key'])) {
                    $return[] = $child;
                    try {
                        $child = $node->nextChild($child->id());
                    } catch (ChildNotFoundException $e) {
                        // no more children
                        $child = null;
                    }
                    continue;
                }
                $pass = true;
                // check tag
                if (!empty($rule['tag']) && $rule['tag'] != $child->getTag()->name() && $rule['tag'] != '*') {
                    // child failed tag check
                    $pass = false;
                }
                // check key
                if ($pass && !is_null($rule['key'])) {
                    if ($rule['noKey']) {
                        if (!is_null($child->getAttribute($rule['key']))) {
                            $pass = false;
                        }
                    } else {
                        if ($rule['key'] != 'plaintext' && is_null($child->getAttribute($rule['key']))) {
                            $pass = false;
                        }
                    }
                }
                // compare values
                if ($pass && !is_null($rule['key']) && !is_null($rule['value']) && $rule['value'] != '*') {
                    if ($rule['key'] == 'plaintext') {
                        // plaintext search
                        $nodeValue = $child->text();
                    } else {
                        // normal search
                        $nodeValue = $child->getAttribute($rule['key']);
                    }
                    $check = $this->match($rule['operator'], $rule['value'], $nodeValue);
                    // handle multiple classes
                    if (!$check && $rule['key'] == 'class') {
                        $childClasses = explode(' ', $child->getAttribute('class'));
                        foreach ($childClasses as $class) {
                            if (!empty($class)) {
                                $check = $this->match($rule['operator'], $rule['value'], $class);
                            }
                            if ($check) {
                                break;
                            }
                        }
                    }
                    if (!$check) {
                        $pass = false;
                    }
                }
                if ($pass) {
                    // it passed all checks
                    $return[] = $child;
                } else {
                    // this child failed to be matched
                    if ($child instanceof InnerNode && $child->hasChildren()) {
                        // we still want to check its children
                        $children[] = $child;
                    }
                }
                try {
                    // get next child
                    $child = $node->nextChild($child->id());
                } catch (ChildNotFoundException $e) {
                    // no more children
                    $child = null;
                }
            }
            if ((!isset($options['checkGrandChildren']) || $options['checkGrandChildren']) && count($children) > 0) {
                // we have children that failed but are not leaves.
                $matches = $this->seek($children, $rule, $options);
                foreach ($matches as $match) {
                    $return[] = $match;
                }
            }
        }
        return $return;
    }