ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
mergeduplicates.php
Go to the documentation of this file.
1 #!/usr/bin/env php
2 <?php
3 
4 namespace Sabre\VObject;
5 
6 // This sucks.. we have to try to find the composer autoloader. But chances
7 // are, we can't find it this way. So we'll do our bestest
8 $paths = [
9  __DIR__ . '/../vendor/autoload.php', // In case vobject is cloned directly
10  __DIR__ . '/../../../autoload.php', // In case vobject is a composer dependency.
11 ];
12 
13 foreach ($paths as $path) {
14  if (file_exists($path)) {
15  include $path;
16  break;
17  }
18 }
19 
20 if (!class_exists('Sabre\\VObject\\Version')) {
21  fwrite(STDERR, "Composer autoloader could not be loaded.\n");
22  die(1);
23 }
24 
25 echo "sabre/vobject ", Version::VERSION, " duplicate contact merge tool\n";
26 
27 if ($argc < 3) {
28 
29  echo "\n";
30  echo "Usage: ", $argv[0], " input.vcf output.vcf [debug.log]\n";
31  die(1);
32 
33 }
34 
35 $input = fopen($argv[1], 'r');
36 $output = fopen($argv[2], 'w');
37 $debug = isset($argv[3]) ? fopen($argv[3], 'w') : null;
38 
40 
41 // The following properties are ignored. If they appear in some vcards
42 // but not in others, we don't consider them for the sake of finding
43 // differences.
45  "PRODID",
46  "VERSION",
47  "REV",
48  "UID",
49  "X-ABLABEL",
50 ];
51 
52 
54 
55 $stats = [
56  "Total vcards" => 0,
57  "No FN property" => 0,
58  "Ignored duplicates" => 0,
59  "Merged values" => 0,
60  "Error" => 0,
61  "Unique cards" => 0,
62  "Total written" => 0,
63 ];
64 
65 function writeStats() {
66 
67  global $stats;
68  foreach ($stats as $name => $value) {
69  echo str_pad($name, 23, " ", STR_PAD_RIGHT), str_pad($value, 6, " ", STR_PAD_LEFT), "\n";
70  }
71  // Moving cursor back a few lines.
72  echo "\033[" . count($stats) . "A";
73 
74 }
75 
76 function write($vcard) {
77 
78  global $stats, $output;
79 
80  $stats["Total written"]++;
81  fwrite($output, $vcard->serialize() . "\n");
82 
83 }
84 
85 while ($vcard = $splitter->getNext()) {
86 
87  $stats["Total vcards"]++;
88  writeStats();
89 
90  $fn = isset($vcard->FN) ? (string)$vcard->FN : null;
91 
92  if (empty($fn)) {
93 
94  // Immediately write this vcard, we don't compare it.
95  $stats["No FN property"]++;
96  $stats['Unique cards']++;
97  write($vcard);
98  $vcard->destroy();
99  continue;
100 
101  }
102 
103  if (!isset($collectedNames[$fn])) {
104 
105  $collectedNames[$fn] = $vcard;
106  $stats['Unique cards']++;
107  continue;
108 
109  } else {
110 
111  // Starting comparison for all properties. We only check if properties
112  // in the current vcard exactly appear in the earlier vcard as well.
113  foreach ($vcard->children() as $newProp) {
114 
115  if (in_array($newProp->name, $ignoredProperties)) {
116  // We don't care about properties such as UID and REV.
117  continue;
118  }
119  $ok = false;
120  foreach ($collectedNames[$fn]->select($newProp->name) as $compareProp) {
121 
122  if ($compareProp->serialize() === $newProp->serialize()) {
123  $ok = true;
124  break;
125  }
126  }
127 
128  if (!$ok) {
129 
130  if ($newProp->name === 'EMAIL' || $newProp->name === 'TEL') {
131 
132  // We're going to make another attempt to find this
133  // property, this time just by value. If we find it, we
134  // consider it a success.
135  foreach ($collectedNames[$fn]->select($newProp->name) as $compareProp) {
136 
137  if ($compareProp->getValue() === $newProp->getValue()) {
138  $ok = true;
139  break;
140  }
141  }
142 
143  if (!$ok) {
144 
145  // Merging the new value in the old vcard.
146  $collectedNames[$fn]->add(clone $newProp);
147  $ok = true;
148  $stats['Merged values']++;
149 
150  }
151 
152  }
153 
154  }
155 
156  if (!$ok) {
157 
158  // echo $newProp->serialize() . " does not appear in earlier vcard!\n";
159  $stats['Error']++;
160  if ($debug) fwrite($debug, "Missing '" . $newProp->name . "' property in duplicate. Earlier vcard:\n" . $collectedNames[$fn]->serialize() . "\n\nLater:\n" . $vcard->serialize() . "\n\n");
161 
162  $vcard->destroy();
163  continue 2;
164  }
165 
166  }
167 
168  }
169 
170  $vcard->destroy();
171  $stats['Ignored duplicates']++;
172 
173 }
174 
175 foreach ($collectedNames as $vcard) {
176 
177  // Overwriting any old PRODID
178  $vcard->PRODID = '-//Sabre//Sabre VObject ' . Version::VERSION . '//EN';
179  write($vcard);
180  writeStats();
181 
182 }
183 
184 echo str_repeat("\n", count($stats)), "\nDone.\n";
$path
Definition: aliased.php:25
global $argv
Definition: svg-scanner.php:41
if($argc< 3) $input
foreach($paths as $path) if(!class_exists( 'Sabre\\VObject\\Version'))
const VERSION
Full version number.
Definition: Version.php:17
select
Definition: langcheck.php:166
The VCard component.
Definition: VCard.php:18