aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/sabre/vobject/bin/mergeduplicates.php
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sabre/vobject/bin/mergeduplicates.php')
-rwxr-xr-xvendor/sabre/vobject/bin/mergeduplicates.php184
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";