/** * @param mixed $handler_id The ID of the handler. * @param Array $args The argument list. * @param Array &$data The local request data. */ public function _handler_frontpage($handler_id, array $args, array &$data) { midcom::get('auth')->require_valid_user(); midcom_helper_datamanager2_widget_autocomplete::add_head_elements(); $data['tree'] = $this->_master->get_group_tree(); $this->_view_toolbar->add_item(array(MIDCOM_TOOLBAR_URL => 'person/create/', MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('create person'), MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/stock_person-new.png', MIDCOM_TOOLBAR_ENABLED => midcom::get('auth')->can_user_do('midgard:create', null, 'org_openpsa_contacts_person_dba'))); $this->_view_toolbar->add_item(array(MIDCOM_TOOLBAR_URL => 'group/create/organization/', MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('create organization'), MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/stock_people-new.png', MIDCOM_TOOLBAR_ENABLED => midcom::get('auth')->can_user_do('midgard:create', null, 'org_openpsa_contacts_group_dba'))); $this->_view_toolbar->add_item(array(MIDCOM_TOOLBAR_URL => 'group/create/group/', MIDCOM_TOOLBAR_LABEL => sprintf($this->_l10n_midcom->get('create %s'), $this->_l10n->get('group')), MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/stock_people-new.png', MIDCOM_TOOLBAR_ENABLED => midcom::get('auth')->can_user_do('midgard:create', null, 'org_openpsa_contacts_group_dba'))); $p_merger = new org_openpsa_contacts_duplicates_merge('person'); if ($p_merger->merge_needed()) { $this->_view_toolbar->add_item(array(MIDCOM_TOOLBAR_URL => 'duplicates/person/', MIDCOM_TOOLBAR_LABEL => $this->_l10n->get('merge persons'), MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/repair.png', MIDCOM_TOOLBAR_ENABLED => midcom::get('auth')->can_user_do('midgard:update', null, 'org_openpsa_contacts_person_dba'))); } if ($this->_topic->can_do('midgard:update') && $this->_topic->can_do('midcom:component_config')) { $this->_node_toolbar->add_item(array(MIDCOM_TOOLBAR_URL => 'config/', MIDCOM_TOOLBAR_LABEL => $this->_l10n_midcom->get('component configuration'), MIDCOM_TOOLBAR_HELPTEXT => $this->_l10n_midcom->get('component configuration helptext'), MIDCOM_TOOLBAR_ICON => 'stock-icons/16x16/stock_folder-properties.png')); } midcom::get('head')->set_pagetitle($this->_l10n->get("my contacts")); }
/** * Support for contacts person merge */ function org_openpsa_contacts_duplicates_merge_person(&$person1, &$person2, $mode) { switch ($mode) { case 'all': break; /* In theory we could have future things (like resource/manager ships), but now we don't support that mode, we just exit */ /* In theory we could have future things (like resource/manager ships), but now we don't support that mode, we just exit */ case 'future': return true; break; default: // Mode not implemented debug_add("mode {$mode} not implemented", MIDCOM_LOG_ERROR); return false; break; } // Transfer links from classes we drive // ** expense reports ** $qb_expense = org_openpsa_expenses_expense::new_query_builder(); $qb_expense->add_constraint('person', '=', $person2->id); $expenses = $qb_expense->execute(); if ($expenses === false) { // Some error with QB debug_add('QB Error / expenses', MIDCOM_LOG_ERROR); return false; } foreach ($expenses as $expense) { debug_add("Transferred expense #{$expense->id} to person #{$person1->id} (from #{$expense->person})", MIDCOM_LOG_INFO); $expense->person = $person1->id; if (!$expense->update()) { // Error updating debug_add("Failed to update expense #{$expense->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // Transfer metadata dependencies from classes that we drive $classes = array('org_openpsa_expenses_expense'); $metadata_fields = array('creator' => 'guid', 'revisor' => 'guid'); foreach ($classes as $class) { $ret = org_openpsa_contacts_duplicates_merge::person_metadata_dependencies_helper($class, $person1, $person2, $metadata_fields); if (!$ret) { // Failure updating metadata debug_add("Failed to update metadata dependencies in class {$class}, errsrtr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // All done return true; }
/** * Support for contacts person merge */ function org_openpsa_contacts_duplicates_merge_person(&$person1, &$person2, $mode) { switch ($mode) { case 'all': break; /* In theory we could have future things (like resource/manager ships), but now we don't support that mode, we just exit */ /* In theory we could have future things (like resource/manager ships), but now we don't support that mode, we just exit */ case 'future': return true; break; default: // Mode not implemented debug_add("mode {$mode} not implemented", MIDCOM_LOG_ERROR); return false; break; } // Transfer links from classes we drive // ** resources ** $qb_member = org_openpsa_projects_task_resource_dba::new_query_builder(); $qb_member->add_constraint('person', '=', $person2->id); $members = $qb_member->execute(); if ($members === false) { // Some error with QB debug_add('QB Error', MIDCOM_LOG_ERROR); return false; } // Transfer memberships foreach ($members as $member) { // TODO: figure out duplicate memberships and delete unneeded ones $member->person = $person1->id; debug_add("Transferred task resource #{$member->id} to person #{$person1->id} (from #{$member->person})", MIDCOM_LOG_INFO); if (!$member->update()) { debug_add("Failed to update task resource #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // ** task statuses ** $qb_receipt = org_openpsa_projects_task_status_dba::new_query_builder(); $qb_receipt->add_constraint('targetPerson', '=', $person2->id); $receipts = $qb_receipt->execute(); if ($receipts === false) { // Some error with QB debug_add('QB Error / status', MIDCOM_LOG_ERROR); return false; } foreach ($receipts as $receipt) { debug_add("Transferred task_status #{$receipt->id} to person #{$person1->id} (from #{$receipt->person})", MIDCOM_LOG_INFO); $receipt->targetPerson = $person1->id; if (!$receipt->update()) { // Error updating debug_add("Failed to update status #{$receipt->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // ** hour reports ** $qb_log = org_openpsa_projects_hour_report_dba::new_query_builder(); $qb_log->add_constraint('person', '=', $person2->id); $logs = $qb_log->execute(); if ($logs === false) { // Some error with QB debug_add('QB Error / hours', MIDCOM_LOG_ERROR); return false; } foreach ($logs as $log) { debug_add("Transferred hour_report #{$log->id} to person #{$person1->id} (from #{$log->person})", MIDCOM_LOG_INFO); $log->person = $person1->id; if (!$log->update()) { // Error updating debug_add("Failed to update hour_report #{$log->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // ** Task managers ** $qb_task = org_openpsa_projects_task_dba::new_query_builder(); $qb_task->add_constraint('manager', '=', $person2->id); $tasks = $qb_task->execute(); if ($tasks === false) { // Some error with QB debug_add('QB Error / tasks', MIDCOM_LOG_ERROR); return false; } foreach ($tasks as $task) { debug_add("Transferred task #{$task->id} to person #{$person1->id} (from #{$task->person})", MIDCOM_LOG_INFO); $task->manager = $person1->id; if (!$task->update()) { // Error updating debug_add("Failed to update task #{$task->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // Transfer metadata dependencies from classes that we drive $classes = array('org_openpsa_projects_task_resource_dba', 'org_openpsa_projects_task_status_dba', 'org_openpsa_projects_task_dba', 'org_openpsa_projects_hour_report_dba'); $metadata_fields = array('creator' => 'guid', 'revisor' => 'guid'); foreach ($classes as $class) { $ret = org_openpsa_contacts_duplicates_merge::person_metadata_dependencies_helper($class, $person1, $person2, $metadata_fields); if (!$ret) { // Failure updating metadata debug_add("Failed to update metadata dependencies in class {$class}, errsrtr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // All done return true; }
/** * Support for contacts person merge */ function org_openpsa_contacts_duplicates_merge_person(&$person1, &$person2, $mode) { switch ($mode) { case 'all': break; case 'future': // DirMar does not have future references so we have nothing to transfer... return true; break; default: // Mode not implemented debug_add("mode {$mode} not implemented", MIDCOM_LOG_ERROR); return false; break; } // Transfer links from classes we drive // ** Members ** $qb_member = org_openpsa_directmarketing_campaign_member_dba::new_query_builder(); $qb_member->add_constraint('person', '=', $person2->id); $members = $qb_member->execute(); if ($members === false) { // Some error with QB debug_add('QB Error', MIDCOM_LOG_ERROR); return false; } // Transfer memberships foreach ($members as $member) { $member->person = $person1->id; if (!$member->_check_duplicate_membership()) { // This is a duplicate membership, delete it debug_add("Person #{$person1->id} is already member in campaign #{$member->campaign}, removing membership #{$member->id}", MIDCOM_LOG_INFO); if (!$member->delete()) { debug_add("Could not delete campaign member #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } continue; } debug_add("Transferred campaign membership #{$member->id} to person #{$person1->id} (from #{$member->person})", MIDCOM_LOG_INFO); if (!$member->update()) { debug_add("Failed to update campaign member #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // ** Receipts ** $qb_receipt = org_openpsa_directmarketing_campaign_messagereceipt_dba::new_query_builder(); $qb_receipt->add_constraint('person', '=', $person2->id); $receipts = $qb_receipt->execute(); if ($receipts === false) { // Some error with QB debug_add('QB Error / receipts', MIDCOM_LOG_ERROR); return false; } foreach ($receipts as $receipt) { debug_add("Transferred message_receipt #{$receipt->id} to person #{$person1->id} (from #{$receipt->person})", MIDCOM_LOG_INFO); $receipt->person = $person1->id; if (!$receipt->update()) { // Error updating debug_add("Failed to update receipt #{$receipt->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // ** Logs ** $qb_log = org_openpsa_directmarketing_link_log_dba::new_query_builder(); $qb_log->add_constraint('person', '=', $person2->id); $logs = $qb_log->execute(); if ($logs === false) { // Some error with QB debug_add('QB Error / links', MIDCOM_LOG_ERROR); return false; } foreach ($logs as $log) { debug_add("Transferred link_log #{$log->id} to person #{$person1->id} (from #{$log->person})", MIDCOM_LOG_INFO); $log->person = $person1->id; if (!$log->update()) { // Error updating debug_add("Failed to update link #{$log->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // Transfer metadata dependencies from classes that we drive $classes = array('org_openpsa_directmarketing_campaign_dba', 'org_openpsa_directmarketing_campaign_member_dba', 'org_openpsa_directmarketing_campaign_message_dba', 'org_openpsa_directmarketing_campaign_messagereceipt_dba', 'org_openpsa_directmarketing_link_log_dba'); foreach ($classes as $class) { // TODO: 1.8 metadata format support $ret = org_openpsa_contacts_duplicates_merge::person_metadata_dependencies_helper($class, $person1, $person2, $metadata_fields); if (!$ret) { // Failure updating metadata debug_add("Failed to update metadata dependencies in class {$class}, errsrtr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // All done return true; }
/** * Support for contacts person merge */ function org_openpsa_contacts_duplicates_merge_person(&$person1, &$person2, $mode) { switch ($mode) { case 'all': break; case 'future': // Contacts does not have future references so we have nothing to transfer... return true; break; default: // Mode not implemented debug_add("mode {$mode} not implemented", MIDCOM_LOG_ERROR); return false; break; } $qb = midcom_db_member::new_query_builder(); $qb->begin_group('OR'); // We need the remaining persons memberships later when we compare the two $qb->add_constraint('uid', '=', $person1->id); $qb->add_constraint('uid', '=', $person2->id); $qb->end_group(); $members = $qb->execute(); if ($members === false) { // Some error with QB debug_add('QB Error', MIDCOM_LOG_ERROR); return false; } // Transfer memberships $membership_map = array(); foreach ($members as $member) { if ($member->uid != $person1->id) { debug_add("Transferred membership #{$member->id} to person #{$person1->id} (from #{$member->uid})"); $member->uid = $person1->id; } if (!isset($membership_map[$member->gid]) || !is_array($membership_map[$member->gid])) { $membership_map[$member->gid] = array(); } $membership_map[$member->gid][] = $member; } unset($members); // Merge memberships foreach ($membership_map as $members) { foreach ($members as $member) { if (count($members) == 1) { // We only have one membership in this group, skip rest of the logic if (!$member->update()) { // Failure updating member debug_add("Failed to update member #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } continue; } // TODO: Compare memberships to determine which of them are identical and thus not worth keeping if (!$member->update()) { // Failure updating member debug_add("Failed to update member #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } } // Transfer metadata dependencies from classes that we drive $classes = array('midcom_db_member', 'org_openpsa_contacts_person_dba', 'org_openpsa_contacts_group_dba'); $metadata_fields = array('creator' => 'guid', 'revisor' => 'guid'); foreach ($classes as $class) { $ret = org_openpsa_contacts_duplicates_merge::person_metadata_dependencies_helper($class, $person1, $person2, $metadata_fields); if (!$ret) { // Failure updating metadata debug_add("Failed to update metadata dependencies in class {$class}, errsrtr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // Copy fields missing from person1 and present in person2 over $skip_properties = array('id' => true, 'guid' => true); $changed = false; foreach ($person2 as $property => $value) { // Copy only simple properties not marked to be skipped missing from person1 if (empty($person2->{$property}) || !empty($person1->{$property}) || isset($skip_properties[$property]) || is_array($value) || is_object($value)) { continue; } $person1->{$property} = $value; $changed = true; } // Avoid unnecessary updates if ($changed) { if (!$person1->update()) { // Error updating person debug_add("Error updating person #{$person1->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } // PONDER: sensible way to do the same for parameters ?? return true; }
/** * Support for contacts person merge */ function org_openpsa_contacts_duplicates_merge_person(&$person1, &$person2, $mode) { switch ($mode) { case 'all': break; /* case 'future': // Calendar should have future mode but we don't support it yet break; */ /* case 'future': // Calendar should have future mode but we don't support it yet break; */ default: // Mode not implemented debug_add("mode {$mode} not implemented", MIDCOM_LOG_ERROR); return false; break; } $qb = org_openpsa_calendar_event_member_dba::new_query_builder(); $qb->begin_group('OR'); // We need the remaining persons memberships later when we compare the two $qb->add_constraint('uid', '=', $person1->id); $qb->add_constraint('uid', '=', $person2->id); $qb->end_group(); $members = $qb->execute(); if ($members === false) { // Some error with QB debug_add('QB Error', MIDCOM_LOG_ERROR); return false; } // Transfer memberships $membership_map = array(); foreach ($members as $member) { if ($member->uid != $person1->id) { debug_add("Transferred event membership #{$member->id} to person #{$person1->id} (from #{$member->uid})"); $member->uid = $person1->id; } if (!isset($membership_map[$member->eid]) || !is_array($membership_map[$member->eid])) { $membership_map[$member->eid] = array(); } $membership_map[$member->eid][] = $member; } unset($members); // Merge memberships foreach ($membership_map as $members) { foreach ($members as $member) { if (count($members) == 1) { // We only have one membership in this event, skip rest of the logic if (!$member->update()) { // Failure updating member debug_add("Failed to update eventmember #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } continue; } // TODO: Compare memberships to determine which of them are identical and thus not worth keeping if (!$member->update()) { // Failure updating member debug_add("Failed to update eventmember #{$member->id}, errstr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } } // Transfer metadata dependencies from classes that we drive $classes = array('org_openpsa_calendar_event_dba', 'org_openpsa_calendar_event_member_dba'); $metadata_fields = array('creator' => 'guid', 'revisor' => 'guid'); foreach ($classes as $class) { $ret = org_openpsa_contacts_duplicates_merge::person_metadata_dependencies_helper($class, $person1, $person2, $metadata_fields); if (!$ret) { // Failure updating metadata debug_add("Failed to update metadata dependencies in class {$class}, errsrtr: " . midcom_connection::get_error_string(), MIDCOM_LOG_ERROR); return false; } } return true; }
/** * @param mixed $handler_id The ID of the handler. * @param Array $args The argument list. * @param Array &$data The local request data. */ public function _handler_sidebyside($handler_id, array $args, array &$data) { $this->set_active_leaf('persons_merge'); midcom::get('auth')->require_valid_user(); // Process the selection if present. if (!empty($_POST['org_openpsa_contacts_handler_duplicates_person_keep']) && !empty($_POST['org_openpsa_contacts_handler_duplicates_person_options']) && count($_POST['org_openpsa_contacts_handler_duplicates_person_options']) == 2) { $option1 = new org_openpsa_contacts_person_dba($_POST['org_openpsa_contacts_handler_duplicates_person_options'][1]); $option2 = new org_openpsa_contacts_person_dba($_POST['org_openpsa_contacts_handler_duplicates_person_options'][2]); foreach ($_POST['org_openpsa_contacts_handler_duplicates_person_keep'] as $keep => $dummy) { switch (true) { case $keep == 'both': $option1->require_do('midgard:update'); $option2->require_do('midgard:update'); if (!$option1->parameter('org.openpsa.contacts.duplicates:not_duplicate', $option2->guid, time()) || !$option2->parameter('org.openpsa.contacts.duplicates:not_duplicate', $option1->guid, time())) { $errstr = midcom_connection::get_error_string(); // Failed to set as not duplicate, clear parameters that might have been set $option1->parameter('org.openpsa.contacts.duplicates:not_duplicate', $option2->guid, ''); $option2->parameter('org.openpsa.contacts.duplicates:not_duplicate', $option1->guid, ''); // TODO: Localize midcom::get('uimessages')->add($this->_l10n->get('org.openpsa.contacts'), "Failed to mark #{$option1->id} and # {$option2->id} as not duplicates, errstr: {$errstr}", 'error'); // Switch is a "loop" so we continue 2 levels to get out of the foreach as well continue 2; } // Clear the possible duplicate parameters $option1->parameter('org.openpsa.contacts.duplicates:possible_duplicate', $option2->guid, ''); $option2->parameter('org.openpsa.contacts.duplicates:possible_duplicate', $option1->guid, ''); // TODO: Localize midcom::get('uimessages')->add($this->_l10n->get('org.openpsa.contacts'), "Keeping both \"{$option1->name}\" and \"{$option2->name}\", they will not be marked as duplicates in the future", 'ok'); // Switch is a "loop" so we continue 2 levels to get out of the foreach as well continue 2; // Safety break break; case $keep == $option1->guid: $person1 =& $option1; $person2 =& $option2; break; case $keep == $option2->guid: $person1 =& $option2; $person2 =& $option1; break; default: throw new midcom_error('Something weird happened (basically we got bogus data)'); } $person1->require_do('midgard:update'); $person2->require_do('midgard:delete'); // TODO: Merge person2 data to person1 and then delete person2 $merger = new org_openpsa_contacts_duplicates_merge('person'); if (!$merger->merge_delete($person1, $person2)) { // TODO: Localize midcom::get('uimessages')->add($this->_l10n->get('org.openpsa.contacts'), 'Merge failed, errstr: ' . $merger->errstr(), 'error'); } } //PONDER: redirect to avoid reloading the POST in case user presses reload ?? } // Then find us next pair we have sufficient rights for... $this->_request_data['notfound'] = false; $this->_request_data['person1'] = false; $this->_request_data['person2'] = false; $this->_request_data['loop_i'] = 0; $i =& $this->_request_data['loop_i']; if (isset($_REQUEST['org_openpsa_contacts_handler_duplicates_person_decide_later']) && isset($_REQUEST['org_openpsa_contacts_handler_duplicates_person_loop_i'])) { $i = $_REQUEST['org_openpsa_contacts_handler_duplicates_person_loop_i'] + 1; } while ($i < 100) { debug_add("Loop iteration {$i}"); $qb = new midgard_query_builder('midgard_parameter'); $qb->add_constraint('domain', '=', 'org.openpsa.contacts.duplicates:possible_duplicate'); $qb->add_order('name', 'ASC'); $qb->set_limit(1); if ($i > 0) { $qb->set_offset($i); } $ret = @$qb->execute(); if (empty($ret)) { debug_add("No more results to be had, setting notfound and breaking out of loop"); $this->_request_data['notfound'] = true; break; } $param =& $ret[0]; debug_add("Found duplicate mark on person #{$param->parentguid} for person {$param->name}"); try { $person1 = new org_openpsa_contacts_person_dba($param->parentguid); $person2 = new org_openpsa_contacts_person_dba($param->name); } catch (midcom_error $e) { $i++; continue; } // Make sure we actually have enough rights to do this if (!$person1->can_do('midgard:update') || !$person1->can_do('midgard:delete') || !$person2->can_do('midgard:update') || !$person2->can_do('midgard:delete')) { debug_add("Insufficient rights to merge these two, continuing to see if we have more"); $i++; continue; } // Extra sanity check (in case of semi-successful not-duplicate mark) if ($person1->parameter('org.openpsa.contacts.duplicates:not_duplicate', $person2->guid) || $person2->parameter('org.openpsa.contacts.duplicates:not_duplicate', $person1->guid)) { debug_add("It seems these two (#{$person1->id} and #{$person2->id}) have also marked as not duplicates, some cleanup might be a good thing", MIDCOM_LOG_WARN); $i++; continue; } $this->_request_data['probability'] = (double) $param->value; $this->_request_data['person1'] = $person1; $this->_request_data['person2'] = $person2; break; } }