/** * That checks for duplicate contacts. * * @param array $fields * Fields array which are submitted. * @param $errors * @param int $contactID * Contact id. * @param string $contactType * Contact type. */ public static function checkDuplicateContacts(&$fields, &$errors, $contactID, $contactType) { // if this is a forced save, ignore find duplicate rule if (empty($fields['_qf_Contact_upload_duplicate'])) { $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, $contactType); $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $contactType, 'Supervised', array($contactID)); if ($ids) { $contactLinks = CRM_Contact_BAO_Contact_Utils::formatContactIDSToLinks($ids, TRUE, TRUE, $contactID); $duplicateContactsLinks = '<div class="matching-contacts-found">'; $duplicateContactsLinks .= ts('One matching contact was found. ', array('count' => count($contactLinks['rows']), 'plural' => '%count matching contacts were found.<br />')); if ($contactLinks['msg'] == 'view') { $duplicateContactsLinks .= ts('You can View the existing contact', array('count' => count($contactLinks['rows']), 'plural' => 'You can View the existing contacts')); } else { $duplicateContactsLinks .= ts('You can View or Edit the existing contact', array('count' => count($contactLinks['rows']), 'plural' => 'You can View or Edit the existing contacts')); } if ($contactLinks['msg'] == 'merge') { // We should also get a merge link if this is for an existing contact $duplicateContactsLinks .= ts(', or Merge this contact with an existing contact'); } $duplicateContactsLinks .= '.'; $duplicateContactsLinks .= '</div>'; $duplicateContactsLinks .= '<table class="matching-contacts-actions">'; $row = ''; for ($i = 0; $i < count($contactLinks['rows']); $i++) { $row .= ' <tr> '; $row .= ' <td class="matching-contacts-name"> '; $row .= $contactLinks['rows'][$i]['display_name']; $row .= ' </td>'; $row .= ' <td class="matching-contacts-email"> '; $row .= $contactLinks['rows'][$i]['primary_email']; $row .= ' </td>'; $row .= ' <td class="action-items"> '; $row .= $contactLinks['rows'][$i]['view']; $row .= $contactLinks['rows'][$i]['edit']; $row .= CRM_Utils_Array::value('merge', $contactLinks['rows'][$i]); $row .= ' </td>'; $row .= ' </tr> '; } $duplicateContactsLinks .= $row . '</table>'; $duplicateContactsLinks .= ts("If you're sure this record is not a duplicate, click the 'Save Matching Contact' button below."); $errors['_qf_default'] = $duplicateContactsLinks; // let smarty know that there are duplicates $template = CRM_Core_Smarty::singleton(); $template->assign('isDuplicate', 1); } elseif (!empty($fields['_qf_Contact_refresh_dedupe'])) { // add a session message for no matching contacts CRM_Core_Session::setStatus(ts('No matching contact found.'), ts('None Found'), 'info'); } } }
/** * Global form rule. * * @param array $fields * The input form values. * @param array $files * The uploaded files if any. * @param CRM_Core_Form $form * The form object. * * @return bool|array * true if no errors, else array of errors */ public static function formRule($fields, $files, $form) { CRM_Utils_Hook::validateProfile($form->_ufGroup['name']); $errors = array(); // if no values, return if (empty($fields)) { return TRUE; } $register = NULL; // hack we use a -1 in options to indicate that its registration if ($form->_id) { $form->_isUpdateDupe = 1; } if ($form->_mode == CRM_Profile_Form::MODE_REGISTER) { $register = TRUE; } // dont check for duplicates during registration validation: CRM-375 if (!$register && empty($fields['_qf_Edit_upload_duplicate'])) { // fix for CRM-3240 if (!empty($fields['email-Primary'])) { $fields['email'] = CRM_Utils_Array::value('email-Primary', $fields); } // fix for CRM-6141 if (!empty($fields['phone-Primary-1']) && empty($fields['phone-Primary'])) { $fields['phone-Primary'] = $fields['phone-Primary-1']; } $ctype = CRM_Core_BAO_UFGroup::getContactType($form->_gid); // If all profile fields is of Contact Type then consider // profile is of Individual type(default). if (!$ctype) { $ctype = 'Individual'; } $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, $ctype); if ($form->_mode == CRM_Profile_Form::MODE_CREATE) { // fix for CRM-2888 $exceptions = array(); } else { // for edit mode we need to allow our own record to be a dupe match! $exceptions = array($form->_session->get('userID')); } // for dialog mode we should always use fuzzy rule. $ruleType = 'Unsupervised'; if ($form->_context == 'dialog') { $ruleType = 'Supervised'; } $dedupeParams['check_permission'] = FALSE; $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $ctype, $ruleType, $exceptions, $form->_ruleGroupID); if ($ids) { if ($form->_isUpdateDupe == 2) { CRM_Core_Session::setStatus(ts('Note: this contact may be a duplicate of an existing record.'), ts('Possible Duplicate Detected'), 'alert'); } elseif ($form->_isUpdateDupe == 1) { if (!$form->_id) { $form->_id = $ids[0]; } } else { if ($form->_context == 'dialog') { $contactLinks = CRM_Contact_BAO_Contact_Utils::formatContactIDSToLinks($ids, TRUE, TRUE); $duplicateContactsLinks = '<div class="matching-contacts-found">'; $duplicateContactsLinks .= ts('One matching contact was found. ', array('count' => count($contactLinks['rows']), 'plural' => '%count matching contacts were found.<br />')); if ($contactLinks['msg'] == 'view') { $duplicateContactsLinks .= ts('You can View the existing contact.', array('count' => count($contactLinks['rows']), 'plural' => 'You can View the existing contacts.')); } else { $duplicateContactsLinks .= ts('You can View or Edit the existing contact.', array('count' => count($contactLinks['rows']), 'plural' => 'You can View or Edit the existing contacts.')); } $duplicateContactsLinks .= '</div>'; $duplicateContactsLinks .= '<table class="matching-contacts-actions">'; $row = ''; for ($i = 0; $i < count($contactLinks['rows']); $i++) { $row .= ' <tr> '; $row .= ' <td class="matching-contacts-name"> '; $row .= $contactLinks['rows'][$i]['display_name']; $row .= ' </td>'; $row .= ' <td class="matching-contacts-email"> '; $row .= $contactLinks['rows'][$i]['primary_email']; $row .= ' </td>'; $row .= ' <td class="action-items"> '; $row .= $contactLinks['rows'][$i]['view'] . ' '; $row .= $contactLinks['rows'][$i]['edit']; $row .= ' </td>'; $row .= ' </tr> '; } $duplicateContactsLinks .= $row . '</table>'; $duplicateContactsLinks .= "If you're sure this record is not a duplicate, click the 'Save Matching Contact' button below."; $errors['_qf_default'] = $duplicateContactsLinks; // let smarty know that there are duplicates $template = CRM_Core_Smarty::singleton(); $template->assign('isDuplicate', 1); } else { $errors['_qf_default'] = ts('A record already exists with the same information.'); } } } } foreach ($fields as $key => $value) { list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $key, 3); if ($fieldName == 'state_province' && !empty($fields["country-{$locTypeId}"])) { // Validate Country - State list $countryId = $fields["country-{$locTypeId}"]; $stateProvinceId = $value; if ($stateProvinceId && $countryId) { $stateProvinceDAO = new CRM_Core_DAO_StateProvince(); $stateProvinceDAO->id = $stateProvinceId; $stateProvinceDAO->find(TRUE); if ($stateProvinceDAO->country_id != $countryId) { // country mismatch hence display error $stateProvinces = CRM_Core_PseudoConstant::stateProvince(); $countries = CRM_Core_PseudoConstant::country(); $errors[$key] = "State/Province " . $stateProvinces[$stateProvinceId] . " is not part of " . $countries[$countryId] . ". It belongs to " . $countries[$stateProvinceDAO->country_id] . "."; } } } if ($fieldName == 'county' && $fields["state_province-{$locTypeId}"]) { // Validate County - State list $stateProvinceId = $fields["state_province-{$locTypeId}"]; $countyId = $value; if ($countyId && $stateProvinceId) { $countyDAO = new CRM_Core_DAO_County(); $countyDAO->id = $countyId; $countyDAO->find(TRUE); if ($countyDAO->state_province_id != $stateProvinceId) { // state province mismatch hence display error $stateProvinces = CRM_Core_PseudoConstant::stateProvince(); $counties = CRM_Core_PseudoConstant::county(); $errors[$key] = "County " . $counties[$countyId] . " is not part of " . $stateProvinces[$stateProvinceId] . ". It belongs to " . $stateProvinces[$countyDAO->state_province_id] . "."; } } } } foreach (CRM_Contact_BAO_Contact::$_greetingTypes as $greeting) { if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) { $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name'); if ($customizedValue == $greetingType && empty($fields[$greeting . '_custom'])) { $errors[$greeting . '_custom'] = ts('Custom %1 is a required field if %1 is of type Customized.', array(1 => ucwords(str_replace('_', ' ', $greeting)))); } } } return empty($errors) ? TRUE : $errors; }
/** * Function to that checks for duplicate contacts * * @param array $fields fields array which are submitted * @param array $error error message array * @param int $contactID contact id * @param string $contactType contact type */ static function checkDuplicateContacts(&$fields, &$errors, $contactID, $contactType) { // if this is a forced save, ignore find duplicate rule if (!CRM_Utils_Array::value('_qf_Contact_upload_duplicate', $fields)) { require_once 'CRM/Dedupe/Finder.php'; $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, $contactType); $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $contactType, 'Fuzzy', array($contactID)); if ($ids) { $viewUrls = array(); $editUrls = array(); require_once 'CRM/Contact/BAO/Contact/Utils.php'; list($viewUrls, $editUrls, $mergeUrl) = CRM_Contact_BAO_Contact_Utils::formatContactIDSToLinks($ids, true, true, $contactID); $viewUrl = implode(', ', $viewUrls); $editUrl = implode(', ', $editUrls); $errors['_qf_default'] = ts('One matching contact was found.', array('count' => count($editUrls), 'plural' => '%count matching contacts were found.')); $errors['_qf_default'] .= '<br />'; $errors['_qf_default'] .= ts('If you need to verify if this is the same contact, click here - %1 - to VIEW the existing contact in a new tab.', array(1 => $viewUrl, 'count' => count($viewUrls), 'plural' => 'If you need to verify whether one of these is the same contact, click here - %1 - to VIEW the existing contact in a new tab.')); $errors['_qf_default'] .= '<br />'; $errors['_qf_default'] .= ts('If you know the record you are creating is a duplicate, click here - %1 - to EDIT the original record instead.', array(1 => $editUrl)); $errors['_qf_default'] .= '<br />'; //allow to merge with matching contact, CRM-3160 if (!empty($mergeUrl)) { $errors['_qf_default'] .= ts('If you know the record you are editing is a duplicate, click here - %1 - to MERGE with the existing record instead.', array(1 => $mergeUrl)); $errors['_qf_default'] .= '<br />'; } $errors['_qf_default'] .= ts('If you are sure this is NOT a duplicate, click the "Save Matching Contact" button (this button is located at the bottom of the Contact Details section below).'); // let smarty know that there are duplicates $template =& CRM_Core_Smarty::singleton(); $template->assign('isDuplicate', 1); } else { if (CRM_Utils_Array::value('_qf_Contact_refresh_dedupe', $fields)) { // add a session message for no matching contacts CRM_Core_Session::setStatus('No matching contact found.'); } } } }
/** * global form rule * * @param array $fields the input form values * @param array $files the uploaded files if any * @param object $form the form object * * @return true if no errors, else array of errors * @access public * @static */ static function formRule(&$fields, &$files, &$form) { $errors = array(); // if no values, return if (empty($fields)) { return true; } $cid = $register = null; // hack we use a -1 in options to indicate that its registration if ($form->_id) { $cid = $form->_id; $form->_isUpdateDupe = true; } if ($form->_mode == CRM_Profile_Form::MODE_REGISTER) { $register = true; } // dont check for duplicates during registration validation: CRM-375 if (!$register && !CRM_Utils_Array::value('_qf_Edit_upload_duplicate', $fields)) { // fix for CRM-3240 if (CRM_Utils_Array::value('email-Primary', $fields)) { $fields['email'] = CRM_Utils_Array::value('email-Primary', $fields); } $session =& CRM_Core_Session::singleton(); $ctype = CRM_Core_BAO_UFGroup::getContactType($form->_gid); require_once 'CRM/Dedupe/Finder.php'; $dedupeParams = CRM_Dedupe_Finder::formatParams($fields, $ctype); if ($form->_mode == CRM_Profile_Form::MODE_CREATE) { // fix for CRM-2888 $exceptions = array(); } else { // for edit mode we need to allow our own record to be a dupe match! $exceptions = array($session->get('userID')); } // for dialog mode we should always use fuzzy rule. $ruleType = 'Strict'; if ($form->_context == 'dialog') { $ruleType = 'Fuzzy'; } $ids = CRM_Dedupe_Finder::dupesByParams($dedupeParams, $ctype, $ruleType, $exceptions); if ($ids) { if ($form->_isUpdateDupe) { if (!$form->_id) { $form->_id = $ids[0]; } } else { if ($form->_context == 'dialog') { $viewUrls = array(); require_once 'CRM/Contact/BAO/Contact/Utils.php'; list($viewUrls) = CRM_Contact_BAO_Contact_Utils::formatContactIDSToLinks($ids); $viewUrl = implode(', ', $viewUrls); $errors['_qf_default'] = ts('One matching contact was found.', array('count' => count($viewUrls), 'plural' => '%count matching contacts were found.')); $errors['_qf_default'] .= '<br />'; $errors['_qf_default'] .= ts('If you need to verify if this is the same contact, click here - %1 - to VIEW the existing contact in a new tab.', array(1 => $viewUrl, 'count' => count($viewUrls), 'plural' => 'If you need to verify whether one of these is the same contact, click here - %1 - to VIEW the existing contact in a new tab.')); $errors['_qf_default'] .= '<br />'; $errors['_qf_default'] .= ts('If you are sure this is NOT a duplicate, click the Save Matching Contact button to create a new contact record.'); // let smarty know that there are duplicates $template =& CRM_Core_Smarty::singleton(); $template->assign('isDuplicate', 1); } else { $errors['_qf_default'] = ts('A record already exists with the same information.'); } } } } foreach ($fields as $key => $value) { list($fieldName, $locTypeId, $phoneTypeId) = CRM_Utils_System::explode('-', $key, 3); if ($fieldName == 'state_province' && $fields["country-{$locTypeId}"]) { // Validate Country - State list $countryId = $fields["country-{$locTypeId}"]; $stateProvinceId = $value; if ($stateProvinceId && $countryId) { $stateProvinceDAO =& new CRM_Core_DAO_StateProvince(); $stateProvinceDAO->id = $stateProvinceId; $stateProvinceDAO->find(true); if ($stateProvinceDAO->country_id != $countryId) { // country mismatch hence display error $stateProvinces = CRM_Core_PseudoConstant::stateProvince(); $countries =& CRM_Core_PseudoConstant::country(); $errors[$key] = "State/Province " . $stateProvinces[$stateProvinceId] . " is not part of " . $countries[$countryId] . ". It belongs to " . $countries[$stateProvinceDAO->country_id] . "."; } } } if ($fieldName == 'county' && $fields["state_province-{$locTypeId}"]) { // Validate County - State list $stateProvinceId = $fields["state_province-{$locTypeId}"]; $countyId = $value; if ($countyId && $stateProvinceId) { $countyDAO =& new CRM_Core_DAO_County(); $countyDAO->id = $countyId; $countyDAO->find(true); if ($countyDAO->state_province_id != $stateProvinceId) { // state province mismatch hence display error $stateProvinces = CRM_Core_PseudoConstant::stateProvince(); $counties =& CRM_Core_PseudoConstant::county(); $errors[$key] = "County " . $counties[$countyId] . " is not part of " . $stateProvinces[$stateProvinceId] . ". It belongs to " . $stateProvinces[$countyDAO->state_province_id] . "."; } } } } $elements = array('email_greeting' => 'email_greeting_custom', 'postal_greeting' => 'postal_greeting_custom', 'addressee' => 'addressee_custom'); foreach ($elements as $greeting => $customizedGreeting) { if ($greetingType = CRM_Utils_Array::value($greeting, $fields)) { $customizedValue = CRM_Core_OptionGroup::getValue($greeting, 'Customized', 'name'); if ($customizedValue == $greetingType && !CRM_Utils_Array::value($customizedGreeting, $fields)) { $errors[$customizedGreeting] = ts('Custom %1 is a required field if %1 is of type Customized.', array(1 => ucwords(str_replace('_', " ", $greeting)))); } } } return empty($errors) ? true : $errors; }