Esempio n. 1
0
 /**
  * @param CRM_Utils_Sort $sort
  *
  * @return string
  */
 public function buildPrevNextCache($sort)
 {
     $cacheKey = 'civicrm search ' . $this->_key;
     // We should clear the cache in following conditions:
     // 1. when starting from scratch, i.e new search
     // 2. if records are sorted
     // get current page requested
     $pageNum = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     // get the current sort order
     $currentSortID = CRM_Utils_Request::retrieve('crmSID', 'String', CRM_Core_DAO::$_nullObject);
     $session = CRM_Core_Session::singleton();
     // get previous sort id
     $previousSortID = $session->get('previousSortID');
     // check for current != previous to ensure cache is not reset if paging is done without changing
     // sort criteria
     if (!$pageNum || !empty($currentSortID) && $currentSortID != $previousSortID) {
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
         // this means it's fresh search, so set pageNum=1
         if (!$pageNum) {
             $pageNum = 1;
         }
     }
     // set the current sort as previous sort
     if (!empty($currentSortID)) {
         $session->set('previousSortID', $currentSortID);
     }
     $pageSize = CRM_Utils_Request::retrieve('crmRowCount', 'Integer', CRM_Core_DAO::$_nullObject, FALSE, 50);
     $firstRecord = ($pageNum - 1) * $pageSize;
     //for alphabetic pagination selection save
     $sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', CRM_Core_DAO::$_nullObject);
     //for text field pagination selection save
     $countRow = CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
     // $sortByCharacter triggers a refresh in the prevNext cache
     if ($sortByCharacter && $sortByCharacter != 'all') {
         $cacheKey .= "_alphabet";
         $this->fillupPrevNextCache($sort, $cacheKey);
     } elseif ($firstRecord >= $countRow) {
         $this->fillupPrevNextCache($sort, $cacheKey, $countRow, 500 + $firstRecord - $countRow);
     }
     return $cacheKey;
 }
Esempio n. 2
0
 /**
  * Clear the contact cache so things are kosher. We started off being super aggressive with clearing
  * caches, but are backing off from this with every release. Compromise between ease of coding versus
  * performance versus being accurate at that very instant
  *
  * @param $contactID
  *   The contactID that was edited / deleted.
  */
 public static function clearContactCaches($contactID = NULL)
 {
     // clear acl cache if any.
     CRM_ACL_BAO_Cache::resetCache();
     if (empty($contactID)) {
         // also clear prev/next dedupe cache - if no contactID passed in
         CRM_Core_BAO_PrevNextCache::deleteItem();
     }
     // reset the group contact cache for this group
     CRM_Contact_BAO_GroupContactCache::remove();
 }
Esempio n. 3
0
 /**
  * Delete a contact and all its associated records.
  *
  * @param int $id
  *   Id of the contact to delete.
  * @param bool $restore
  *   Whether to actually restore, not delete.
  * @param bool $skipUndelete
  *   Whether to force contact delete or not.
  *
  * @return bool
  *   Was contact deleted?
  */
 public static function deleteContact($id, $restore = FALSE, $skipUndelete = FALSE)
 {
     if (!$id) {
         return FALSE;
     }
     // If trash is disabled in system settings then we always skip
     if (!CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'contact_undelete', NULL, 1)) {
         $skipUndelete = TRUE;
     }
     // make sure we have edit permission for this contact
     // before we delete
     if ($skipUndelete && !CRM_Core_Permission::check('delete contacts') || $restore && !CRM_Core_Permission::check('access deleted contacts')) {
         return FALSE;
     }
     // CRM-12929
     // Restrict contact to be delete if contact has financial trxns
     $error = NULL;
     if ($skipUndelete && CRM_Financial_BAO_FinancialItem::checkContactPresent(array($id), $error)) {
         return FALSE;
     }
     // make sure this contact_id does not have any membership types
     $membershipTypeID = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $id, 'id', 'member_of_contact_id');
     if ($membershipTypeID) {
         return FALSE;
     }
     $contact = new CRM_Contact_DAO_Contact();
     $contact->id = $id;
     if (!$contact->find(TRUE)) {
         return FALSE;
     }
     $contactType = $contact->contact_type;
     // currently we only clear employer cache.
     // we are now deleting inherited membership if any.
     if ($contact->contact_type == 'Organization') {
         $action = $restore ? CRM_Core_Action::ENABLE : CRM_Core_Action::DISABLE;
         $relationshipDtls = CRM_Contact_BAO_Relationship::getRelationship($id);
         if (!empty($relationshipDtls)) {
             foreach ($relationshipDtls as $rId => $details) {
                 CRM_Contact_BAO_Relationship::disableEnableRelationship($rId, $action);
             }
         }
         CRM_Contact_BAO_Contact_Utils::clearAllEmployee($id);
     }
     if ($restore) {
         return self::contactTrashRestore($contact, TRUE);
     }
     // start a new transaction
     $transaction = new CRM_Core_Transaction();
     if ($skipUndelete) {
         CRM_Utils_Hook::pre('delete', $contactType, $id, CRM_Core_DAO::$_nullArray);
         //delete billing address if exists.
         CRM_Contribute_BAO_Contribution::deleteAddress(NULL, $id);
         // delete the log entries since we dont have triggers enabled as yet
         $logDAO = new CRM_Core_DAO_Log();
         $logDAO->entity_table = 'civicrm_contact';
         $logDAO->entity_id = $id;
         $logDAO->delete();
         // delete contact participants CRM-12155
         CRM_Event_BAO_Participant::deleteContactParticipant($id);
         // delete contact contributions CRM-12155
         CRM_Contribute_BAO_Contribution::deleteContactContribution($id);
         // do activity cleanup, CRM-5604
         CRM_Activity_BAO_Activity::cleanupActivity($id);
         // delete all notes related to contact
         CRM_Core_BAO_Note::cleanContactNotes($id);
         // delete cases related to contact
         $contactCases = CRM_Case_BAO_Case::retrieveCaseIdsByContactId($id);
         if (!empty($contactCases)) {
             foreach ($contactCases as $caseId) {
                 //check if case is associate with other contact or not.
                 $caseContactId = CRM_Case_BAO_Case::getCaseClients($caseId);
                 if (count($caseContactId) <= 1) {
                     CRM_Case_BAO_Case::deleteCase($caseId);
                 }
             }
         }
         $contact->delete();
     } else {
         self::contactTrashRestore($contact);
     }
     //delete the contact id from recently view
     CRM_Utils_Recent::delContact($id);
     // Update the group contact cache
     if ($restore) {
         CRM_Contact_BAO_GroupContactCache::remove();
     } else {
         CRM_Contact_BAO_GroupContactCache::removeContact($id);
     }
     // delete any dupe cache entry
     CRM_Core_BAO_PrevNextCache::deleteItem($id);
     $transaction->commit();
     if ($skipUndelete) {
         CRM_Utils_Hook::post('delete', $contactType, $contact->id, $contact);
     }
     // also reset the DB_DO global array so we can reuse the memory
     // http://issues.civicrm.org/jira/browse/CRM-4387
     CRM_Core_DAO::freeResult();
     return TRUE;
 }
Esempio n. 4
0
 function buildPrevNextCache($sort)
 {
     //for prev/next pagination
     $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     if (!$crmPID) {
         $cacheKey = "civicrm search {$this->_key}";
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
         $sql = $this->_query->searchQuery(0, 0, $sort, FALSE, FALSE, FALSE, FALSE, TRUE, $this->_campaignWhereClause, NULL, $this->_campaignFromClause);
         list($select, $from) = explode(' FROM ', $sql);
         $insertSQL = "\nINSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cacheKey, data )\nSELECT 'civicrm_contact', contact_a.id, contact_a.id, '{$cacheKey}', contact_a.display_name\nFROM {$from}\n";
         CRM_Core_Error::ignoreException();
         $result = CRM_Core_DAO::executeQuery($insertSQL);
         CRM_Core_Error::setCallback();
         if (is_a($result, 'DB_Error')) {
             return;
         }
         // also record an entry in the cache key table, so we can delete it periodically
         CRM_Core_BAO_Cache::setItem($cacheKey, 'CiviCRM Search PrevNextCache', $cacheKey);
     }
 }
Esempio n. 5
0
 /**
  * Process the form submission.
  *
  *
  * @return void
  */
 public function postProcess()
 {
     $values = $this->exportValues();
     //FIXME: Handle logic to replace is_default column by usage
     // reset used column to General (since there can only
     // be one 'Supervised' or 'Unsupervised' rule)
     if ($values['used'] != 'General') {
         $query = "\nUPDATE civicrm_dedupe_rule_group\n   SET used = 'General'\n WHERE contact_type = %1\n   AND used = %2";
         $queryParams = array(1 => array($this->_contactType, 'String'), 2 => array($values['used'], 'String'));
         CRM_Core_DAO::executeQuery($query, $queryParams);
     }
     $rgDao = new CRM_Dedupe_DAO_RuleGroup();
     if ($this->_action & CRM_Core_Action::UPDATE) {
         $rgDao->id = $this->_rgid;
     }
     $rgDao->title = $values['title'];
     $rgDao->is_reserved = CRM_Utils_Array::value('is_reserved', $values, FALSE);
     $rgDao->used = $values['used'];
     $rgDao->contact_type = $this->_contactType;
     $rgDao->threshold = $values['threshold'];
     $rgDao->save();
     // make sure name is set only during insert
     if ($this->_action & CRM_Core_Action::ADD) {
         // generate name based on title
         $rgDao->name = CRM_Utils_String::titleToVar($values['title']) . "_{$rgDao->id}";
         $rgDao->save();
     }
     // lets skip updating of fields for reserved dedupe group
     if ($rgDao->is_reserved) {
         CRM_Core_Session::setStatus(ts("The rule '%1' has been saved.", array(1 => $rgDao->title)), ts('Saved'), 'success');
         return;
     }
     $ruleDao = new CRM_Dedupe_DAO_Rule();
     $ruleDao->dedupe_rule_group_id = $rgDao->id;
     $ruleDao->delete();
     $ruleDao->free();
     $substrLenghts = array();
     $tables = array();
     $daoObj = new CRM_Core_DAO();
     $database = $daoObj->database();
     for ($count = 0; $count < self::RULES_COUNT; $count++) {
         if (empty($values["where_{$count}"])) {
             continue;
         }
         list($table, $field) = explode('.', CRM_Utils_Array::value("where_{$count}", $values));
         $length = !empty($values["length_{$count}"]) ? CRM_Utils_Array::value("length_{$count}", $values) : NULL;
         $weight = $values["weight_{$count}"];
         if ($table and $field) {
             $ruleDao = new CRM_Dedupe_DAO_Rule();
             $ruleDao->dedupe_rule_group_id = $rgDao->id;
             $ruleDao->rule_table = $table;
             $ruleDao->rule_field = $field;
             $ruleDao->rule_length = $length;
             $ruleDao->rule_weight = $weight;
             $ruleDao->save();
             $ruleDao->free();
             if (!array_key_exists($table, $tables)) {
                 $tables[$table] = array();
             }
             $tables[$table][] = $field;
         }
         // CRM-6245: we must pass table/field/length triples to the createIndexes() call below
         if ($length) {
             if (!isset($substrLenghts[$table])) {
                 $substrLenghts[$table] = array();
             }
             //CRM-13417 to avoid fatal error "Incorrect prefix key; the used key part isn't a string, the used length is longer than the key part, or the storage engine doesn't support unique prefix keys, 1089"
             $schemaQuery = "SELECT * FROM INFORMATION_SCHEMA.COLUMNS\n          WHERE TABLE_SCHEMA = '{$database}' AND\n          TABLE_NAME = '{$table}' AND COLUMN_NAME = '{$field}';";
             $dao = CRM_Core_DAO::executeQuery($schemaQuery);
             if ($dao->fetch()) {
                 // set the length to null for all the fields where prefix length is not supported. eg. int,tinyint,date,enum etc dataTypes.
                 if ($dao->COLUMN_NAME == $field && !in_array($dao->DATA_TYPE, array('char', 'varchar', 'binary', 'varbinary', 'text', 'blob'))) {
                     $length = NULL;
                 } elseif ($dao->COLUMN_NAME == $field && !empty($dao->CHARACTER_MAXIMUM_LENGTH) && $length > $dao->CHARACTER_MAXIMUM_LENGTH) {
                     //set the length to CHARACTER_MAXIMUM_LENGTH in case the length provided by the user is greater than the limit
                     $length = $dao->CHARACTER_MAXIMUM_LENGTH;
                 }
             }
             $substrLenghts[$table][$field] = $length;
         }
     }
     // also create an index for this dedupe rule
     // CRM-3837
     CRM_Utils_Hook::dupeQuery($ruleDao, 'dedupeIndexes', $tables);
     CRM_Core_BAO_SchemaHandler::createIndexes($tables, 'dedupe_index', $substrLenghts);
     //need to clear cache of deduped contacts
     //based on the previous rule
     $cacheKey = "merge {$this->_contactType}_{$this->_rgid}_%";
     CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey);
     CRM_Core_Session::setStatus(ts("The rule '%1' has been saved.", array(1 => $rgDao->title)), ts('Saved'), 'success');
 }
Esempio n. 6
0
 /**
  * Based on the provided two contact_ids and a set of tables, move the belongings of the
  * other contact to the main one - be it Location / CustomFields or Contact .. related info.
  * A superset of moveContactBelongings() function.
  *
  * @param int $mainId
  *   Main contact with whom merge has to happen.
  * @param int $otherId
  *   Duplicate contact which would be deleted after merge operation.
  *
  * @param $migrationInfo
  *
  * @return bool
  */
 public static function moveAllBelongings($mainId, $otherId, $migrationInfo)
 {
     if (empty($migrationInfo)) {
         return FALSE;
     }
     $qfZeroBug = 'e8cddb72-a257-11dc-b9cc-0016d3330ee9';
     $relTables = CRM_Dedupe_Merger::relTables();
     $moveTables = $locBlocks = $tableOperations = array();
     foreach ($migrationInfo as $key => $value) {
         if ($value == $qfZeroBug) {
             $value = '0';
         }
         if ((in_array(substr($key, 5), CRM_Dedupe_Merger::getContactFields()) || substr($key, 0, 12) == 'move_custom_') && $value != NULL) {
             $submitted[substr($key, 5)] = $value;
         } elseif (substr($key, 0, 14) == 'move_location_' and $value != NULL) {
             $locField = explode('_', $key);
             $fieldName = $locField[2];
             $fieldCount = $locField[3];
             $operation = CRM_Utils_Array::value('operation', $migrationInfo['location'][$fieldName][$fieldCount]);
             // default operation is overwrite.
             if (!$operation) {
                 $operation = 2;
             }
             $locBlocks[$fieldName][$fieldCount]['operation'] = $operation;
             $locBlocks[$fieldName][$fieldCount]['locTypeId'] = CRM_Utils_Array::value('locTypeId', $migrationInfo['location'][$fieldName][$fieldCount]);
         } elseif (substr($key, 0, 15) == 'move_rel_table_' and $value == '1') {
             $moveTables = array_merge($moveTables, $relTables[substr($key, 5)]['tables']);
             if (array_key_exists('operation', $migrationInfo)) {
                 foreach ($relTables[substr($key, 5)]['tables'] as $table) {
                     if (array_key_exists($key, $migrationInfo['operation'])) {
                         $tableOperations[$table] = $migrationInfo['operation'][$key];
                     }
                 }
             }
         }
     }
     // **** Do location related migration:
     if (!empty($locBlocks)) {
         $locComponent = array('email' => 'Email', 'phone' => 'Phone', 'im' => 'IM', 'openid' => 'OpenID', 'address' => 'Address');
         $primaryBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mainId, array('is_primary' => 1));
         $billingBlockIds = CRM_Contact_BAO_Contact::getLocBlockIds($mainId, array('is_billing' => 1));
         foreach ($locBlocks as $name => $block) {
             if (!is_array($block) || CRM_Utils_System::isNull($block)) {
                 continue;
             }
             $daoName = 'CRM_Core_DAO_' . $locComponent[$name];
             $primaryDAOId = array_key_exists($name, $primaryBlockIds) ? array_pop($primaryBlockIds[$name]) : NULL;
             $billingDAOId = array_key_exists($name, $billingBlockIds) ? array_pop($billingBlockIds[$name]) : NULL;
             foreach ($block as $blkCount => $values) {
                 $locTypeId = CRM_Utils_Array::value('locTypeId', $values, 1);
                 $operation = CRM_Utils_Array::value('operation', $values, 2);
                 $otherBlockId = CRM_Utils_Array::value($blkCount, $migrationInfo['other_details']['loc_block_ids'][$name]);
                 // keep 1-1 mapping for address - loc type.
                 $idKey = $blkCount;
                 if (array_key_exists($name, $locComponent)) {
                     $idKey = $locTypeId;
                 }
                 if (isset($migrationInfo['main_details']['loc_block_ids'][$name])) {
                     $mainBlockId = CRM_Utils_Array::value($idKey, $migrationInfo['main_details']['loc_block_ids'][$name]);
                 }
                 if (!$otherBlockId) {
                     continue;
                 }
                 // for the block which belongs to other-contact, link the contact to main-contact
                 $otherBlockDAO = new $daoName();
                 $otherBlockDAO->id = $otherBlockId;
                 $otherBlockDAO->contact_id = $mainId;
                 $otherBlockDAO->location_type_id = $locTypeId;
                 // if main contact already has primary & billing, set the flags to 0.
                 if ($primaryDAOId) {
                     $otherBlockDAO->is_primary = 0;
                 }
                 if ($billingDAOId) {
                     $otherBlockDAO->is_billing = 0;
                 }
                 // overwrite - need to delete block which belongs to main-contact.
                 if (isset($mainBlockId) && $mainBlockId && $operation == 2) {
                     $deleteDAO = new $daoName();
                     $deleteDAO->id = $mainBlockId;
                     $deleteDAO->find(TRUE);
                     // if we about to delete a primary / billing block, set the flags for new block
                     // that we going to assign to main-contact
                     if ($primaryDAOId && $primaryDAOId == $deleteDAO->id) {
                         $otherBlockDAO->is_primary = 1;
                     }
                     if ($billingDAOId && $billingDAOId == $deleteDAO->id) {
                         $otherBlockDAO->is_billing = 1;
                     }
                     $deleteDAO->delete();
                     $deleteDAO->free();
                 }
                 $otherBlockDAO->update();
                 $otherBlockDAO->free();
             }
         }
     }
     // **** Do tables related migrations
     if (!empty($moveTables)) {
         CRM_Dedupe_Merger::moveContactBelongings($mainId, $otherId, $moveTables, $tableOperations);
         unset($moveTables, $tableOperations);
     }
     // **** Do contact related migrations
     CRM_Dedupe_Merger::moveContactBelongings($mainId, $otherId);
     // FIXME: fix gender, prefix and postfix, so they're edible by createProfileContact()
     $names['gender'] = array('newName' => 'gender_id', 'groupName' => 'gender');
     $names['individual_prefix'] = array('newName' => 'prefix_id', 'groupName' => 'individual_prefix');
     $names['individual_suffix'] = array('newName' => 'suffix_id', 'groupName' => 'individual_suffix');
     $names['communication_style'] = array('newName' => 'communication_style_id', 'groupName' => 'communication_style');
     $names['addressee'] = array('newName' => 'addressee_id', 'groupName' => 'addressee');
     $names['email_greeting'] = array('newName' => 'email_greeting_id', 'groupName' => 'email_greeting');
     $names['postal_greeting'] = array('newName' => 'postal_greeting_id', 'groupName' => 'postal_greeting');
     CRM_Core_OptionGroup::lookupValues($submitted, $names, TRUE);
     // fix custom fields so they're edible by createProfileContact()
     static $treeCache = array();
     if (!array_key_exists($migrationInfo['main_details']['contact_type'], $treeCache)) {
         $treeCache[$migrationInfo['main_details']['contact_type']] = CRM_Core_BAO_CustomGroup::getTree($migrationInfo['main_details']['contact_type'], CRM_Core_DAO::$_nullObject, NULL, -1);
     }
     $cgTree =& $treeCache[$migrationInfo['main_details']['contact_type']];
     $cFields = array();
     foreach ($cgTree as $key => $group) {
         if (!isset($group['fields'])) {
             continue;
         }
         foreach ($group['fields'] as $fid => $field) {
             $cFields[$fid]['attributes'] = $field;
         }
     }
     if (!isset($submitted)) {
         $submitted = array();
     }
     foreach ($submitted as $key => $value) {
         if (substr($key, 0, 7) == 'custom_') {
             $fid = (int) substr($key, 7);
             if (empty($cFields[$fid])) {
                 continue;
             }
             $htmlType = $cFields[$fid]['attributes']['html_type'];
             switch ($htmlType) {
                 case 'File':
                     $customFiles[] = $fid;
                     unset($submitted["custom_{$fid}"]);
                     break;
                 case 'Select Country':
                 case 'Select State/Province':
                     $submitted[$key] = CRM_Core_BAO_CustomField::getDisplayValue($value, $fid, $cFields);
                     break;
                 case 'CheckBox':
                 case 'AdvMulti-Select':
                 case 'Multi-Select':
                 case 'Multi-Select Country':
                 case 'Multi-Select State/Province':
                     // Merge values from both contacts for multivalue fields, CRM-4385
                     // get the existing custom values from db.
                     $customParams = array('entityID' => $mainId, $key => TRUE);
                     $customfieldValues = CRM_Core_BAO_CustomValueTable::getValues($customParams);
                     if (!empty($customfieldValues[$key])) {
                         $existingValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $customfieldValues[$key]);
                         if (is_array($existingValue) && !empty($existingValue)) {
                             $mergeValue = $submmtedCustomValue = array();
                             if ($value) {
                                 $submmtedCustomValue = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
                             }
                             //hack to remove null and duplicate values from array.
                             foreach (array_merge($submmtedCustomValue, $existingValue) as $k => $v) {
                                 if ($v != '' && !in_array($v, $mergeValue)) {
                                     $mergeValue[] = $v;
                                 }
                             }
                             //keep state and country as array format.
                             //for checkbox and m-select format w/ VALUE_SEPARATOR
                             if (in_array($htmlType, array('CheckBox', 'Multi-Select', 'AdvMulti-Select'))) {
                                 $submitted[$key] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, $mergeValue) . CRM_Core_DAO::VALUE_SEPARATOR;
                             } else {
                                 $submitted[$key] = $mergeValue;
                             }
                         }
                     } elseif (in_array($htmlType, array('Multi-Select Country', 'Multi-Select State/Province'))) {
                         //we require submitted values should be in array format
                         if ($value) {
                             $mergeValueArray = explode(CRM_Core_DAO::VALUE_SEPARATOR, $value);
                             //hack to remove null values from array.
                             $mergeValue = array();
                             foreach ($mergeValueArray as $k => $v) {
                                 if ($v != '') {
                                     $mergeValue[] = $v;
                                 }
                             }
                             $submitted[$key] = $mergeValue;
                         }
                     }
                     break;
                 default:
                     break;
             }
         }
     }
     // **** Do file custom fields related migrations
     // FIXME: move this someplace else (one of the BAOs) after discussing
     // where to, and whether CRM_Core_BAO_File::deleteFileReferences() shouldn't actually,
     // like, delete a file...
     if (!isset($customFiles)) {
         $customFiles = array();
     }
     foreach ($customFiles as $customId) {
         list($tableName, $columnName, $groupID) = CRM_Core_BAO_CustomField::getTableColumnGroup($customId);
         // get the contact_id -> file_id mapping
         $fileIds = array();
         $sql = "SELECT entity_id, {$columnName} AS file_id FROM {$tableName} WHERE entity_id IN ({$mainId}, {$otherId})";
         $dao = CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
         while ($dao->fetch()) {
             $fileIds[$dao->entity_id] = $dao->file_id;
         }
         $dao->free();
         // delete the main contact's file
         if (!empty($fileIds[$mainId])) {
             CRM_Core_BAO_File::deleteFileReferences($fileIds[$mainId], $mainId, $customId);
         }
         // move the other contact's file to main contact
         //NYSS need to INSERT or UPDATE depending on whether main contact has an existing record
         if (CRM_Core_DAO::singleValueQuery("SELECT id FROM {$tableName} WHERE entity_id = {$mainId}")) {
             $sql = "UPDATE {$tableName} SET {$columnName} = {$fileIds[$otherId]} WHERE entity_id = {$mainId}";
         } else {
             $sql = "INSERT INTO {$tableName} ( entity_id, {$columnName} ) VALUES ( {$mainId}, {$fileIds[$otherId]} )";
         }
         CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
         if (CRM_Core_DAO::singleValueQuery("\n        SELECT id\n        FROM civicrm_entity_file\n        WHERE entity_table = '{$tableName}' AND file_id = {$fileIds[$otherId]}")) {
             $sql = "\n          UPDATE civicrm_entity_file\n          SET entity_id = {$mainId}\n          WHERE entity_table = '{$tableName}' AND file_id = {$fileIds[$otherId]}";
         } else {
             $sql = "\n          INSERT INTO civicrm_entity_file ( entity_table, entity_id, file_id )\n          VALUES ( '{$tableName}', {$mainId}, {$fileIds[$otherId]} )";
         }
         CRM_Core_DAO::executeQuery($sql, CRM_Core_DAO::$_nullArray);
     }
     // move view only custom fields CRM-5362
     $viewOnlyCustomFields = array();
     foreach ($submitted as $key => $value) {
         $fid = (int) substr($key, 7);
         if (array_key_exists($fid, $cFields) && !empty($cFields[$fid]['attributes']['is_view'])) {
             $viewOnlyCustomFields[$key] = $value;
         }
     }
     // special case to set values for view only, CRM-5362
     if (!empty($viewOnlyCustomFields)) {
         $viewOnlyCustomFields['entityID'] = $mainId;
         CRM_Core_BAO_CustomValueTable::setValues($viewOnlyCustomFields);
     }
     // **** Delete other contact & update prev-next caching
     $otherParams = array('contact_id' => $otherId, 'id' => $otherId, 'version' => 3);
     if (CRM_Core_Permission::check('merge duplicate contacts') && CRM_Core_Permission::check('delete contacts')) {
         // if ext id is submitted then set it null for contact to be deleted
         if (!empty($submitted['external_identifier'])) {
             $query = "UPDATE civicrm_contact SET external_identifier = null WHERE id = {$otherId}";
             CRM_Core_DAO::executeQuery($query);
         }
         civicrm_api('contact', 'delete', $otherParams);
         CRM_Core_BAO_PrevNextCache::deleteItem($otherId);
     }
     // FIXME: else part
     /*         else { */
     /*             CRM_Core_Session::setStatus( ts('Do not have sufficient permission to delete duplicate contact.') ); */
     /*         } */
     // CRM-15681 merge sub_types
     if ($other_sub_types = CRM_Utils_array::value('contact_sub_type', $migrationInfo['other_details'])) {
         if ($main_sub_types = CRM_Utils_array::value('contact_sub_type', $migrationInfo['main_details'])) {
             $submitted['contact_sub_type'] = array_unique(array_merge($main_sub_types, $other_sub_types));
         } else {
             $submitted['contact_sub_type'] = $other_sub_types;
         }
     }
     // **** Update contact related info for the main contact
     if (!empty($submitted)) {
         $submitted['contact_id'] = $mainId;
         //update current employer field
         if ($currentEmloyerId = CRM_Utils_Array::value('current_employer_id', $submitted)) {
             if (!CRM_Utils_System::isNull($currentEmloyerId)) {
                 $submitted['current_employer'] = $submitted['current_employer_id'];
             } else {
                 $submitted['current_employer'] = '';
             }
             unset($submitted['current_employer_id']);
         }
         //CRM-14312 include prefix/suffix from mainId if not overridden for proper construction of display/sort name
         if (!isset($submitted['prefix_id']) && !empty($migrationInfo['main_details']['prefix_id'])) {
             $submitted['prefix_id'] = $migrationInfo['main_details']['prefix_id'];
         }
         if (!isset($submitted['suffix_id']) && !empty($migrationInfo['main_details']['suffix_id'])) {
             $submitted['suffix_id'] = $migrationInfo['main_details']['suffix_id'];
         }
         CRM_Contact_BAO_Contact::createProfileContact($submitted, CRM_Core_DAO::$_nullArray, $mainId);
         unset($submitted);
     }
     CRM_Utils_Hook::post('merge', 'Contact', $mainId, CRM_Core_DAO::$_nullObject);
     return TRUE;
 }
Esempio n. 7
0
 /**
  * Clear the contact cache so things are kosher. We started off being super aggressive with clearing
  * caches, but are backing off from this with every release. Compromise between ease of coding versus
  * performance versus being accurate at that very instant
  *
  * @param $contactID
  *   The contactID that was edited / deleted.
  */
 public static function clearContactCaches($contactID = NULL)
 {
     // clear acl cache if any.
     CRM_ACL_BAO_Cache::resetCache();
     if (empty($contactID)) {
         // also clear prev/next dedupe cache - if no contactID passed in
         CRM_Core_BAO_PrevNextCache::deleteItem();
     }
     CRM_Contact_BAO_GroupContactCache::opportunisticCacheFlush();
 }
Esempio n. 8
0
 /**
  * Browse all rule groups.
  */
 public function run()
 {
     $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE, 0);
     $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 0);
     $context = CRM_Utils_Request::retrieve('context', 'String', $this);
     $limit = CRM_Utils_Request::retrieve('limit', 'Integer', $this);
     $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive');
     $urlQry = "reset=1&rgid={$rgid}&gid={$gid}&limit={$limit}";
     $this->assign('urlQuery', $urlQry);
     $session = CRM_Core_Session::singleton();
     $contactIds = $session->get('selectedSearchContactIds');
     if ($context == 'search' || !empty($contactIds)) {
         $context = 'search';
         $this->assign('backURL', $session->readUserContext());
     }
     if ($action & CRM_Core_Action::RENEW) {
         // empty cache
         if ($rgid) {
             CRM_Core_BAO_PrevNextCache::deleteItem(NULL, CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid));
         }
         CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update"));
     } elseif ($action & CRM_Core_Action::MAP) {
         // do a batch merge if requested
         $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', TRUE, 75);
         $skippedCount = CRM_Utils_Request::retrieve('skipped', 'Positive', $this, FALSE, 0);
         $skippedCount = $skippedCount + count($result['skipped']);
         $mergedCount = CRM_Utils_Request::retrieve('merged', 'Positive', $this, FALSE, 0);
         $mergedCount = $mergedCount + count($result['merged']);
         if (empty($result['merged']) && empty($result['skipped'])) {
             $message = '';
             if ($mergedCount >= 1) {
                 $message = ts("%1 pairs of duplicates were merged", array(1 => $mergedCount));
             }
             if ($skippedCount >= 1) {
                 $message = $message ? "{$message} and " : '';
                 $message .= ts("%1 pairs of duplicates were skipped due to conflict", array(1 => $skippedCount));
             }
             $message .= ts(" during the batch merge process with safe mode.");
             CRM_Core_Session::setStatus($message, ts('Merge Complete'), 'success');
             CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update"));
         } else {
             $urlQry .= "&action=map&skipped={$skippedCount}&merged={$mergedCount}";
             CRM_Utils_System::jsRedirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry), ts('Batch Merge Task in progress'), ts('The batch merge task is still in progress. This page will be refreshed automatically.'));
         }
     }
     if ($action & CRM_Core_Action::UPDATE || $action & CRM_Core_Action::BROWSE) {
         $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0);
         $this->action = CRM_Core_Action::UPDATE;
         $urlQry .= '&snippet=4';
         if ($context == 'conflicts') {
             $urlQry .= "&selected=1";
         }
         $this->assign('sourceUrl', CRM_Utils_System::url('civicrm/ajax/dedupefind', $urlQry, FALSE, NULL, FALSE));
         //reload from cache table
         $cacheKeyString = CRM_Dedupe_Merger::getMergeCacheKeyString($rgid, $gid);
         $stats = CRM_Dedupe_Merger::getMergeStatsMsg($cacheKeyString);
         if ($stats) {
             CRM_Core_Session::setStatus($stats);
             // reset so we not displaying same message again
             CRM_Dedupe_Merger::resetMergeStats($cacheKeyString);
         }
         $join = CRM_Dedupe_Merger::getJoinOnDedupeTable();
         $where = "de.id IS NULL";
         if ($context == 'conflicts') {
             $where .= " AND pn.is_selected = 1";
         }
         $this->_mainContacts = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where);
         if (empty($this->_mainContacts)) {
             if ($context == 'conflicts') {
                 // if the current screen was intended to list only selected contacts, move back to full dupe list
                 CRM_Utils_System::redirect(CRM_Utils_System::url(CRM_Utils_System::currentPath(), $urlQry . '&action=update'));
             }
             if ($gid) {
                 $foundDupes = $this->get("dedupe_dupes_{$gid}");
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupesInGroup($rgid, $gid, $limit);
                 }
                 $this->set("dedupe_dupes_{$gid}", $foundDupes);
             } elseif (!empty($contactIds)) {
                 $foundDupes = $this->get("search_dedupe_dupes_{$gid}");
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIds);
                 }
                 $this->set("search_dedupe_dupes_{$gid}", $foundDupes);
             } else {
                 $foundDupes = $this->get('dedupe_dupes');
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupes($rgid, array(), TRUE, $limit);
                 }
                 $this->set('dedupe_dupes', $foundDupes);
             }
             if (!$foundDupes) {
                 $ruleGroup = new CRM_Dedupe_BAO_RuleGroup();
                 $ruleGroup->id = $rgid;
                 $ruleGroup->find(TRUE);
                 $session = CRM_Core_Session::singleton();
                 $session->setStatus(ts('No possible duplicates were found using %1 rule.', array(1 => $ruleGroup->name)), ts('None Found'), 'info');
                 $url = CRM_Utils_System::url('civicrm/contact/deduperules', 'reset=1');
                 if ($context == 'search') {
                     $url = $session->readUserContext();
                 }
                 CRM_Utils_System::redirect($url);
             } else {
                 $mainContacts = CRM_Dedupe_Finder::parseAndStoreDupePairs($foundDupes, $cacheKeyString);
                 if ($cid) {
                     $this->_cid = $cid;
                 }
                 if ($gid) {
                     $this->_gid = $gid;
                 }
                 $this->_rgid = $rgid;
                 $this->_mainContacts = $mainContacts;
                 $session = CRM_Core_Session::singleton();
                 if ($this->_cid) {
                     $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/deduperules', $urlQry . "&action=update&cid={$this->_cid}"));
                 } else {
                     $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry . "&action=update"));
                 }
             }
         } else {
             if ($cid) {
                 $this->_cid = $cid;
             }
             if ($gid) {
                 $this->_gid = $gid;
             }
             $this->_rgid = $rgid;
         }
         $this->assign('action', $this->action);
         $this->browse();
     } else {
         $this->action = CRM_Core_Action::UPDATE;
         $this->edit($this->action);
         $this->assign('action', $this->action);
     }
     $this->assign('context', $context);
     // parent run
     return parent::run();
 }
Esempio n. 9
0
 /**
  * Delete information about merges for the given string.
  *
  * @param $cacheKeyString
  */
 public static function resetMergeStats($cacheKeyString)
 {
     CRM_Core_BAO_PrevNextCache::deleteItem(NULL, "{$cacheKeyString}_stats");
 }
 function fillupPrevNextCache($sort, $cacheKey = NULL)
 {
     if (!$cacheKey) {
         $cacheKey = "civicrm search {$this->_key}";
     }
     CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
     // lets fill up the prev next cache here, so view can scroll thru
     $sql = $this->_query->searchQuery(0, 0, $sort, FALSE, FALSE, FALSE, TRUE, TRUE, NULL);
     // CRM-9096
     // due to limitations in our search query writer, the above query does not work
     // in cases where the query is being sorted on a non-contact table
     // this results in a fatal error :(
     // see below for the gross hack of trapping the error and not filling
     // the prev next cache in this situation
     // the other alternative of running the FULL query will just be incredibly inefficient
     // and slow things down way too much on large data sets / complex queries
     $insertSQL = "\nINSERT INTO civicrm_prevnext_cache ( entity_table, entity_id1, entity_id2, cacheKey, data )\nSELECT 'civicrm_contact', contact_a.id, contact_a.id, '{$cacheKey}', contact_a.display_name\n";
     $replaceSQL = "SELECT contact_a.id as id";
     $sql = str_replace($replaceSQL, $insertSQL, $sql);
     CRM_Core_Error::ignoreException();
     $result = CRM_Core_DAO::executeQuery($sql);
     CRM_Core_Error::setCallback();
     if (is_a($result, 'DB_Error')) {
         // oops the above query failed, so lets just ignore it
         // and return
         // we print a sorry cant figure it out on view page
         return;
     }
     // also record an entry in the cache key table, so we can delete it periodically
     CRM_Core_BAO_Cache::setItem($cacheKey, 'CiviCRM Search PrevNextCache', $cacheKey);
 }
Esempio n. 11
0
 static function clearContactCaches()
 {
     // clear acl cache if any.
     CRM_ACL_BAO_Cache::resetCache();
     // also clear prev/next dedupe cache
     CRM_Core_BAO_PrevNextCache::deleteItem();
     // reset the group contact cache for this group
     CRM_Contact_BAO_GroupContactCache::remove();
 }
 /**
  * The post processing of the form gets done here.
  *
  * Key things done during post processing are
  *      - check for reset or next request. if present, skip post processing.
  *      - now check if user requested running a saved search, if so, then
  *        the form values associated with the saved search are used for searching.
  *      - if user has done a submit with new values the regular post submission is
  *        done.
  * The processing consists of using a Selector / Controller framework for getting the
  * search results.
  */
 public function postProcess()
 {
     // get user submitted values
     // get it from controller only if form has been submitted, else preProcess has set this
     if (!empty($_POST)) {
         $this->_formValues = $this->controller->exportValues($this->_name);
         $this->normalizeFormValues();
     }
     CRM_Core_BAO_CustomValue::fixCustomFieldValue($this->_formValues);
     $this->_params = CRM_Relationship_BAO_Query::convertFormValues($this->_formValues);
     $this->_returnProperties =& $this->returnProperties();
     if ($this->_done) {
         return;
     }
     $this->_done = TRUE;
     //for prev/next pagination
     $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     if (array_key_exists($this->_searchButtonName, $_POST) || $this->_force && !$crmPID) {
         //reset the cache table for new search
         $cacheKey = "civicrm search {$this->controller->_key}";
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey);
     }
     //get the button name
     $buttonName = $this->controller->getButtonName();
     if (isset($this->_componentMode) && empty($this->_formValues['component_mode'])) {
         $this->_formValues['component_mode'] = $this->_componentMode;
     }
     if (isset($this->_operator) && empty($this->_formValues['operator'])) {
         $this->_formValues['operator'] = $this->_operator;
     }
     if (empty($this->_formValues['qfKey'])) {
         $this->_formValues['qfKey'] = $this->controller->_key;
     }
     $this->set('type', $this->_action);
     $this->set('formValues', $this->_formValues);
     $this->set('queryParams', $this->_params);
     $this->set('returnProperties', $this->_returnProperties);
     if ($buttonName == $this->_actionButtonName) {
         // check actionName and if next, then do not repeat a search, since we are going to the next page
         // hack, make sure we reset the task values
         $stateMachine = $this->controller->getStateMachine();
         $formName = $stateMachine->getTaskFormName();
         $this->controller->resetPage($formName);
         return;
     } else {
         $output = CRM_Core_Selector_Controller::SESSION;
         // create the selector, controller and run - store results in session
         $searchChildGroups = TRUE;
         $setDynamic = FALSE;
         if (strpos(self::$_selectorName, 'CRM_Relationship_Selector') !== FALSE) {
             $selector = new self::$_selectorName($this->_customSearchClass, $this->_formValues, $this->_params, $this->_returnProperties, $this->_action, FALSE, $this->_context, $this->_contextMenu);
             $setDynamic = TRUE;
         } else {
             $selector = new self::$_selectorName($this->_params, $this->_action, NULL, FALSE, NULL, "search", "advanced");
         }
         $selector->setKey($this->controller->_key);
         // added the sorting  character to the form array
         $config = CRM_Core_Config::singleton();
         // do this only for contact search
         $sortID = NULL;
         if ($this->get(CRM_Utils_Sort::SORT_ID)) {
             $sortID = CRM_Utils_Sort::sortIDValue($this->get(CRM_Utils_Sort::SORT_ID), $this->get(CRM_Utils_Sort::SORT_DIRECTION));
         }
         $controller = new CRM_Relationship_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $sortID, CRM_Core_Action::VIEW, $this, $output);
         $controller->setEmbedded(TRUE);
         $controller->setDynamicAction($setDynamic);
         $controller->run();
     }
 }
 /**
  * Delete a contact and all its associated records
  *
  * @param  int  $id id of the contact to delete
  * @param  bool $restore       whether to actually restore, not delete
  * @param  bool $skipUndelete  whether to force contact delete or not
  *
  * @return boolean true if contact deleted, false otherwise
  * @access public
  * @static
  */
 static function deleteContact($id, $restore = FALSE, $skipUndelete = FALSE)
 {
     if (!$id) {
         return FALSE;
     }
     // make sure we have edit permission for this contact
     // before we delete
     if ($skipUndelete && !CRM_Core_Permission::check('delete contacts') || $restore && !CRM_Core_Permission::check('access deleted contacts')) {
         return FALSE;
     }
     // make sure this contact_id does not have any membership types
     $membershipTypeID = CRM_Core_DAO::getFieldValue('CRM_Member_DAO_MembershipType', $id, 'id', 'member_of_contact_id');
     if ($membershipTypeID) {
         return FALSE;
     }
     $contact = new CRM_Contact_DAO_Contact();
     $contact->id = $id;
     if (!$contact->find(TRUE)) {
         return FALSE;
     }
     $contactType = $contact->contact_type;
     $action = $restore ? 'restore' : 'delete';
     CRM_Utils_Hook::pre($action, $contactType, $id, CRM_Core_DAO::$_nullArray);
     if ($restore) {
         self::contactTrashRestore($contact, TRUE);
         CRM_Utils_Hook::post($action, $contactType, $contact->id, $contact);
         return TRUE;
     }
     // currently we only clear employer cache.
     // we are not deleting inherited membership if any.
     if ($contact->contact_type == 'Organization') {
         CRM_Contact_BAO_Contact_Utils::clearAllEmployee($id);
     }
     // start a new transaction
     $transaction = new CRM_Core_Transaction();
     $config = CRM_Core_Config::singleton();
     if ($skipUndelete or !$config->contactUndelete) {
         //delete billing address if exists.
         CRM_Contribute_BAO_Contribution::deleteAddress(NULL, $id);
         // delete the log entries since we dont have triggers enabled as yet
         $logDAO = new CRM_Core_DAO_Log();
         $logDAO->entity_table = 'civicrm_contact';
         $logDAO->entity_id = $id;
         $logDAO->delete();
         // do activity cleanup, CRM-5604
         CRM_Activity_BAO_Activity::cleanupActivity($id);
         // delete all notes related to contact
         CRM_Core_BAO_Note::cleanContactNotes($id);
         $contact->delete();
     } else {
         self::contactTrashRestore($contact);
     }
     //delete the contact id from recently view
     CRM_Utils_Recent::delContact($id);
     // reset the group contact cache for this group
     CRM_Contact_BAO_GroupContactCache::remove();
     // delete any dupe cache entry
     CRM_Core_BAO_PrevNextCache::deleteItem($id);
     $transaction->commit();
     CRM_Utils_Hook::post('delete', $contactType, $contact->id, $contact);
     // also reset the DB_DO global array so we can reuse the memory
     // http://issues.civicrm.org/jira/browse/CRM-4387
     CRM_Core_DAO::freeResult();
     return TRUE;
 }
Esempio n. 14
0
 /**
  * Common post processing.
  */
 public function postProcess()
 {
     /*
      * sometime we do a postProcess early on, so we dont need to repeat it
      * this will most likely introduce some more bugs :(
      */
     if ($this->_done) {
         return;
     }
     $this->_done = TRUE;
     //for prev/next pagination
     $crmPID = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     if (array_key_exists($this->_searchButtonName, $_POST) || $this->_force && !$crmPID) {
         //reset the cache table for new search
         $cacheKey = "civicrm search {$this->controller->_key}";
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey);
     }
     //get the button name
     $buttonName = $this->controller->getButtonName();
     if (isset($this->_ufGroupID) && empty($this->_formValues['uf_group_id'])) {
         $this->_formValues['uf_group_id'] = $this->_ufGroupID;
     }
     if (isset($this->_componentMode) && empty($this->_formValues['component_mode'])) {
         $this->_formValues['component_mode'] = $this->_componentMode;
     }
     if (isset($this->_operator) && empty($this->_formValues['operator'])) {
         $this->_formValues['operator'] = $this->_operator;
     }
     if (empty($this->_formValues['qfKey'])) {
         $this->_formValues['qfKey'] = $this->controller->_key;
     }
     if (!CRM_Core_Permission::check('access deleted contacts')) {
         unset($this->_formValues['deleted_contacts']);
     }
     $this->set('type', $this->_action);
     $this->set('formValues', $this->_formValues);
     $this->set('queryParams', $this->_params);
     $this->set('returnProperties', $this->_returnProperties);
     if ($buttonName == $this->_actionButtonName) {
         // check actionName and if next, then do not repeat a search, since we are going to the next page
         // hack, make sure we reset the task values
         $stateMachine = $this->controller->getStateMachine();
         $formName = $stateMachine->getTaskFormName();
         $this->controller->resetPage($formName);
         return;
     } else {
         $output = CRM_Core_Selector_Controller::SESSION;
         // create the selector, controller and run - store results in session
         $searchChildGroups = TRUE;
         if ($this->get('isAdvanced')) {
             $searchChildGroups = FALSE;
         }
         $setDynamic = FALSE;
         if (strpos(self::$_selectorName, 'CRM_Contact_Selector') !== FALSE) {
             $selector = new self::$_selectorName($this->_customSearchClass, $this->_formValues, $this->_params, $this->_returnProperties, $this->_action, FALSE, $searchChildGroups, $this->_context, $this->_contextMenu);
             $setDynamic = TRUE;
         } else {
             $selector = new self::$_selectorName($this->_params, $this->_action, NULL, FALSE, NULL, "search", "advanced");
         }
         $selector->setKey($this->controller->_key);
         // added the sorting  character to the form array
         $config = CRM_Core_Config::singleton();
         // do this only for contact search
         if ($setDynamic && $config->includeAlphabeticalPager) {
             // Don't recompute if we are just paging/sorting
             if ($this->_reset || empty($_GET['crmPID']) && empty($_GET['crmSID']) && !$this->_sortByCharacter) {
                 $aToZBar = CRM_Utils_PagerAToZ::getAToZBar($selector, $this->_sortByCharacter);
                 $this->set('AToZBar', $aToZBar);
             }
         }
         $sortID = NULL;
         if ($this->get(CRM_Utils_Sort::SORT_ID)) {
             $sortID = CRM_Utils_Sort::sortIDValue($this->get(CRM_Utils_Sort::SORT_ID), $this->get(CRM_Utils_Sort::SORT_DIRECTION));
         }
         $controller = new CRM_Contact_Selector_Controller($selector, $this->get(CRM_Utils_Pager::PAGE_ID), $sortID, CRM_Core_Action::VIEW, $this, $output);
         $controller->setEmbedded(TRUE);
         $controller->setDynamicAction($setDynamic);
         $controller->run();
     }
 }
Esempio n. 15
0
 /**
  * Browse all rule groups.
  */
 public function run()
 {
     $gid = CRM_Utils_Request::retrieve('gid', 'Positive', $this, FALSE, 0);
     $action = CRM_Utils_Request::retrieve('action', 'String', $this, FALSE, 0);
     $context = CRM_Utils_Request::retrieve('context', 'String', $this);
     $session = CRM_Core_Session::singleton();
     $contactIds = $session->get('selectedSearchContactIds');
     if ($context == 'search' || !empty($contactIds)) {
         $context = 'search';
         $this->assign('backURL', $session->readUserContext());
     }
     if ($action & CRM_Core_Action::RENEW) {
         // empty cache
         $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE, 0);
         if ($rgid) {
             $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
             $cacheKeyString = "merge {$contactType}";
             $cacheKeyString .= $rgid ? "_{$rgid}" : '_0';
             $cacheKeyString .= $gid ? "_{$gid}" : '_0';
             CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKeyString);
         }
         $urlQry = "reset=1&action=update&rgid={$rgid}";
         if ($gid) {
             $urlQry .= "&gid={$gid}";
         }
         CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
     } elseif ($action & CRM_Core_Action::MAP) {
         // do a batch merge if requested
         $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE, 0);
         $result = CRM_Dedupe_Merger::batchMerge($rgid, $gid, 'safe', TRUE, 75);
         $skippedCount = CRM_Utils_Request::retrieve('skipped', 'Positive', $this, FALSE, 0);
         $skippedCount = $skippedCount + count($result['skipped']);
         $mergedCount = CRM_Utils_Request::retrieve('merged', 'Positive', $this, FALSE, 0);
         $mergedCount = $mergedCount + count($result['merged']);
         if (empty($result['merged']) && empty($result['skipped'])) {
             $message = '';
             if ($mergedCount >= 1) {
                 $message = ts("%1 pairs of duplicates were merged", array(1 => $mergedCount));
             }
             if ($skippedCount >= 1) {
                 $message = $message ? "{$message} and " : '';
                 $message .= ts("%1 pairs of duplicates were skipped due to conflict", array(1 => $skippedCount));
             }
             $message .= ts(" during the batch merge process with safe mode.");
             CRM_Core_Session::setStatus($message, ts('Merge Complete'), 'success');
             $urlQry = "reset=1&action=update&rgid={$rgid}";
             if ($gid) {
                 $urlQry .= "&gid={$gid}";
             }
             CRM_Utils_System::redirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry));
         } else {
             $urlQry = "reset=1&action=map&rgid={$rgid}";
             if ($gid) {
                 $urlQry .= "&gid={$gid}";
             }
             $urlQry .= "&skipped={$skippedCount}&merged={$mergedCount}";
             CRM_Utils_System::jsRedirect(CRM_Utils_System::url('civicrm/contact/dedupefind', $urlQry), ts('Batch Merge Task in progress'), ts('The batch merge task is still in progress. This page will be refreshed automatically.'));
         }
     }
     if ($action & CRM_Core_Action::UPDATE || $action & CRM_Core_Action::BROWSE) {
         $cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this, FALSE, 0);
         $rgid = CRM_Utils_Request::retrieve('rgid', 'Positive', $this, FALSE, 0);
         $this->action = CRM_Core_Action::UPDATE;
         //calculate the $contactType
         if ($rgid) {
             $contactType = CRM_Core_DAO::getFieldValue('CRM_Dedupe_DAO_RuleGroup', $rgid, 'contact_type');
         }
         $sourceParams = 'snippet=4';
         if ($gid) {
             $sourceParams .= "&gid={$gid}";
         }
         if ($rgid) {
             $sourceParams .= "&rgid={$rgid}";
         }
         if ($context == 'conflicts') {
             $sourceParams .= "&selected=1";
         }
         $this->assign('sourceUrl', CRM_Utils_System::url('civicrm/ajax/dedupefind', $sourceParams, FALSE, NULL, FALSE));
         //reload from cache table
         $cacheKeyString = "merge {$contactType}";
         $cacheKeyString .= $rgid ? "_{$rgid}" : '_0';
         $cacheKeyString .= $gid ? "_{$gid}" : '_0';
         $stats = CRM_Dedupe_Merger::getMergeStatsMsg($cacheKeyString);
         if ($stats) {
             CRM_Core_Session::setStatus($stats);
             // reset so we not displaying same message again
             CRM_Dedupe_Merger::resetMergeStats($cacheKeyString);
         }
         $join = "LEFT JOIN civicrm_dedupe_exception de ON ( pn.entity_id1 = de.contact_id1 AND\n                                                                 pn.entity_id2 = de.contact_id2 )";
         $where = "de.id IS NULL";
         if ($context == 'conflicts') {
             $where .= " AND pn.is_selected = 1";
         }
         $this->_mainContacts = CRM_Core_BAO_PrevNextCache::retrieve($cacheKeyString, $join, $where);
         if (empty($this->_mainContacts)) {
             if ($context == 'conflicts') {
                 // if the current screen was intended to list only selected contacts, move back to full dupe list
                 $sourceParams = 'reset=1&action=update';
                 if ($gid) {
                     $sourceParams .= "&gid={$gid}";
                 }
                 if ($rgid) {
                     $sourceParams .= "&rgid={$rgid}";
                 }
                 CRM_Utils_System::redirect(CRM_Utils_System::url(CRM_Utils_System::currentPath(), $sourceParams));
             }
             if ($gid) {
                 $foundDupes = $this->get("dedupe_dupes_{$gid}");
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupesInGroup($rgid, $gid);
                 }
                 $this->set("dedupe_dupes_{$gid}", $foundDupes);
             } elseif (!empty($contactIds)) {
                 $foundDupes = $this->get("search_dedupe_dupes_{$gid}");
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupes($rgid, $contactIds);
                 }
                 $this->get("search_dedupe_dupes_{$gid}", $foundDupes);
             } else {
                 $foundDupes = $this->get('dedupe_dupes');
                 if (!$foundDupes) {
                     $foundDupes = CRM_Dedupe_Finder::dupes($rgid);
                 }
                 $this->set('dedupe_dupes', $foundDupes);
             }
             if (!$foundDupes) {
                 $ruleGroup = new CRM_Dedupe_BAO_RuleGroup();
                 $ruleGroup->id = $rgid;
                 $ruleGroup->find(TRUE);
                 $session = CRM_Core_Session::singleton();
                 $session->setStatus(ts('No possible duplicates were found using %1 rule.', array(1 => $ruleGroup->name)), ts('None Found'), 'info');
                 $url = CRM_Utils_System::url('civicrm/contact/deduperules', 'reset=1');
                 if ($context == 'search') {
                     $url = $session->readUserContext();
                 }
                 CRM_Utils_System::redirect($url);
             } else {
                 $cids = array();
                 foreach ($foundDupes as $dupe) {
                     $cids[$dupe[0]] = 1;
                     $cids[$dupe[1]] = 1;
                 }
                 $cidString = implode(', ', array_keys($cids));
                 $sql = "SELECT id, display_name FROM civicrm_contact WHERE id IN ({$cidString}) ORDER BY sort_name";
                 $dao = new CRM_Core_DAO();
                 $dao->query($sql);
                 $displayNames = array();
                 while ($dao->fetch()) {
                     $displayNames[$dao->id] = $dao->display_name;
                 }
                 // FIXME: sort the contacts; $displayName
                 // is already sort_name-sorted, so use that
                 // (also, consider sorting by dupe count first)
                 // lobo - change the sort to by threshold value
                 // so the more likely dupes are sorted first
                 $session = CRM_Core_Session::singleton();
                 $userId = $session->get('userID');
                 $mainContacts = $permission = array();
                 foreach ($foundDupes as $dupes) {
                     $srcID = $dupes[0];
                     $dstID = $dupes[1];
                     if ($dstID == $userId) {
                         $srcID = $dupes[1];
                         $dstID = $dupes[0];
                     }
                     /***
                      * Eliminate this since it introduces 3 queries PER merge row
                      * and hence is very expensive
                      * CRM-8822
                      * if ( !array_key_exists( $srcID, $permission ) ) {
                      * $permission[$srcID] = CRM_Contact_BAO_Contact_Permission::allow( $srcID, CRM_Core_Permission::EDIT );
                      * }
                      * if ( !array_key_exists( $dstID, $permission ) ) {
                      * $permission[$dstID] = CRM_Contact_BAO_Contact_Permission::allow( $dstID, CRM_Core_Permission::EDIT );
                      * }
                      *
                      * $canMerge = ( $permission[$dstID] && $permission[$srcID] );
                      *
                      */
                     // we'll do permission checking during the merge process
                     $canMerge = TRUE;
                     $mainContacts[] = $row = array('srcID' => $srcID, 'srcName' => $displayNames[$srcID], 'dstID' => $dstID, 'dstName' => $displayNames[$dstID], 'weight' => $dupes[2], 'canMerge' => $canMerge);
                     $data = CRM_Core_DAO::escapeString(serialize($row));
                     $values[] = " ( 'civicrm_contact', {$srcID}, {$dstID}, '{$cacheKeyString}', '{$data}' ) ";
                 }
                 if ($cid) {
                     $this->_cid = $cid;
                 }
                 if ($gid) {
                     $this->_gid = $gid;
                 }
                 $this->_rgid = $rgid;
                 $this->_mainContacts = $mainContacts;
                 CRM_Core_BAO_PrevNextCache::setItem($values);
                 $session = CRM_Core_Session::singleton();
                 if ($this->_cid) {
                     $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/deduperules', "action=update&rgid={$this->_rgid}&gid={$this->_gid}&cid={$this->_cid}"));
                 } else {
                     $session->pushUserContext(CRM_Utils_System::url('civicrm/contact/dedupefind', "reset=1&action=update&rgid={$this->_rgid}"));
                 }
             }
         } else {
             if ($cid) {
                 $this->_cid = $cid;
             }
             if ($gid) {
                 $this->_gid = $gid;
             }
             $this->_rgid = $rgid;
         }
         $this->assign('action', $this->action);
         $this->browse();
     } else {
         $this->action = CRM_Core_Action::UPDATE;
         $this->edit($this->action);
         $this->assign('action', $this->action);
     }
     $this->assign('context', $context);
     // parent run
     return parent::run();
 }
Esempio n. 16
0
 /**
  * @param $sort
  *
  * @return string
  */
 function buildPrevNextCache($sort)
 {
     $cacheKey = 'civicrm search ' . $this->_key;
     // Get current page requested
     $pageNum = CRM_Utils_Request::retrieve('crmPID', 'Integer', CRM_Core_DAO::$_nullObject);
     // When starting from scratch, clear any old cache
     if (!$pageNum) {
         CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey, 'civicrm_contact');
         $pageNum = 1;
     }
     $pageSize = CRM_Utils_Request::retrieve('crmRowCount', 'Integer', CRM_Core_DAO::$_nullObject, FALSE, 50);
     $firstRecord = ($pageNum - 1) * $pageSize;
     //for alphabetic pagination selection save
     $sortByCharacter = CRM_Utils_Request::retrieve('sortByCharacter', 'String', CRM_Core_DAO::$_nullObject);
     //for text field pagination selection save
     $countRow = CRM_Core_BAO_PrevNextCache::getCount($cacheKey, NULL, "entity_table = 'civicrm_contact'");
     // $sortByCharacter triggers a refresh in the prevNext cache
     if ($sortByCharacter && $sortByCharacter != 'all') {
         $cacheKey .= "_alphabet";
         $this->fillupPrevNextCache($sort, $cacheKey);
     } elseif ($firstRecord >= $countRow) {
         $this->fillupPrevNextCache($sort, $cacheKey, $countRow, 500);
     }
     return $cacheKey;
 }
 /**
  * Function to process the form
  *
  * @access public
  *
  * @return None
  */
 public function postProcess()
 {
     $values = $this->exportValues();
     $isDefault = CRM_Utils_Array::value('is_default', $values, FALSE);
     // reset defaults
     if ($isDefault) {
         $query = "\nUPDATE civicrm_dedupe_rule_group \n   SET is_default = 0\n WHERE contact_type = %1 \n   AND level = %2";
         $queryParams = array(1 => array($this->_contactType, 'String'), 2 => array($values['level'], 'String'));
         CRM_Core_DAO::executeQuery($query, $queryParams);
     }
     $rgDao = new CRM_Dedupe_DAO_RuleGroup();
     if ($this->_action & CRM_Core_Action::UPDATE) {
         $rgDao->id = $this->_rgid;
     }
     $rgDao->title = $values['title'];
     $rgDao->is_reserved = CRM_Utils_Array::value('is_reserved', $values, FALSE);
     $rgDao->is_default = $isDefault;
     $rgDao->level = $values['level'];
     $rgDao->contact_type = $this->_contactType;
     $rgDao->threshold = $values['threshold'];
     $rgDao->save();
     // make sure name is set only during insert
     if ($this->_action & CRM_Core_Action::ADD) {
         // generate name based on title
         $rgDao->name = CRM_Utils_String::titleToVar($values['title']) . "_{$rgDao->id}";
         $rgDao->save();
     }
     // lets skip updating of fields for reserved dedupe group
     if ($rgDao->is_reserved) {
         CRM_Core_Session::setStatus(ts('The rule \'%1\' has been saved.', array(1 => $rgDao->title)));
         return;
     }
     $ruleDao = new CRM_Dedupe_DAO_Rule();
     $ruleDao->dedupe_rule_group_id = $rgDao->id;
     $ruleDao->delete();
     $ruleDao->free();
     $substrLenghts = array();
     $tables = array();
     for ($count = 0; $count < self::RULES_COUNT; $count++) {
         if (!CRM_Utils_Array::value("where_{$count}", $values)) {
             continue;
         }
         list($table, $field) = explode('.', CRM_Utils_Array::value("where_{$count}", $values));
         $length = CRM_Utils_Array::value("length_{$count}", $values) ? CRM_Utils_Array::value("length_{$count}", $values) : NULL;
         $weight = $values["weight_{$count}"];
         if ($table and $field) {
             $ruleDao = new CRM_Dedupe_DAO_Rule();
             $ruleDao->dedupe_rule_group_id = $rgDao->id;
             $ruleDao->rule_table = $table;
             $ruleDao->rule_field = $field;
             $ruleDao->rule_length = $length;
             $ruleDao->rule_weight = $weight;
             $ruleDao->save();
             $ruleDao->free();
             if (!array_key_exists($table, $tables)) {
                 $tables[$table] = array();
             }
             $tables[$table][] = $field;
         }
         // CRM-6245: we must pass table/field/length triples to the createIndexes() call below
         if ($length) {
             if (!isset($substrLenghts[$table])) {
                 $substrLenghts[$table] = array();
             }
             $substrLenghts[$table][$field] = $length;
         }
     }
     // also create an index for this dedupe rule
     // CRM-3837
     CRM_Core_BAO_SchemaHandler::createIndexes($tables, 'dedupe_index', $substrLenghts);
     //need to clear cache of deduped contacts
     //based on the previous rule
     $cacheKey = "merge {$this->_contactType}_{$this->_rgid}_%";
     CRM_Core_BAO_PrevNextCache::deleteItem(NULL, $cacheKey);
     CRM_Core_Session::setStatus(ts('The rule \'%1\' has been saved.', array(1 => $rgDao->title)));
 }