#!/usr/bin/env php 0, 'No FN property' => 0, 'Ignored duplicates' => 0, 'Merged values' => 0, 'Error' => 0, 'Unique cards' => 0, 'Total written' => 0, ]; function writeStats() { global $stats; foreach ($stats as $name => $value) { echo str_pad($name, 23, ' ', STR_PAD_RIGHT), str_pad($value, 6, ' ', STR_PAD_LEFT), "\n"; } // Moving cursor back a few lines. echo "\033[".count($stats).'A'; } function write($vcard) { global $stats, $output; ++$stats['Total written']; fwrite($output, $vcard->serialize()."\n"); } while ($vcard = $splitter->getNext()) { ++$stats['Total vcards']; writeStats(); $fn = isset($vcard->FN) ? (string) $vcard->FN : null; if (empty($fn)) { // Immediately write this vcard, we don't compare it. ++$stats['No FN property']; ++$stats['Unique cards']; write($vcard); $vcard->destroy(); continue; } if (!isset($collectedNames[$fn])) { $collectedNames[$fn] = $vcard; ++$stats['Unique cards']; continue; } else { // Starting comparison for all properties. We only check if properties // in the current vcard exactly appear in the earlier vcard as well. foreach ($vcard->children() as $newProp) { if (in_array($newProp->name, $ignoredProperties)) { // We don't care about properties such as UID and REV. continue; } $ok = false; foreach ($collectedNames[$fn]->select($newProp->name) as $compareProp) { if ($compareProp->serialize() === $newProp->serialize()) { $ok = true; break; } } if (!$ok) { if ('EMAIL' === $newProp->name || 'TEL' === $newProp->name) { // We're going to make another attempt to find this // property, this time just by value. If we find it, we // consider it a success. foreach ($collectedNames[$fn]->select($newProp->name) as $compareProp) { if ($compareProp->getValue() === $newProp->getValue()) { $ok = true; break; } } if (!$ok) { // Merging the new value in the old vcard. $collectedNames[$fn]->add(clone $newProp); $ok = true; ++$stats['Merged values']; } } } if (!$ok) { // echo $newProp->serialize() . " does not appear in earlier vcard!\n"; ++$stats['Error']; if ($debug) { fwrite($debug, "Missing '".$newProp->name."' property in duplicate. Earlier vcard:\n".$collectedNames[$fn]->serialize()."\n\nLater:\n".$vcard->serialize()."\n\n"); } $vcard->destroy(); continue 2; } } } $vcard->destroy(); ++$stats['Ignored duplicates']; } foreach ($collectedNames as $vcard) { // Overwriting any old PRODID $vcard->PRODID = '-//Sabre//Sabre VObject '.Version::VERSION.'//EN'; write($vcard); writeStats(); } echo str_repeat("\n", count($stats)), "\nDone.\n";