Implement contact merging.
authorJan Schneider <jan@horde.org>
Mon, 5 Jul 2010 10:34:25 +0000 (12:34 +0200)
committerJan Schneider <jan@horde.org>
Mon, 5 Jul 2010 10:34:47 +0000 (12:34 +0200)
turba/docs/CHANGES
turba/edit.php
turba/lib/Object.php
turba/lib/View/Duplicates.php
turba/merge.php [new file with mode: 0644]
turba/templates/search/duplicate/contact_header.html.php

index 16ef1ff..3479ab4 100644 (file)
@@ -2,6 +2,7 @@
 v3.0-git
 --------
 
+[jan] Add duplicate search and merging.
 [mjr] The listTimeObjects API now returns categories for each source
       individually instead of returning only the categories available
       (Request #8504).
index e9e2019..dc4a710 100644 (file)
@@ -81,7 +81,12 @@ if ($groupedit) {
 $edited = $form->execute();
 if (!is_a($edited, 'PEAR_Error')) {
     $url = Horde_Util::getFormData('url');
-    header('Location: ' . (empty($url) ? $contact->url('Contact', true) : $url));
+    if (empty($url)) {
+        $url = $contact->url('Contact', true);
+    } else {
+        $url = new Horde_Url($url, true);
+    }
+    header('Location: ' . $url->add('unique', hash('md5', microtime())));
     exit;
 }
 
index f651afc..268eb10 100644 (file)
@@ -224,6 +224,21 @@ class Turba_Object {
     }
 
     /**
+     * Merges another contact into this one by filling empty fields of this
+     * contact with values from the other.
+     *
+     * @param Turba_Object $contact  Another contact.
+     */
+    function merge(Turba_Object $contact)
+    {
+        foreach (array_keys($contact->attributes) as $attribute) {
+            if (!$this->hasValue($attribute) && $contact->hasValue($attribute)) {
+                $this->setValue($attribute, $contact->getValue($attribute));
+            }
+        }
+    }
+
+    /**
      * Returns history information about this contact.
      *
      * @return array  A hash with the optional entries 'created' and 'modified'
index 2f357f5..e2d00a7 100644 (file)
@@ -73,7 +73,9 @@ class Turba_View_Duplicates
         $view = new Horde_View(array('templatePath' => TURBA_TEMPLATES . '/search/duplicate'));
         new Horde_View_Helper_Text($view);
 
-        $hasDuplicate = $this->_type && $this->_duplicate;
+        $hasDuplicate = $this->_type && $this->_duplicate &&
+            isset($this->_duplicates[$this->_type]) &&
+            isset($this->_duplicates[$this->_type][$this->_duplicate]);
         if ($hasDuplicate) {
             $vars = new Horde_Variables();
             $view->type = $attributes[$this->_type]['label'];
@@ -81,13 +83,14 @@ class Turba_View_Duplicates
             echo $view->render('header');
 
             $view->contactUrl = Horde::applicationUrl('contact.php');
+            $view->mergeUrl = Horde::applicationUrl('merge.php');
             $view->first = true;
             $duplicate = $this->_duplicates[$this->_type][$this->_duplicate];
             while ($contact = $duplicate->next()) {
                 $contact->lastModification();
             }
             $duplicate->sort(array(array('field' => '__modified', 'ascending' => false)));
-            $view->mergeInto = $duplicate->reset()->getValue('__key');
+            $view->mergeTarget = $duplicate->reset()->getValue('__key');
             while ($contact = $duplicate->next()) {
                 $view->source = $contact->getSource();
                 $view->id = $contact->getValue('__key');
diff --git a/turba/merge.php b/turba/merge.php
new file mode 100644 (file)
index 0000000..4449b85
--- /dev/null
@@ -0,0 +1,50 @@
+<?php
+/**
+ * Merges one contact into another.
+ *
+ * Copyright 2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (ASL).  If you
+ * did not receive this file, see http://www.horde.org/licenses/asl.php.
+ *
+ * @author Jan Schneider <jan@horde.org>
+ */
+
+require_once dirname(__FILE__) . '/lib/Application.php';
+Horde_Registry::appInit('turba');
+
+$source = Horde_Util::getFormData('source');
+$key = Horde_Util::getFormData('key');
+$mergeInto = Horde_Util::getFormData('merge_into');
+$driver = Turba_Driver::singleton($source);
+
+if ($url = Horde_Util::getFormData('url')) {
+    $url = new Horde_Url($url, true);
+    $url->add('unique', hash('md5', microtime()));
+}
+
+$contact = $driver->getObject($mergeInto);
+if (is_a($contact, 'PEAR_Error')) {
+    $notification->push($contact);
+    header('Location: ' . $url);
+    exit;
+}
+$toMerge = $driver->getObject($key);
+if (is_a($toMerge, 'PEAR_Error')) {
+    $notification->push($toMerge);
+    header('Location: ' . $url);
+    exit;
+}
+
+$contact->merge($toMerge);
+if (is_a($result = $contact->store(), 'PEAR_Error')) {
+    $notification->push($result);
+    header('Location: ' . $url);
+    exit;
+}
+if (is_a($result = $driver->delete($key), 'PEAR_Error')) {
+    $notification->push($result);
+}
+
+header('Location: ' . $url);
+exit;
index 65d8c4e..314ccb8 100644 (file)
@@ -6,14 +6,13 @@
   <? endif; ?>
   <div class="turba-duplicate-forms">
     <? if (!$this->first): ?>
-    <form action="<?= $this->contactUrl ?>">
+    <form action="<?= $this->mergeUrl ?>">
       <input type="hidden" name="source" value="<?= $this->source ?>" />
       <input type="hidden" name="key" value="<?= $this->h($this->id) ?>" />
       <input type="hidden" name="url" value="<?= Horde::selfUrl(true) ?>" />
       <input type="hidden" name="merge_into" value="<?= $this->h($this->mergeTarget) ?>" />
-      <input type="hidden" name="actionID" value="merge" />
       <input type="submit" class="button" value="<?= _("<< Merge this into the first contact") ?>" />
-                                                           </form>
+    </form>
     <? endif; ?>
     <form action="<?= $this->contactUrl ?>">
       <input type="hidden" name="source" value="<?= $this->source ?>" />