public function validateFilters($vcardData, array $filters, $test)
    {
        if (!$filters) {
            return true;
        }
        $vcard = VObject\Reader::read($vcardData);

        foreach ($filters as $filter) {
            $isDefined = isset($vcard->{$filter['name']});
            if ($filter['is-not-defined']) {
                if ($isDefined) {
                    $success = false;
                } else {
                    $success = true;
                }
            } elseif ((!$filter['param-filters'] && !$filter['text-matches']) || !$isDefined) {
                // We only need to check for existence
                $success = $isDefined;
            } else {
                $vProperties = $vcard->select($filter['name']);

                $results = [];
                if ($filter['param-filters']) {
                    $results[] = $this->validateParamFilters($vProperties, $filter['param-filters'], $filter['test']);
                }
                if ($filter['text-matches']) {
                    $texts = [];
                    foreach ($vProperties as $vProperty) {
                        $texts[] = $vProperty->getValue();
                    }

                    $results[] = $this->validateTextMatches($texts, $filter['text-matches'], $filter['test']);
                }

                if (1 === count($results)) {
                    $success = $results[0];
                } else {
                    if ('anyof' === $filter['test']) {
                        $success = $results[0] || $results[1];
                    } else {
                        $success = $results[0] && $results[1];
                    }
                }
            } // else

            // There are two conditions where we can already determine whether
            // or not this filter succeeds.
            if ('anyof' === $test && $success) {
                // Destroy circular references to PHP will GC the object.
                $vcard->destroy();

                return true;
            }
            if ('allof' === $test && !$success) {
                // Destroy circular references to PHP will GC the object.
                $vcard->destroy();

                return false;
            }
        } // foreach

        // Destroy circular references to PHP will GC the object.
        $vcard->destroy();

        // If we got all the way here, it means we haven't been able to
        // determine early if the test failed or not.
        //
        // This implies for 'anyof' that the test failed, and for 'allof' that
        // we succeeded. Sounds weird, but makes sense.
        return 'allof' === $test;
    }