Skip to content

Commit

Permalink
Revert "Use entity functions to save custom data"
Browse files Browse the repository at this point in the history
  • Loading branch information
colemanw authored Sep 28, 2020
1 parent 9ac482a commit da47b7d
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 20 deletions.
121 changes: 121 additions & 0 deletions includes/wf_crm_webform_base.inc
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,127 @@ abstract class wf_crm_webform_base {
return $values;
}

/**
* Save custom data for an entity
*
* @param $entity
* Array of values
* @param $entity_id
* Numeric id of entity
* @param $entity_type
* Type of crm entity, e.g. "Contact"
* @param $known
* Is this a known record (as opposed to a contact matched via dedupe rules)?
* We only allow saving blank fields for known contacts.
* @param $contact_index
* Contact's index
*/
protected function saveCustomData($entity, $entity_id, $entity_type, $known = TRUE, $contact_index = 1) {
$existing = FALSE;
$params = ['entityID' => $entity_id];
$createMultiValues = [];

foreach ($entity as $table => $values) {
if (substr($table, 0, 2) == 'cg' && is_array($values)) {
if ($existing === FALSE) {
$existing = $this->getCustomData($entity_id, $entity_type, FALSE);
}
$existing += [$table => []];
$insert = 0;

foreach ($values as $valuesIndex => $custom) {
// Match to id of existing record (id will be 0 for non-multi-value custom sets, which is fine)
if ($id = each($existing[$table])) {
$suf = $id['key'];
}
// Create new record(s) using negative numbers
else {
$suf = --$insert;
}

$multivaluesCreateMode = NULL;

// Handle 'Create mode' for multivalues custom fields of Contact entity.
if ($entity_type === 'Contact') {
$createModeKey = 'civicrm_' . $contact_index . '_contact_' . $valuesIndex . '_' . $table . '_createmode';
$multivaluesCreateMode = isset($this->data['config']['create_mode'][$createModeKey]) ? (int) $this->data['config']['create_mode'][$createModeKey] : NULL;
}
$multiValueSuffix = '_' . $suf;

if ($multivaluesCreateMode === self::MULTIVALUE_FIELDSET_MODE_CREATE_ONLY) {
// Using 'Create only' mode we don't need custom value's suffix
// so the value can be added as new instead of updated.
$multiValueSuffix = '';
}

$customGroupParams = [];

foreach ($custom as $k => $v) {
// Only save if this is not blank or data already exists and record is known
if ($v !== '' || ($suf >= 0 && $known)) {
$customGroupParams[$k . $multiValueSuffix] = $v;
}
}

if ($multivaluesCreateMode === self::MULTIVALUE_FIELDSET_MODE_CREATE_ONLY) {
$createMultiValues[] = $customGroupParams;
}
else {
$params = array_merge($params, $customGroupParams);
}
}
}
}

if (count($params) > 1) {
// Update existing values.
$this->saveCustomValues($entity_id, $params);
}

if (!empty($createMultiValues)) {
// Add new values.
foreach ($createMultiValues as $multiValuesSet) {
$this->saveCustomValues($entity_id, array_merge($multiValuesSet, ['entityID' => $entity_id]), TRUE);
}
}
}

/**
* Saves a set of custom values for specific entity Id.
*
* @param int $entity_id
* @param array $params
* @param bool $skipEmpty
*/
protected function saveCustomValues($entity_id, array $params, $skipEmpty = FALSE) {
if ($skipEmpty) {
// Remove empty values from $params array. Useful to not save empty values
// with 'Create only' mode.
foreach ($params as $key => $value) {
$checkValue = str_replace(CRM_Core_DAO::VALUE_SEPARATOR, '', $value);
if (empty($checkValue)) {
unset($params[$key]);
}
}
}

$result = CRM_Core_BAO_CustomValueTable::setValues($params);

// Prevent wholesale failure by saving each param individually if there was an error while trying to save them all at once
if (!empty($result['is_error'])) {
$bt = debug_backtrace();
array_shift($params);
foreach ($params as $k => $v) {
$single_param = ['entityID' => $entity_id, $k => $v];
$result = CRM_Core_BAO_CustomValueTable::setValues($single_param);
if (!empty($result['is_error'])) {
$file = explode('/', $bt[0]['file']);
watchdog('webform_civicrm', 'The CiviCRM "CustomValueTable::setValues" function returned the error: "%msg" when called by line !line of !file with the following parameters: "!params"', ['%msg' => $result['error_message'], '!line' => $bt[0]['line'], '!file' => array_pop($file), '!params' => print_r($single_param, TRUE)], WATCHDOG_ERROR);
}
}
}
}

/**
* @param string $fid
* @param mixed $default
Expand Down
41 changes: 21 additions & 20 deletions includes/wf_crm_webform_postprocess.inc
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
}
$this->saveCurrentEmployer($contact, $cid);

$this->saveCustomData($contact, $cid, 'Contact', !empty($this->existing_contacts[$c]), $c);

$this->fillHiddenContactFields($cid, $c);

$this->saveContactLocation($contact, $cid, $c);
Expand Down Expand Up @@ -224,7 +226,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
if (isset($this->data['grant']['number_of_grant'])) {
$this->processGrants();
}
// Save contribution line-items
// Save contribution custom data & line-items
if (!empty($this->ent['contribution'][1]['id'])) {
$this->processContribution();
}
Expand Down Expand Up @@ -1032,7 +1034,13 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
if (empty($params['campaign_id']) || empty($this->all_fields['participant_campaign_id'])) {
unset($params['campaign_id']);
}

// Reformat custom data from nested arrays
$custom = [];
foreach ($this->data['participant'][$n] as $key => $vals) {
if (substr($key, 0, 2) == 'cg' && isset($vals[$e])) {
$custom[$key][1] = $vals[$e];
}
}
// Loop through event ids to support multi-valued form elements
$this->events = (array) $params['event_id'];
foreach ($this->events as $i => $id_and_type) {
Expand Down Expand Up @@ -1084,6 +1092,9 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
if ($c == 1) {
$registered_by_id[$e][$i] = $result['id'];
}
if ($custom) {
$this->saveCustomData($custom, $result['id'], 'Participant');
}
}
}
}
Expand Down Expand Up @@ -1286,13 +1297,14 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
unset($params['status_id']);
}
$result = wf_civicrm_api('case', 'create', $params);

// Final processing if save was successful
if (!empty($result['id'])) {
// handle case tags
$this->handleEntityTags('case', $result['id'], $n, $params);
// Store id
$this->ent['case'][$n]['id'] = $result['id'];
// Save custom field data
$this->saveCustomData($data, $result['id'], 'Case', FALSE);
// Save case roles
foreach ($params as $param => $val) {
if ($val && strpos($param, 'role_') === 0) {
Expand Down Expand Up @@ -1401,7 +1413,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
$this->handleEntityTags('activity', $activity['id'], $n, $params);
// Store id
$this->ent['activity'][$n]['id'] = $activity['id'];
// Save attachments
// Save custom data & attachments
$this->saveCustomData($data, $activity['id'], 'Activity', FALSE);
if (isset($data['activityupload'])) {
$this->processAttachments('activity', $n, $activity['id'], empty($params['id']));
}
Expand Down Expand Up @@ -1513,7 +1526,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
if (!empty($result['id'])) {
// Store id
$this->ent['grant'][$n]['id'] = $result['id'];
// Save attachments
// Save custom data & attachments
$this->saveCustomData($data, $result['id'], 'Grant', FALSE);
if (isset($data['grantupload'])) {
$this->processAttachments('grant', $n, $result['id'], empty($params['id']));
}
Expand Down Expand Up @@ -2090,6 +2104,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
private function processContribution() {
$contribution = $this->data['contribution'][1]['contribution'][1];
$id = $this->ent['contribution'][1]['id'];
// Save custom data
$this->saveCustomData($this->data['contribution'][1], $id, 'Contribution', FALSE);
// Save soft credits
if (!empty($contribution['soft'])) {
// Get total amount from total amount after line item calculation
Expand Down Expand Up @@ -2257,7 +2273,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
private function fillDataFromSubmission() {
foreach ($this->enabled as $field_key => $fid) {
$val = $this->submissionValue($fid);
$customValue = NULL;
// If value is null then it was hidden by a webform conditional rule - skip it
if ($val !== NULL && $val !== [NULL]) {
list( , $c, $ent, $n, $table, $name) = explode('_', $field_key, 6);
Expand Down Expand Up @@ -2293,16 +2308,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
if (!empty($this->data[$ent][$c][$table][$n][$name]) && is_array($this->data[$ent][$c][$table][$n][$name])) {
$val = array_unique(array_merge($val, $this->data[$ent][$c][$table][$n][$name]));
}
// We need to handle items being de-selected too and provide an array to pass to Entity.create API
// Extract a list of available items
$exposedOptions = $this->getExposedOptions($field_key);
$customValue = [];
foreach ($exposedOptions as $itemName => $itemLabel) {
if (in_array($itemName, $val)) {
$customValue[] = $itemName;
}
}

// Implode data that will be stored as a string
if ($table !== 'other' && $name !== 'event_id' && $name !== 'relationship_type_id' && $table !== 'contact' && $dataType != 'ContactReference' && strpos($name, 'tag') !== 0) {
$val = CRM_Utils_Array::implodePadded($val);
Expand Down Expand Up @@ -2362,13 +2367,9 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base {
$date = wf_crm_aval($this->data, "$ent:$c:$table:$n:$name", '');
$val = $date . str_replace(':', '', $val);
}

// Only known contacts are allowed to empty a field
if (($val !== '' && $val !== NULL && $val !== []) || !empty($this->existing_contacts[$c])) {
$this->data[$ent][$c][$table][$n][$name] = $val;
if (substr($name, 0, 6) === 'custom') {
$this->data[$ent][$c][$ent][$n][$name] = $customValue ?? $val;
}
}
}
}
Expand Down

0 comments on commit da47b7d

Please sign in to comment.