diff options
Diffstat (limited to 'vendor/sabre/vobject/bin/mergeduplicates.php')
-rwxr-xr-x | vendor/sabre/vobject/bin/mergeduplicates.php | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/vendor/sabre/vobject/bin/mergeduplicates.php b/vendor/sabre/vobject/bin/mergeduplicates.php new file mode 100755 index 000000000..1662e7bf3 --- /dev/null +++ b/vendor/sabre/vobject/bin/mergeduplicates.php @@ -0,0 +1,184 @@ +#!/usr/bin/env php +<?php + +namespace Sabre\VObject; + +// This sucks.. we have to try to find the composer autoloader. But chances +// are, we can't find it this way. So we'll do our bestest +$paths = [ + __DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly + __DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency. +]; + +foreach ($paths as $path) { + if (file_exists($path)) { + include $path; + break; + } +} + +if (!class_exists('Sabre\\VObject\\Version')) { + fwrite(STDERR, "Composer autoloader could not be loaded.\n"); + die(1); +} + +echo "sabre/vobject ", Version::VERSION, " duplicate contact merge tool\n"; + +if ($argc < 3) { + + echo "\n"; + echo "Usage: ", $argv[0], " input.vcf output.vcf [debug.log]\n"; + die(1); + +} + +$input = fopen($argv[1], 'r'); +$output = fopen($argv[2], 'w'); +$debug = isset($argv[3]) ? fopen($argv[3], 'w') : null; + +$splitter = new Splitter\VCard($input); + +// The following properties are ignored. If they appear in some vcards +// but not in others, we don't consider them for the sake of finding +// differences. +$ignoredProperties = [ + "PRODID", + "VERSION", + "REV", + "UID", + "X-ABLABEL", +]; + + +$collectedNames = []; + +$stats = [ + "Total vcards" => 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 ($newProp->name === 'EMAIL' || $newProp->name === 'TEL') { + + // 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"; |