From c4a3d9d5158b126eeda437f4bd24d3634d9f8962 Mon Sep 17 00:00:00 2001 From: Jack Aponte Date: Fri, 31 Jan 2020 14:35:56 -0800 Subject: [PATCH] Revert "#43: Update to match Drupal 7.x-5.0" --- includes/contact_component.inc | 59 ++- includes/utils.inc | 514 ++++++++++-------------- includes/wf_crm_admin_component.inc | 2 +- includes/wf_crm_admin_form.inc | 22 +- includes/wf_crm_admin_help.inc | 14 +- includes/wf_crm_webform_ajax.inc | 2 +- includes/wf_crm_webform_base.inc | 171 ++++---- includes/wf_crm_webform_postprocess.inc | 198 ++++----- includes/wf_crm_webform_preprocess.inc | 83 ++-- js/webform_civicrm_admin.js | 2 +- webform_civicrm.info | 6 +- webform_civicrm.module | 28 +- 12 files changed, 528 insertions(+), 573 deletions(-) diff --git a/includes/contact_component.inc b/includes/contact_component.inc index 0c0d95b6b..1c0496dad 100644 --- a/includes/contact_component.inc +++ b/includes/contact_component.inc @@ -253,7 +253,7 @@ function _webform_edit_civicrm_contact($component) { '#parents' => array('extra', 'default_custom_ref'), ); } - + $case_count = isset($data['case']['number_of_case']) ? $data['case']['number_of_case'] : 0; if ($case_count > 0) { $form['defaults']['default']['#options']['case_roles'] = t('Case roles'); @@ -347,7 +347,7 @@ function _webform_edit_civicrm_contact($component) { '#type' => 'select', '#multiple' => TRUE, '#title' => t('Tags'), - '#options' => array('' => '- ' . t('None') . ' -') + wf_crm_get_tags('contact'), + '#options' => array('' => '- ' . t('None') . ' -') + CRM_Core_BAO_Tag::getTags("civicrm_contact", $tags, NULL, '- '), '#default_value' => $component['extra']['filters']['tag'], '#description' => t('Listed contacts must be have at least one of the selected tags (leave blank to not filter by tag).'), ); @@ -887,56 +887,55 @@ function wf_crm_update_existing_component(&$component, $enabled, $data) { * @return array */ function wf_crm_find_relations($cid, $types = array(), $current = TRUE) { - $found = $allowed = $type_ids = []; + $found = $allowed = array(); $cid = (int) $cid; static $employer_type = 0; if ($cid) { if (!$employer_type && $current) { $employer_type = wf_crm_aval(wf_civicrm_api('relationshipType', 'get', array('name_a_b' => 'Employee of', 'return' => 'id')), 'id'); } + $type_ids = ''; foreach ($types as $t) { - list($type, $a) = explode('_', $t); + list($type, $a_b) = explode('_', $t); // Put current employer first in the list if ($type == $employer_type && $current) { - $search_key = $a == 'b' ? 'id' : 'employer_id'; - // Note: inconsistency in api3 - search key is "employer_id" but return key is "current_employer_id" - $employer = wf_crm_apivalues('contact', 'get', [ - $search_key => $cid, - 'sequential' => 1, - ], $a == 'b' ? 'current_employer_id' : 'id'); - if ($employer) { - $found[$employer[0]] = $employer[0]; + $sql = "SELECT id, employer_id + FROM civicrm_contact + WHERE id = $cid OR employer_id = $cid"; + $dao = CRM_Core_DAO::executeQuery($sql); + $employer = $dao->id == $cid ? $dao->employer_id : $dao->id; + while ($dao->fetch()) { + $found[$employer] = $employer; } + $dao->free(); } - $type_ids[] = $type; - if ($a == 'a' || $a == 'r') { + $type_ids .= ($type_ids ? ',' : '') . $type; + if ($a_b == 'a' || $a_b == 'r') { $allowed[] = $type . '_a'; } - if ($a == 'b' || $a == 'r') { + if ($a_b == 'b' || $a_b == 'r') { $allowed[] = $type . '_b'; } } - $params = [ - 'return' => ['contact_id_a', 'contact_id_b', 'relationship_type_id', 'end_date'], - 'contact_id_a' => $cid, - 'contact_id_b' => $cid, - 'options' => ['or' => [['contact_id_a', 'contact_id_b']]], - ]; + $typeClause = ''; if ($type_ids) { - $params['relationship_type_id'] = ['IN' => $type_ids]; + $typeClause = "AND relationship_type_id IN ($type_ids)"; } + $sql = "SELECT relationship_type_id, contact_id_a, contact_id_b + FROM civicrm_relationship + WHERE (contact_id_a = $cid OR contact_id_b = $cid) $typeClause"; if ($current) { - $params['is_active'] = 1; + $sql .= " AND is_active = 1 AND (end_date > CURDATE() OR end_date IS NULL)"; } - foreach (wf_crm_apivalues('relationship', 'get', $params) as $relationship) { - $a = $relationship['contact_id_a'] == $cid ? 'b' : 'a'; - if (!$current || empty($relationship['end_date']) || strtotime($relationship['end_date']) > time()) { - if (!$allowed || in_array($relationship['relationship_type_id'] . '_' . $a, $allowed)) { - $c = $relationship["contact_id_$a"]; - $found[$c] = $c; - } + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $a_b = $dao->contact_id_a == $cid ? 'b' : 'a'; + if (!$allowed || in_array($dao->relationship_type_id . '_' . $a_b, $allowed)) { + $c = $dao->{"contact_id_$a_b"}; + $found[$c] = $c; } } + $dao->free(); } return $found; } diff --git a/includes/utils.inc b/includes/utils.inc index 371c506e9..4a4b8ebc9 100644 --- a/includes/utils.inc +++ b/includes/utils.inc @@ -54,12 +54,14 @@ function wf_crm_field_options($field, $context, $data) { elseif ($name == 'privacy') { $ret = wf_crm_get_privacy_options(); } - elseif (isset($field['table']) && $field['table'] === 'tag') { - $split = explode('_', $name); - $ret = wf_crm_get_tags($ent, wf_crm_aval($split, 1)); - } - elseif (isset($field['table']) && $field['table'] === 'group') { - $ret = wf_crm_apivalues('group', 'get', array('is_hidden' => 0), 'title'); + elseif ($table === 'other') { + if ($field['table'] === 'tag') { + $split = explode('_', $name); + $ret = CRM_Core_BAO_Tag::getTags("civicrm_{$ent}", $ret, wf_crm_aval($split, 1), '- '); + } + elseif ($field['table'] === 'group') { + $ret = wf_crm_apivalues('group', 'get', array('is_hidden' => 0), 'title'); + } } elseif ($name === 'survey_id') { $ret = wf_crm_get_surveys(wf_crm_aval($data, "activity:$c:activity:1", array())); @@ -118,78 +120,29 @@ function wf_crm_field_options($field, $context, $data) { return $ret; } -/** - * Fetch tags within a given tagset - * - * If no tagset specified, all tags NOT within a tagset are returned. - * Return format is a flat array with some tic marks to indicate nesting. - * - * @param string $used_for - * @param int $parent_id - * @return array - */ -function wf_crm_get_tags($used_for, $parent_id = NULL) { - $params = [ - 'used_for' => ['LIKE' => "%civicrm_{$used_for}%"], - 'is_tagset' => 0, - 'is_selectable' => 1, - 'parent_id' => $parent_id ?: ['IS NULL' => 1], - 'options' => ['sort' => 'name'], - ]; - $tags = wf_crm_apivalues('Tag', 'get', $params, 'name'); - // Tagsets cannot be nested so no need to fetch children - if ($parent_id || !$tags) { - return $tags; - } - // Fetch child tags - unset($params['parent_id']); - $params += ['return' => ['name', 'parent_id'], 'parent_id.is_tagset' => 0, 'parent_id.is_selectable' => 1]; - $unsorted = wf_crm_apivalues('Tag', 'get', $params); - $parents = array_fill_keys(array_keys($tags), ['depth' => 1]); - // Loop until all children are placed under their parents - while ($unsorted) { - foreach ($unsorted as $id => $tag) { - $parent = $tag['parent_id']; - if (isset($parents[$parent])) { - $name = str_repeat('- ', $parents[$parent]['depth']) . $tag['name']; - $pos = array_search($parents[$parent]['child'] ?? $parent, array_keys($tags)) + 1; - $tags = array_slice($tags, 0, $pos, TRUE) + [$id => $name] + array_slice($tags, $pos, NULL, TRUE); - $parents[$id] = ['depth' => $parents[$parent]['depth'] + 1]; - $parents[$parent]['child'] = $id; - unset($unsorted[$id]); - } - } - } - return $tags; -} - /** * Get list of states, keyed by abbreviation rather than ID. - * + * FIXME use the api for this. * @param null|int|string $param - * @return array */ function wf_crm_get_states($param = NULL) { $ret = array(); if (!$param || $param == 'default') { - $provinceLimit = wf_crm_get_civi_setting('provinceLimit'); - if (!$param && $provinceLimit) { - $param = (array) $provinceLimit; + $config = CRM_Core_Config::singleton(); + if (!$param && !empty($config->provinceLimit)) { + $param = implode(',', $config->provinceLimit); } else { - $param = [(int) wf_crm_get_civi_setting('defaultContactCountry', 1228)]; + $param = (int) $config->defaultContactCountry; } } else { - $param = array((int) $param); + $param = (int) $param; } - $states = wf_crm_apivalues('state_province', 'get', array( - 'return' => 'abbreviation,name', - 'sort' => 'name', - 'country_id' => array('IN' => $param) - )); - foreach ($states as $state) { - $ret[strtoupper($state['abbreviation'])] = $state['name']; + $sql = "SELECT name AS label, UPPER(abbreviation) AS value FROM civicrm_state_province WHERE country_id IN ($param) ORDER BY name"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $ret[$dao->value] = $dao->label; } // Localize the state/province names if in an non-en_US locale $tsLocale = CRM_Utils_System::getUFLocale(); @@ -214,73 +167,62 @@ function wf_crm_get_states($param = NULL) { * @return string or integer */ function wf_crm_state_abbr($input, $ret = 'abbreviation', $country_id = NULL) { - $params = ['sequential' => 1]; - if ($ret == 'id') { - $params['abbreviation'] = $input; + $input_type = $ret == 'id' ? 'abbreviation' : 'id'; + $sql = "SELECT $ret FROM civicrm_state_province WHERE $input_type = %1"; + $vars = array(1 => array($input, $ret == 'id' ? 'String' : 'Integer')); + if ($ret === 'id') { if (!$country_id || $country_id === 'default') { - $country_id = (int) wf_crm_get_civi_setting('defaultContactCountry', 1228); + $config = CRM_Core_Config::singleton(); + $country_id = (int) $config->defaultContactCountry; } + $sql .= ' AND country_id = %2'; + $vars[2] = array($country_id, 'Integer'); } - else { - $params['id'] = $input; - } - $params['country_id'] = $country_id; - $result = wf_crm_apivalues('StateProvince', 'get', $params, $ret); - return wf_crm_aval($result, 0); + $sql .= ' LIMIT 0, 1'; + return CRM_Core_DAO::singleValueQuery($sql, $vars); } /** * Get list of events. + * FIXME use the api for this. * * @param array $reg_options * @param string $context - * * @return array */ function wf_crm_get_events($reg_options, $context) { - $ret = []; + $ret = array(); $format = wf_crm_aval($reg_options, 'title_display', 'title'); - $params = [ - 'is_template' => 0, - 'is_active' => 1, - ]; - $event_types = array_filter((array) $reg_options['event_type'], "is_numeric"); - if ($event_types) { - $params['event_type_id'] = ['IN' => $event_types]; - } - if (is_numeric(wf_crm_aval($reg_options, 'show_public_events'))) { - $params['is_public'] = $reg_options['show_public_events']; - } - $params['options'] = ['sort' => 'start_date' . ($context == 'config_form' ? ' DESC' : '')]; - $values = wf_crm_apivalues('Event', 'get', $params); + $sql = "SELECT id, title, start_date, end_date, event_type_id FROM civicrm_event WHERE is_template = 0 AND is_active = 1"; // 'now' means only current events, 1 means show all past events, other values are relative date strings $date_past = wf_crm_aval($reg_options, 'show_past_events', 'now'); if ($date_past != '1') { $date_past = date('Y-m-d H:i:s', strtotime($date_past)); - foreach ($values as $key => $value) { - if (isset($value['end_date']) && $value['end_date'] <= $date_past) { - unset($values[$key]); - } - } + $sql .= " AND (end_date >= '$date_past' OR end_date IS NULL)"; } // 'now' means only past events, 1 means show all future events, other values are relative date strings $date_future = wf_crm_aval($reg_options, 'show_future_events', '1'); if ($date_future != '1') { $date_future = date('Y-m-d H:i:s', strtotime($date_future)); - foreach ($values as $key => $value) { - if (isset($value['end_date']) && $value['end_date'] >= $date_future) { - unset($values[$key]); - } - } + $sql .= " AND (end_date <= '$date_future' OR end_date IS NULL)"; } - foreach ($values as $value) { - $ret[$value['id'] . '-' . $value['event_type_id']] = wf_crm_format_event($value, $format); + $event_types = array_filter((array) $reg_options['event_type'], "is_numeric"); + if ($event_types) { + $sql .= ' AND event_type_id IN ( ' . implode(", ", $event_types) . ' ) '; + } + if (is_numeric(wf_crm_aval($reg_options, 'show_public_events'))) { + $sql .= ' AND is_public = ' . $reg_options['show_public_events']; + } + $sql .= ' ORDER BY start_date ' . ($context == 'config_form' ? 'DESC' : ''); + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $ret[$dao->id . '-' . $dao->event_type_id] = wf_crm_format_event($dao, $format); } return $ret; } /** - * @param array $event + * @param array|object $event * @param string $format * @return string */ @@ -289,29 +231,28 @@ function wf_crm_format_event($event, $format) { // Date format foreach ($format as $value) { if (strpos($value, 'dateformat') === 0) { - $date_format = wf_crm_get_civi_setting($value); + $config = CRM_Core_Config::singleton(); + $date_format = $config->$value; } } - $title = []; + $event = (object) $event; + $title = array(); if (in_array('title', $format)) { - $title[] = $event['title']; + $title[] = $event->title; } if (in_array('type', $format)) { - $types = wf_crm_apivalues('event', 'getoptions', [ - 'field' => 'event_type_id', - 'context' => 'get', - ]); - $title[] = $types[$event['event_type_id']]; + $types = wf_crm_apivalues('event', 'getoptions', array('field' => 'event_type_id', 'context' => 'get')); + $title[] = $types[$event->event_type_id]; } - if (in_array('start', $format) && !empty($event['start_date'])) { - $title[] = CRM_Utils_Date::customFormat($event['start_date'], $date_format); + if (in_array('start', $format) && $event->start_date) { + $title[] = CRM_Utils_Date::customFormat($event->start_date, $date_format); } - if (in_array('end', $format) && isset($event['end_date'])) { + if (in_array('end', $format) && $event->end_date) { // Avoid showing redundant end-date if it is the same as the start date - $same_day = substr($event['start_date'], 0, 10) == substr($event['end_date'], 0, 10); + $same_day = substr($event->start_date, 0, 10) == substr($event->end_date, 0, 10); if (!$same_day || in_array('dateformatDatetime', $format) || in_array('dateformatTime', $format)) { - $end_format = (in_array('dateformatDatetime', $format) && $same_day) ? wf_crm_get_civi_setting('dateformatTime') : $date_format; - $title[] = CRM_Utils_Date::customFormat($event['end_date'], $end_format); + $end_format = (in_array('dateformatDatetime', $format) && $same_day) ? $config->dateformatTime : $date_format; + $title[] = CRM_Utils_Date::customFormat($event->end_date, $end_format); } } return implode(' - ', $title); @@ -452,10 +393,10 @@ function wf_crm_get_matching_rules($contact_type) { static $rules; $contact_type = ucfirst($contact_type); if (!$rules) { - $rules = array_fill_keys(['Individual', 'Organization', 'Household'], []); - $values = wf_crm_apivalues('RuleGroup', 'get'); - foreach ($values as $value) { - $rules[$value['contact_type']][$value['id']] = $value['title']; + $rules = array_fill_keys(array('Individual', 'Organization', 'Household'), array()); + $dao = CRM_Core_DAO::executeQuery('SELECT * FROM civicrm_dedupe_rule_group'); + while ($dao->fetch()) { + $rules[$dao->contact_type][$dao->id] = $dao->title; } } return $rules[$contact_type]; @@ -528,7 +469,8 @@ function wf_crm_get_fields($var = 'fields') { static $sets; if (!$fields) { - $components = wf_crm_get_civi_setting('enable_components'); + $config = CRM_Core_Config::singleton(); + $components = $config->enableComponents; $sets = array( 'contact' => array('entity_type' => 'contact', 'label' => t('Contact Fields')), @@ -538,7 +480,7 @@ function wf_crm_get_fields($var = 'fields') { 'email' => array('entity_type' => 'contact', 'label' => t('Email'), 'max_instances' => 9, 'custom_fields' => 'combined'), 'website' => array('entity_type' => 'contact', 'label' => t('Website'), 'max_instances' => 9, 'custom_fields' => 'combined'), 'im' => array('entity_type' => 'contact', 'label' => t('Instant Message'), 'max_instances' => 9, 'custom_fields' => 'combined'), - 'activity' => array('entity_type' => 'activity', 'label' => t('Activity'), 'max_instances' => 60, 'attachments' => TRUE), + 'activity' => array('entity_type' => 'activity', 'label' => t('Activity'), 'max_instances' => 40, 'attachments' => TRUE), 'relationship' => array('entity_type' => 'contact', 'label' => t('Relationship'), 'help_text' => TRUE, 'custom_fields' => 'combined'), ); $conditional_sets = array( @@ -562,9 +504,9 @@ function wf_crm_get_fields($var = 'fields') { 'type' => 'number', 'data_type' => 'Money', 'extra' => array( - 'field_prefix' => wf_crm_get_civi_setting('defaultCurrencySymbol', '$'), - 'point' => wf_crm_get_civi_setting('monetaryDecimalPoint', '.'), - 'separator' => wf_crm_get_civi_setting('monetaryThousandSeparator', ','), + 'field_prefix' => wf_crm_aval($config, 'defaultCurrencySymbol', '$'), + 'point' => wf_crm_aval($config, 'monetaryDecimalPoint', '.'), + 'separator' => wf_crm_aval($config, 'monetaryThousandSeparator', ','), 'decimals' => 2, 'min' => 0, ), @@ -601,9 +543,15 @@ function wf_crm_get_fields($var = 'fields') { 'contact_type' => 'organization', ); // Individual names - $enabled_names = wf_crm_get_civi_setting('contact_edit_options'); - $name_options = array_column(wf_crm_apivalues('OptionValue', 'get', ['option_group_id' => 'contact_edit_options', 'return' => ['name', 'value']]), 'name', 'value'); - $enabled_names = array_intersect_key($name_options, array_flip($enabled_names)); + if (version_compare(CRM_Utils_System::version(), '4.5', '<')) { + // This setting doesn't exist prior to 4.5 so hard-code it. + $enabled_names = array('Prefix', 'Suffix', 'First Name', 'Middle Name', 'Last Name'); + } + else { + $enabled_names = wf_crm_explode_multivalue_str(CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'contact_edit_options')); + $name_options = CRM_Core_OptionGroup::values('contact_edit_options', FALSE, FALSE, FALSE, NULL, 'name'); + $enabled_names = array_intersect_key($name_options, array_flip($enabled_names)); + } foreach (array('prefix_id' => t('Name Prefix'), 'formal_title' => t('Formal Title'), 'first_name' => t('First Name'), 'middle_name' => t('Middle Name'), 'last_name' => t('Last Name'), 'suffix_id' => t('Name Suffix')) as $key => $label) { if (in_array(ucwords(str_replace(array('_id', '_'), array('', ' '), $key)), $enabled_names)) { $fields['contact_' . $key] = array( @@ -650,7 +598,7 @@ function wf_crm_get_fields($var = 'fields') { $fields['contact_preferred_language'] = array( 'name' => t('Preferred Language'), 'type' => 'select', - 'value' => wf_crm_get_civi_setting('lcMessages', 'en_US'), + 'value' => $config->lcMessages, ); if (array_key_exists('file', webform_components())) { $fields['contact_image_URL'] = array( @@ -744,7 +692,7 @@ function wf_crm_get_fields($var = 'fields') { 'name' => t('Country'), 'type' => 'select', 'extra' => array('civicrm_live_options' => 1), - 'value' => wf_crm_get_civi_setting('defaultContactCountry', 1228), + 'value' => $config->defaultContactCountry, ); $fields['address_state_province_id'] = array( 'name' => t('State/Province'), @@ -792,17 +740,14 @@ function wf_crm_get_fields($var = 'fields') { 'type' => 'select', 'expose_list' => TRUE, ); - $defaultLocType = wf_crm_aval(wf_civicrm_api('LocationType', 'get', [ - 'return' => ["id"], - 'is_default' => 1, - ]), 'id'); + $defaultLocType = CRM_Core_BAO_LocationType::getDefault(); foreach (array('address' => t('Address # Location'), 'phone' => t('Phone # Location'), 'email' => t('Email # Location'), 'im' => t('IM # Location')) as $key => $label) { if (isset($sets[$key])) { $fields[$key . '_location_type_id'] = array( 'name' => $label, 'type' => 'select', 'expose_list' => TRUE, - 'value' => $defaultLocType, + 'value' => $defaultLocType->id, ); } } @@ -823,6 +768,16 @@ function wf_crm_get_fields($var = 'fields') { 'table' => 'group', 'expose_list' => TRUE, ); + $tagsets = array('' => t('Tag(s)')) + CRM_Core_BAO_Tag::getTagSet('civicrm_contact'); + foreach ($tagsets as $pid => $name) { + $fields['other_tag' . ($pid ? "_$pid" : '')] = array( + 'name' => $name, + 'type' => 'select', + 'extra' => array('multiple' => 1, 'civicrm_live_options' => 1), + 'table' => 'tag', + 'expose_list' => TRUE, + ); + } $fields['activity_activity_type_id'] = array( 'name' => t('Activity # Type'), 'type' => 'select', @@ -894,9 +849,8 @@ function wf_crm_get_fields($var = 'fields') { 'integer' => 1, ), ); - $tag_entities = array('other', 'activity'); if (isset($sets['case'])) { - $tag_entities[] = 'case'; + $case_info = new CRM_Case_XMLProcessor_Process(); $fields['case_case_type_id'] = array( 'name' => t('Case # Type'), 'type' => 'select', @@ -906,7 +860,7 @@ function wf_crm_get_fields($var = 'fields') { 'name' => t('Case # Client'), 'type' => 'select', 'expose_list' => TRUE, - 'extra' => array('required' => 1, 'multiple' => wf_crm_get_civi_setting('civicaseAllowMultipleClients', 0)), + 'extra' => array('required' => 1, 'multiple' => $case_info->getAllowMultipleCaseClients()), 'data_type' => 'ContactReference', 'set' => 'caseRoles', 'value' => 1, @@ -950,10 +904,12 @@ function wf_crm_get_fields($var = 'fields') { ); // Fetch case roles $sets['caseRoles'] = array('entity_type' => 'case', 'label' => t('Case Roles')); - foreach (wf_crm_apivalues('case_type', 'get') as $case_type) { + // Use the vanilla civicrm_api for this because it will throw an error in CiviCRM 4.4 (api doesn't exist) + $case_types = civicrm_api('case_type', 'get', array('version' => 3, 'options' => array('limit' => 0))); + foreach (wf_crm_aval($case_types, 'values', array()) as $case_type) { foreach ($case_type['definition']['caseRoles'] as $role) { foreach (wf_crm_get_relationship_types() as $rel_type) { - if (in_array($role['name'], [$rel_type['name_b_a'], $rel_type['label_b_a']])) { + if ($rel_type['name_b_a'] == $role['name']) { if (!isset($fields['case_role_' . $rel_type['id']])) { $fields['case_role_' . $rel_type['id']] = array( 'name' => $rel_type['label_b_a'], @@ -974,29 +930,6 @@ function wf_crm_get_fields($var = 'fields') { } } } - $all_tagsets = wf_crm_apivalues('tag', 'get', [ - 'return' => ['id', 'name', 'used_for'], - 'is_tagset' => 1, - 'parent_id' => ['IS NULL' => 1], - ]); - foreach ($tag_entities as $entity) { - $table_name = $entity == 'other' ? 'civicrm_contact' : "civicrm_$entity"; - $tagsets = ['' => t('Tag(s)')]; - foreach ($all_tagsets as $set) { - if (strpos($set['used_for'], $table_name) !== FALSE) { - $tagsets[$set['id']] = $set['name']; - } - } - foreach ($tagsets as $pid => $name) { - $fields[$entity . '_tag' . ($pid ? "_$pid" : '')] = [ - 'name' => $name, - 'type' => 'select', - 'extra' => ['multiple' => 1, 'civicrm_live_options' => 1], - 'table' => 'tag', - 'expose_list' => TRUE, - ]; - } - } $fields['relationship_relationship_type_id'] = array( 'name' => t('Relationship Type(s)'), 'type' => 'select', @@ -1141,7 +1074,7 @@ function wf_crm_get_fields($var = 'fields') { ), 'set' => 'contributionRecur', ); - } + } if (isset($sets['participant'])) { $fields['participant_event_id'] = array( 'name' => t('Event(s)'), @@ -1338,7 +1271,7 @@ function wf_crm_get_fields($var = 'fields') { } // File attachment fields - $numAttachments = wf_crm_get_civi_setting('max_attachments', 3); + $numAttachments = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'max_attachments'); foreach ($sets as $ent => $set) { if (!empty($set['attachments']) && $numAttachments) { $sets["{$ent}upload"] = array( @@ -1379,117 +1312,109 @@ function wf_crm_get_fields($var = 'fields') { 'email' => t('email'), ); - // Fetch custom groups + // Pull custom fields and match to Webform element types + $custom_types = wf_crm_custom_types_map_array(); list($contact_types) = wf_crm_get_contact_types(); - $custom_sets = []; - $custom_groups = wf_crm_apivalues('CustomGroup', 'get', [ - 'return' => ['title', 'extends', 'extends_entity_column_value', 'extends_entity_column_id', 'is_multiple', 'max_multiple', 'help_pre'], - 'is_active' => 1, - 'extends' => ['IN' => array_keys($contact_types + $sets)], - 'options' => ['sort' => 'weight'], - ]); - foreach ($custom_groups as $custom_group) { - $set = 'cg' . $custom_group['id']; - $entity_type = strtolower($custom_group['extends']); - // Place these custom fields directly into their entity - if (wf_crm_aval($sets, "$entity_type:custom_fields") == 'combined') { - $set = $entity_type; - } - else { - $sets[$set] = [ - 'label' => $custom_group['title'], - 'entity_type' => $entity_type, - 'max_instances' => 1, - ]; - if (isset($contact_types[$entity_type]) || $entity_type == 'contact') { - $sets[$set]['entity_type'] = 'contact'; - if ($entity_type != 'contact') { - $sets[$set]['contact_type'] = $entity_type; + $custom_extends = "'" . implode("','", array_keys($contact_types + $sets)) . "'"; + $sql = " + SELECT cf.*, cg.title AS custom_group_name, LOWER(cg.extends) AS entity_type, cg.extends_entity_column_id, cg.extends_entity_column_value AS sub_types, cg.is_multiple, cg.max_multiple, cg.id AS custom_group_id, cg.help_pre as cg_help + FROM civicrm_custom_field cf + INNER JOIN civicrm_custom_group cg ON cg.id = cf.custom_group_id + WHERE cf.is_active <> 0 AND cg.extends IN ($custom_extends) AND cg.is_active <> 0 + ORDER BY cf.custom_group_id, cf.weight"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + if (isset($custom_types[$dao->html_type])) { + $set = 'cg' . $dao->custom_group_id; + // Place these custom fields directly into their entity + if (wf_crm_aval($sets, "$dao->entity_type:custom_fields") == 'combined') { + //if ($dao->entity_type == 'address' || $dao->entity_type == 'relationship' || $dao->entity_type == 'membership' || $dao->entity_type == 'phone') { + $set = $dao->entity_type; + } + elseif (!isset($sets[$set])) { + $sets[$set]['label'] = $dao->custom_group_name; + if (isset($contact_types[$dao->entity_type]) || $dao->entity_type == 'contact') { + $sets[$set]['entity_type'] = 'contact'; + if ($dao->entity_type != 'contact') { + $sets[$set]['contact_type'] = $dao->entity_type; + } + if ($dao->is_multiple) { + $sets[$set]['max_instances'] = ($dao->max_multiple ? $dao->max_multiple : 9); + } + else { + $sets[$set]['max_instances'] = 1; + } + } + else { + $sets[$set]['entity_type'] = $dao->entity_type; } - if (!empty($custom_group['is_multiple'])) { - $sets[$set]['max_instances'] = $custom_group['max_multiple'] ?? 9; + if ($dao->sub_types) { + $sets[$set]['sub_types'] = wf_crm_explode_multivalue_str($dao->sub_types); } + if ($dao->extends_entity_column_id) { + $sets[$set]['extension_of'] = $dao->extends_entity_column_id; + } + $sets[$set]['help_text'] = $dao->cg_help; } - if (!empty($custom_group['extends_entity_column_value'])) { - $sets[$set]['sub_types'] = $custom_group['extends_entity_column_value']; + $id = $set . '_custom_' . $dao->id; + $fields[$id] = $custom_types[$dao->html_type]; + if ($dao->html_type == 'Text' && $dao->data_type == 'Money') { + $fields[$id] = $moneyDefaults; } - if (!empty($custom_group['extends_entity_column_id'])) { - $sets[$set]['extension_of'] = $custom_group['extends_entity_column_id']; + $fields[$id]['name'] = $dao->label; + $fields[$id]['required'] = $dao->is_required; + $fields[$id]['value'] = implode(',', wf_crm_explode_multivalue_str($dao->default_value)); + $fields[$id]['data_type'] = $dao->data_type; + if (!empty($dao->help_pre) || !empty($dao->help_post)) { + $fields[$id]['extra']['description'] = $dao->help_pre ? $dao->help_pre : $dao->help_post; + $fields[$id]['extra']['description_above'] = (int) !$dao->help_pre; + $fields[$id]['has_help'] = TRUE; + } + // Conditional rule - todo: support additional entities + if ($sets[$set]['entity_type'] == 'contact' && !empty($sets[$set]['sub_types'])) { + $fields[$id]['civicrm_condition'] = array( + 'andor' => 'or', + 'action' => 'show', + 'rules' => array( + 'contact_contact_sub_type' => array( + 'values' => $sets[$set]['sub_types'], + ), + ), + ); } - $sets[$set]['help_text'] = $custom_group['help_pre'] ?? NULL; - } - $custom_sets[$custom_group['id']] = $set; - } - - // Fetch custom fields - $custom_types = wf_crm_custom_types_map_array(); - $custom_fields = wf_crm_apivalues('CustomField', 'get', [ - 'is_active' => 1, - 'custom_group_id' => ['IN' => array_keys($custom_sets)], - 'html_type' => ['IN' => array_keys($custom_types)], - 'options' => ['sort' => 'weight'], - ]); - foreach ($custom_fields as $custom_field) { - $set = $custom_sets[$custom_field['custom_group_id']]; - $custom_group = $custom_groups[$custom_field['custom_group_id']]; - $id = $set . '_custom_' . $custom_field['id']; - $fields[$id] = $custom_types[$custom_field['html_type']]; - if ($custom_field['html_type'] == 'Text' && $custom_field['data_type'] == 'Money') { - $fields[$id] = $moneyDefaults; - } - $fields[$id]['name'] = $custom_field['label']; - $fields[$id]['required'] = (int) !empty($custom_field['is_required']); - if (!empty($custom_field['default_value'])) { - $fields[$id]['value'] = implode(',', wf_crm_explode_multivalue_str($custom_field['default_value'])); - } - $fields[$id]['data_type'] = $custom_field['data_type']; - if (!empty($custom_field['help_pre']) || !empty($custom_field['help_post'])) { - $fields[$id]['extra']['description'] = !empty($custom_field['help_pre']) ? $custom_field['help_pre'] : $custom_field['help_post']; - $fields[$id]['extra']['description_above'] = (int) empty($custom_field['help_pre']); - $fields[$id]['has_help'] = TRUE; - } - // Conditional rule - todo: support additional entities - if ($sets[$set]['entity_type'] == 'contact' && !empty($sets[$set]['sub_types'])) { - $fields[$id]['civicrm_condition'] = [ - 'andor' => 'or', - 'action' => 'show', - 'rules' => [ - 'contact_contact_sub_type' => [ - 'values' => $sets[$set]['sub_types'], - ], - ], - ]; - } - if ($set == 'relationship' && !empty($custom_group['extends_entity_column_value'])) { - $fields[$id]['attributes']['data-relationship-type'] = implode(',', $custom_group['extends_entity_column_value']); - } + if ($dao->entity_type == 'relationship' && $dao->sub_types) { + $fields[$id]['attributes']['data-relationship-type'] = implode(',', wf_crm_explode_multivalue_str($dao->sub_types)); + } - if ($fields[$id]['type'] == 'date') { - $fields[$id]['extra']['start_date'] = (!empty($custom_field['start_date_years']) ? '-' . $custom_field['start_date_years'] : '-50') . ' years'; - $fields[$id]['extra']['end_date'] = (!empty($custom_field['end_date_years']) ? '+' . $custom_field['end_date_years'] : '+50') . ' years'; - // Add "time" component for datetime fields - if (!empty($custom_field['time_format'])) { - $fields[$id]['name'] .= ' - ' . t('date'); - $fields[$id . '_timepart'] = [ - 'name' => $custom_field['label'] . ' - ' . t('time'), - 'type' => 'time', - 'extra' => ['hourformat' => $custom_field['time_format'] == 1 ? '12-hour' : '24-hour'], - ]; + if ($fields[$id]['type'] == 'date') { + $fields[$id]['extra']['start_date'] = ($dao->start_date_years ? '-' . $dao->start_date_years : '-50') . ' years'; + $fields[$id]['extra']['end_date'] = ($dao->end_date_years ? '+' . $dao->end_date_years : '+50') . ' years'; + // Add "time" component for datetime fields + if (!empty($dao->time_format)) { + $fields[$id]['name'] .= ' - ' . t('date'); + $fields[$id . '_timepart'] = array( + 'name' => $dao->label . ' - ' . t('time'), + 'type' => 'time', + 'extra' => array('hourformat' => $dao->time_format == 1 ? '12-hour' : '24-hour'), + ); + } + } + elseif ($fields[$id]['data_type'] == 'ContactReference') { + $fields[$id]['expose_list'] = TRUE; + $fields[$id]['empty_option'] = t('None'); + } + elseif ($fields[$id]['data_type'] !== 'Boolean' && $fields[$id]['type'] == 'select') { + $fields[$id]['extra']['civicrm_live_options'] = 1; + } + elseif ($fields[$id]['type'] == 'textarea') { + $fields[$id]['extra']['cols'] = $dao->note_columns; + $fields[$id]['extra']['rows'] = $dao->note_rows; } - } - elseif ($fields[$id]['data_type'] == 'ContactReference') { - $fields[$id]['expose_list'] = TRUE; - $fields[$id]['empty_option'] = t('None'); - } - elseif ($fields[$id]['data_type'] !== 'Boolean' && $fields[$id]['type'] == 'select') { - $fields[$id]['extra']['civicrm_live_options'] = 1; - } - elseif ($fields[$id]['type'] == 'textarea') { - $fields[$id]['extra']['cols'] = $custom_field['note_columns'] ?? 60; - $fields[$id]['extra']['rows'] = $custom_field['note_rows'] ?? 4; } } + $sets += wf_crm_get_empty_sets(); + $dao->free(); } return $$var; } @@ -1833,11 +1758,31 @@ function wf_crm_is_positive($val) { * @return array $sets */ function wf_crm_get_empty_sets() { - $sets = wf_crm_get_fields('sets'); - foreach (array_keys(wf_crm_get_fields()) as $key) { - list($set) = explode('_', $key); - unset($sets[$set]); + $sets = array(); + + $sql = "SELECT cg.id, cg.title, cg.help_pre, cg.extends, SUM(cf.is_active) as custom_field_sum + FROM civicrm_custom_group cg + LEFT OUTER JOIN civicrm_custom_field cf + ON (cg.id = cf.custom_group_id) + GROUP By cg.id"; + + $dao = CRM_Core_DAO::executeQuery($sql); + + while($dao->fetch()) { + // Because a set with all fields disabled = empty set + if (empty($dao->custom_field_sum)) { + $set = 'cg' . $dao->id; + if ($dao->extends == 'address' || $dao->extends == 'relationship' || $dao->extends == 'membership') { + $set = $dao->extends; + } + $sets[$set] = array( + 'label' => $dao->title, + 'entity_type' => strtolower($dao->extends), + 'help_text' => $dao->help_pre, + ); + } } + return $sets; } @@ -1850,6 +1795,7 @@ function wf_crm_custom_types_map_array() { $custom_types = array( 'Select' => array('type' => 'select'), 'Multi-Select' => array('type' => 'select', 'extra' => array('multiple' => 1)), + 'AdvMulti-Select' => array('type' => 'select', 'extra' => array('multiple' => 1)), 'Radio' => array('type' => 'select', 'extra' => array('aslist' => 0)), 'CheckBox' => array('type' => 'select', 'extra' => array('multiple' => 1)), 'Text' => array('type' => 'textfield'), @@ -1867,31 +1813,3 @@ function wf_crm_custom_types_map_array() { return $custom_types; } - -/** - * @param string $setting_name - * @param mixed $default_value - * @return mixed - */ -function wf_crm_get_civi_setting($setting_name, $default_value = NULL) { - $aliases = [ - 'defaultCurrencySymbol' => 'defaultCurrency', - ]; - $settings = wf_civicrm_api('Setting', 'get', [ - 'sequential' => 1, - 'return' => str_replace(array_keys($aliases), array_values($aliases), $setting_name), - ]); - // Not a real setting, requires cross-lookup - if ($setting_name == 'defaultCurrencySymbol') { - $currencies = wf_crm_apivalues('Contribution', 'getoptions', [ - 'field' => "currency", - 'context' => "abbreviate", - ]); - return wf_crm_aval($currencies, $settings['values'][0]['defaultCurrency'], $default_value); - } - $result = wf_crm_aval($settings, "values:0:$setting_name", $default_value); - if ($result === 'default') { - return $default_value; - } - return $result; -} diff --git a/includes/wf_crm_admin_component.inc b/includes/wf_crm_admin_component.inc index a79d80ec2..88f134644 100644 --- a/includes/wf_crm_admin_component.inc +++ b/includes/wf_crm_admin_component.inc @@ -373,7 +373,7 @@ class wf_crm_admin_component { } } // CSS trick to add currency symbol to options element keys - $symbol = wf_crm_get_civi_setting('defaultCurrencySymbol', '$'); + $symbol = wf_crm_aval(CRM_Core_Config::singleton(), 'defaultCurrencySymbol', '$'); backdrop_add_css(' .option-key-cell:before { content:"' . $symbol . '"; diff --git a/includes/wf_crm_admin_form.inc b/includes/wf_crm_admin_form.inc index 770fa223c..e0cf387e9 100644 --- a/includes/wf_crm_admin_form.inc +++ b/includes/wf_crm_admin_form.inc @@ -652,12 +652,6 @@ class wf_crm_admin_form { '#multiple' => TRUE, ); $this->help($this->form['caseTab']['case'][$fs]["case_{$n}_settings_existing_case_status"], 'existing_case_status'); - $this->form['caseTab']['case'][$fs]["case_{$n}_settings_duplicate_case"] = array( - '#type' => 'checkbox', - '#title' => t('Create new case based on existing case'), - '#default_value' => wf_crm_aval($this->data, "case:{$n}:duplicate_case", 0), - ); - $this->help($this->form['caseTab']['case'][$fs]["case_{$n}_settings_duplicate_case"], 'duplicate_case_status'); $case_type = wf_crm_aval($this->data, "case:{$n}:case:1:case_type_id"); foreach ($this->filterCaseSets($case_type) as $sid => $set) { $fs1 = "case_case_{$n}_fieldset_$sid"; @@ -700,8 +694,9 @@ class wf_crm_admin_form { if ($sid == 'caseRoles') { // Lookup case-role names $creator = $manager = NULL; - $case_types = wf_crm_apivalues('case_type', 'get', array('id' => $case_type)); - foreach ($case_types as $type) { + // Use the vanilla civicrm_api for this because it will throw an error in CiviCRM 4.4 (api doesn't exist) + $case_types = civicrm_api('case_type', 'get', array('version' => 3, 'id' => $case_type, 'options' => array('limit' => 0))); + foreach (wf_crm_aval($case_types, 'values', array()) as $type) { foreach ($type['definition']['caseRoles'] as $role) { if (!empty($role['creator'])) { $creator = ($creator == $role['name'] || $creator === NULL) ? $role['name'] : FALSE; @@ -1672,11 +1667,6 @@ class wf_crm_admin_form { if (substr($key, 0, 7) == 'civicrm') { ++$i; $field = wf_crm_get_field($key); - if (substr($key, -11) === '_createmode') { - // Update webform's settings with 'Create mode' value for custom group. - $this->settings['data']['config']['create_mode'][$key] = $val; - } - if (!isset($enabled[$key])) { $val = (array) $val; if (in_array('create_civicrm_webform_element', $val, TRUE) || (!empty($val[0]) && $field['type'] == 'hidden')) { @@ -1707,6 +1697,10 @@ class wf_crm_admin_form { webform_component_update($component); } + if (substr($key, -11) === '_createmode') { + // Update webform's settings with 'Create mode' value for custom group. + $this->settings['data']['config']['create_mode'][$key] = $val; + } } // add empty fieldsets for custom civicrm sets with no fields, if "add dynamically" is checked elseif (strpos($key, 'settings_dynamic_custom') && $val == 1) { @@ -2020,7 +2014,7 @@ class wf_crm_admin_form { * Default value callback */ public static function get_default_contact_cs($fid, $options) { - return wf_crm_get_civi_setting('checksum_timeout', 7); + return CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'checksum_timeout', NULL, 7); } /** diff --git a/includes/wf_crm_admin_help.inc b/includes/wf_crm_admin_help.inc index aba5b31b1..dac666895 100644 --- a/includes/wf_crm_admin_help.inc +++ b/includes/wf_crm_admin_help.inc @@ -138,6 +138,8 @@ class wf_crm_admin_help { public static function contribution_payment_processor_id() { print '

' . t('Supported payment processors enabled on the contribution page are available here. "Pay Later" option allows the user to purchase events/memberships without entering a credit card.') . + '

' . + t("Note that only on-site credit card processors are currently supported on Webforms. Services that redirect to an external website, such as Paypal Standard, are not supported. Recurring payments are not supported.") . '

'; } @@ -348,7 +350,7 @@ class wf_crm_admin_help { public static function activity_assignee_contact_id() { civicrm_initialize(); print '

'; - if (wf_crm_get_civi_setting('activity_assignee_notification')) { + if (CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'activity_assignee_notification')) { print t('A copy of this activity will be emailed to the assignee.'); } else { @@ -380,16 +382,6 @@ class wf_crm_admin_help { '

'; } - public static function duplicate_case_status() { - print '

' . - t('Choosing this option means a new case will always be created even when an existing case has been selected. If an existing case has been selected the data for this case will NOT be updated.') . - '

' . - t('Useful if you want to pre-fill a form with existing case data, allow the user to make updates and then create a new case with their updates.') . - '

' . - t('Note: Populate the existing case by selecting an option from the Update Existing Case drop-down or by passing "case1=[caseid]" in the url etc.') . - '

'; - } - public static function existing_grant_status() { print '

' . t('If a matching grant of the chosen type already exists for the applicant, it will be autofilled and updated.') . diff --git a/includes/wf_crm_webform_ajax.inc b/includes/wf_crm_webform_ajax.inc index 67afb7cb7..415f0dec8 100644 --- a/includes/wf_crm_webform_ajax.inc +++ b/includes/wf_crm_webform_ajax.inc @@ -134,7 +134,7 @@ class wf_crm_webform_ajax extends wf_crm_webform_base { } } // Populate related contacts - elseif ($i > $c && $field == 'existing') { + elseif ($c == 1 && $i > $c && $field == 'existing') { $related_component = $this->getComponent($fid); if (wf_crm_aval($related_component['extra'], 'default') == 'relationship') { $old_related_cid = wf_crm_aval($this->ent, "contact:$i:id"); diff --git a/includes/wf_crm_webform_base.inc b/includes/wf_crm_webform_base.inc index 6498522ab..5eeaa3e4c 100755 --- a/includes/wf_crm_webform_base.inc +++ b/includes/wf_crm_webform_base.inc @@ -59,7 +59,7 @@ abstract class wf_crm_webform_base { return $this->_contribution_page; case 'tax_rate': - $taxSettings = wf_crm_get_civi_setting('contribution_invoice_settings'); + $taxSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); if (is_array($taxSettings) && !empty($taxSettings['invoicing'])) { if ($this->contribution_page) { // tax integration @@ -208,6 +208,19 @@ abstract class wf_crm_webform_base { $rel = $this->getRelationship($types, $cid, wf_crm_aval($this->ent['contact'], "$r:id")); if ($rel) { $info['relationship'][$r] = $rel; + // Fetch custom data + $len = strlen($prefix . 'custom_'); + foreach ($this->enabled as $k => $v) { + if (substr($k, 0, $len) == $prefix . 'custom_') { + $custom = wf_civicrm_api('custom_value', 'get', array('entity_id' => $rel['id'], 'entity_table' => 'Relationship')); + foreach ($custom['values'] as $k => $v) { + if (isset($v[0])) { + $info['relationship'][$r]["custom_$k"] = $v[0]; + } + } + break; + } + } } } } @@ -481,40 +494,39 @@ abstract class wf_crm_webform_base { * @return array */ protected function getRelationship($r_types, $cid1, $cid2) { - $found = []; - $active_only = !empty($this->settings['create_new_relationship']); + $found = array(); + $active_clause = ''; + if (!empty($this->settings['create_new_relationship'])) { + $active_clause = 'AND is_active = 1 AND (end_date IS NULL OR end_date >= now())'; + } if ($r_types && $cid1 && $cid2) { - $types = []; + $types = array(); foreach ($r_types as $r_type) { list($type, $side) = explode('_', $r_type); $types[$type] = $type; } - $params = [ - 'contact_id_a' => ['IN' => [$cid1, $cid2]], - 'contact_id_b' => ['IN' => [$cid1, $cid2]], - 'relationship_type_id' => ['IN' => $types], - ]; - if ($active_only) { - $params['is_active'] = 1; - $params['options']['sort'] = 'is_active DESC, end_date ASC'; - } - foreach (wf_crm_apivalues('relationship', 'get', $params) as $rel) { - $type = $rel['relationship_type_id']; - $side = $rel['contact_id_a'] == $cid1 ? 'a' : 'b'; - if ( - // Verify relationship orientation - (in_array("{$type}_$side", $r_types) || in_array("{$type}_r", $r_types)) - // Verify 2 contacts are different unless we're specifically looking for a self-relationship - && ($rel['contact_id_a'] != $rel['contact_id_b'] || $cid1 == $cid2) - // Verify end date is not past when searching for active only - && (empty($rel['end_date']) || !$active_only || strtotime($rel['end_date']) > time()) - ) { + $sql = "SELECT * FROM civicrm_relationship + WHERE relationship_type_id IN (" . implode(',', $types) . ") + AND ((contact_id_a = $cid1 AND contact_id_b = $cid2) OR (contact_id_a = $cid2 AND contact_id_b = $cid1)) $active_clause + ORDER BY is_active DESC, IF(end_date, 1, 0), end_date DESC"; + $dao = CRM_Core_DAO::executeQuery($sql); + while ($dao->fetch()) { + $type = $dao->relationship_type_id; + $side = $dao->contact_id_a == $cid1 ? 'a' : 'b'; + // Verify this is the correct orientation for the relationship + if (in_array("{$type}_$side", $r_types) || in_array("{$type}_r", $r_types)) { + // Discard metadata from the query + foreach ((array) $dao as $k => $v) { + if ($k[0] != '_' && $k != 'N' && $k != 'relationship_type_id') { + $found[$k] = $v; + } + } // Support multi-valued relationship type fields, fudge the rest $found['relationship_type_id'][] = in_array("{$type}_r", $r_types) ? "{$type}_r" : "{$type}_$side"; - $found['relationship_permission'] = (!empty($rel['is_permission_a_b']) ? 1 : 0) + (!empty($rel['is_permission_b_a']) ? 2 : 0); - $found += $rel; + $found['relationship_permission'] = ($found['is_permission_a_b'] ? 1 : 0) + ($found['is_permission_b_a'] ? 2 : 0); } } + $dao->free(); } return $found; } @@ -605,18 +617,37 @@ abstract class wf_crm_webform_base { /** * Fetch info and remaining spaces for events + * + * @param $events + * Array of event info to fill (reference) */ protected function loadEvents() { if (!empty($this->events)) { $now = time(); - $events = wf_crm_apivalues('Event', 'get', [ - 'return' => ['title', 'start_date', 'end_date', 'event_type_id', 'max_participants', 'financial_type_id', 'event_full_text', 'is_full'], - 'id' => ['IN' => array_keys($this->events)], - ]); - foreach ($events as $id => $event) { - $this->events[$id] = $event + $this->events[$id] + ['available_places' => 0]; - $this->events[$id]['ended'] = !empty($event['end_date']) && strtotime($event['end_date']) < $now; + // Fetch event info + $dao = CRM_Core_DAO::executeQuery('SELECT id, title, start_date, end_date, event_type_id, max_participants, financial_type_id + FROM civicrm_event WHERE id IN (' . implode(',', array_keys($this->events)) . ')'); + while ($dao->fetch()) { + $this->events[$dao->id]['title'] = $dao->title; + $this->events[$dao->id]['start_date'] = $dao->start_date; + $this->events[$dao->id]['end_date'] = $dao->end_date; + $this->events[$dao->id]['event_type_id'] = $dao->event_type_id; + $this->events[$dao->id]['financial_type_id'] = $dao->financial_type_id; + $this->events[$dao->id]['full'] = FALSE; + $this->events[$dao->id]['ended'] = $dao->end_date && strtotime($dao->end_date) < $now; + if ($this->events[$dao->id]['max_participants'] = $dao->max_participants) { + $remaining = CRM_Event_BAO_Participant::eventFull($dao->id, TRUE, FALSE); + if (is_string($remaining)) { + $this->events[$dao->id]['full'] = TRUE; + $this->events[$dao->id]['remaining'] = 0; + $this->events[$dao->id]['full_message'] = $remaining; + } + else { + $this->events[$dao->id]['remaining'] = $remaining ? $remaining : $dao->max_participants; + } + } } + $dao->free(); } } @@ -633,7 +664,7 @@ abstract class wf_crm_webform_base { * @return array */ protected function getCustomData($entity_id, $entity_type = NULL, $normalize = TRUE) { - static $parents = []; + static $parents = array(); if (empty($parents)) { // Create matching table to sort fields by group foreach (wf_crm_get_fields() as $key => $value) { @@ -643,25 +674,36 @@ abstract class wf_crm_webform_base { } } } - $params = ['entity_id' => $entity_id]; + $params = array('entityID' => $entity_id); if ($entity_type) { - $params['entity_table'] = ucfirst($entity_type); + $params['entityType'] = ucfirst($entity_type); + } + $result = CRM_Core_BAO_CustomValueTable::getValues($params); + if (!empty($result['is_error'])) { + return array(); } - $result = wf_crm_apivalues('CustomValue', 'get', $params); - $values = []; + unset($result['is_error'], $result['entityID']); + $values = array(); + // Convert multi-value strings to arrays and sort by group foreach ($result as $key => $value) { - $name = 'custom_' . $key; - // Sort into groups - if (isset($parents[$name])) { - $n = 1; - foreach ($value as $id => $item) { - // Non-numeric keys are api extras like "id" and "latest" - if (is_numeric($id)) { - $values[$parents[$name]][$normalize ? $n++ : $id][$name] = $item; - } + $pieces = explode('_', $key); + if ($pieces[0] == 'custom') { + $name = 'custom_' . $pieces[1]; + if (empty($pieces[2])) { + $pieces[2] = ($normalize ? 1 : 0); + } + if (isset($parents[$name])) { + $values[$parents[$name]][$pieces[2]][$name] = $value; } } } + if ($normalize) { + // Normalize array keys + foreach ($values as &$value) { + array_unshift($value, 0); + unset($value[0]); + } + } return $values; } @@ -900,14 +942,19 @@ abstract class wf_crm_webform_base { 'icon' => $val, ); } - $file = wf_crm_apivalues('Attachment', 'get', $val); + $file = wf_crm_apivalues('file', 'get', $val); + $entity_id = ''; + if ($entity && $n && (strpos($fieldName, 'custom_') === 0 || strpos($fieldName, 'file_') === 0)) { + $entity_id = $this->ent[$entity][$n]['id']; + } if (!empty($file[$val])) { - return [ + $fileHash = is_callable(array('CRM_Core_BAO_File', 'generateFileHash')) ? '&fcs=' . CRM_Core_BAO_File::generateFileHash($entity_id, $val) : ''; + return array( 'data_type' => 'File', - 'name' => $file[$val]['name'], - 'file_url'=> $file[$val]['url'], - 'icon' => file_icon_url((object) ['filemime' => $file[$val]['mime_type']]), - ]; + 'name' => CRM_Utils_File::cleanFileName($file[$val]['uri']), + 'file_url'=> CRM_Utils_System::url('civicrm/file', "reset=1&id={$val}&eid={$entity_id}{$fileHash}", TRUE), + 'icon' => file_icon_url((object) array('filemime' => $file[$val]['mime_type'])), + ); } return NULL; } @@ -948,22 +995,4 @@ abstract class wf_crm_webform_base { return CRM_Core_Key::get('CRM_Contribute_Controller_Contribution', TRUE); } - /** - * Historically webform_civicrm was configured with the live payment processor ID and the is_test flag. - * But this is not how CiviCRM expects it to work and this can cause problems where payments use the live processor - * instead of test. So we "fix" the processor ID here to be the correct one for live/test. - * An "improved" fix would involve changing the configuration saved by the user but this avoids that. - * - * @throws \CiviCRM_API3_Exception - */ - protected function fixPaymentProcessorID() { - // Check for is_test and payment_processor_id (pay later = 0 is set to '' here. is_test has no meaning for pay later). - if (!empty($this->data['contribution'][1]['contribution'][1]['is_test']) - && !empty($this->data['contribution'][1]['contribution'][1]['payment_processor_id'])) { - $paymentProcessor = \Civi\Payment\System::singleton()->getById($this->data['contribution'][1]['contribution'][1]['payment_processor_id']); - $paymentProcessor = \Civi\Payment\System::singleton()->getByName($paymentProcessor->getPaymentProcessor()['name'], TRUE); - $this->data['contribution'][1]['contribution'][1]['payment_processor_id'] = $paymentProcessor->getPaymentProcessor()['id']; - } - } - } diff --git a/includes/wf_crm_webform_postprocess.inc b/includes/wf_crm_webform_postprocess.inc index 4e65ff97b..a0e5af080 100644 --- a/includes/wf_crm_webform_postprocess.inc +++ b/includes/wf_crm_webform_postprocess.inc @@ -43,7 +43,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $this->node = $node; $this->settings = $node->webform_civicrm; $this->data = $this->settings['data']; - $this->fixPaymentProcessorID(); $this->enabled = wf_crm_enabled_fields($node); $this->all_fields = wf_crm_get_fields(); $this->all_sets = wf_crm_get_fields('sets'); @@ -332,7 +331,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $country_id = $this->crmValues[$ckey]; } else { - $country_id = wf_crm_get_civi_setting('defaultContactCountry', 1228); + $config = CRM_Core_Config::singleton(); + $country_id = $config->defaultContactCountry; } $states = wf_crm_get_states($country_id); if ($states && !array_key_exists(strtoupper($element['#value']), $states)) { @@ -386,12 +386,14 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { continue; } $participants = current(wf_crm_aval($this->data['contact'], "$c:contact", array())); + $firstName = CRM_Utils_Array::value('first_name', $participants); + $lastName = CRM_Utils_Array::value('last_name', $participants); - $participantName = ($participants['first_name'] ?? '') . ' ' . ($participants['last_name'] ?? ''); + $participantName = "{$firstName} {$lastName}"; if (!trim($participantName)) { - $participantName = $participants['webform_label'] ?? NULL; + $participantName = CRM_Utils_Array::value('webform_label', $participants); if (!empty($this->existing_contacts[$c])) { - $participantName = wf_crm_apivalues('contact', 'get', $this->existing_contacts[$c], 'display_name')[0]; + $participantName = CRM_Contact_BAO_Contact::displayName($this->existing_contacts[$c]); } } foreach (wf_crm_aval($par, 'participant', array()) as $n => $p) { @@ -406,7 +408,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { 'entity_table' => 'civicrm_participant', 'event_id' => $eid, 'contact_ids' => $contacts, - 'unit_price' => $p['fee_amount'] ?? 0, + 'unit_price' => $p['fee_amount'], 'element' => "civicrm_{$c}_participant_{$n}_participant_{$id_and_type}", 'contact_label' => $participantName, ); @@ -417,29 +419,28 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { // Subtract events already registered for - this only works with known contacts $cids = array_filter($this->existing_contacts); if ($this->events && $cids) { - $status_types = wf_crm_apivalues('participant_status_type', 'get', ['is_counted' => 1, 'return' => 'id']); - $existing = wf_crm_apivalues('Participant', 'get', [ - 'return' => ['event_id', 'contact_id'], - 'event_id' => ['IN' => array_keys($this->events)], - 'status_id' => ['IN' => array_keys($status_types)], - 'contact_id' => ['IN' => $cids], - 'is_test' => 0, - ]); - foreach ($existing as $participant) { - if (isset($this->events[$participant['event_id']])) { - if (!(--$this->events[$participant['event_id']]['count'])) { - unset($this->events[$participant['event_id']]); + $dao = CRM_Core_DAO::executeQuery("SELECT event_id, contact_id + FROM civicrm_participant p, civicrm_participant_status_type s + WHERE s.id = p.status_id AND s.is_counted = 1 + AND event_id IN (" . implode(',', array_keys($this->events)) . ") + AND contact_id IN (" . implode(',', $cids) . ") + AND is_test = 0"); + while ($dao->fetch()) { + if (isset($this->events[$dao->event_id])) { + if (!(--$this->events[$dao->event_id]['count'])) { + unset($this->events[$dao->event_id]); } } foreach ($this->line_items as $k => &$item) { - if ($participant['event_id'] == $item['event_id'] && in_array($participant['contact_id'], $item['contact_ids'])) { - unset($this->line_items[$k]['contact_ids'][array_search($participant['contact_id'], $item['contact_ids'])]); + if ($dao->event_id == $item['event_id'] && in_array($dao->contact_id, $item['contact_ids'])) { + unset($this->line_items[$k]['contact_ids'][array_search($dao->contact_id, $item['contact_ids'])]); if (!(--$item['qty'])) { unset($this->line_items[$k]); } } } } + $dao->free(); } $this->loadEvents(); // Add event info to line items @@ -455,12 +456,12 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { if ($event['ended']) { form_set_error($eid, t('Sorry, you can no longer register for %event.', array('%event' => $event['title']))); } - elseif (!empty($event['max_participants']) && $event['count'] > $event['available_places']) { - if (!empty($event['is_full'])) { - form_set_error($eid, '' . $event['title'] . ': ' . $event['event_full_text']); + elseif ($event['max_participants'] && $event['count'] > $event['remaining']) { + if (!empty($event['full'])) { + form_set_error($eid, '' . $event['title'] . ': ' . $event['full_message']); } else { - form_set_error($eid, format_plural($event['available_places'], + form_set_error($eid, format_plural($event['remaining'], 'Sorry, you tried to register !count people for %event but there is only 1 space remaining.', 'Sorry, you tried to register !count people for %event but there are only @count spaces remaining.', array('%event' => $event['title'], '!count' => $event['count']))); @@ -756,8 +757,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { foreach ($contact['address'] as &$address) { // Translate state/prov abbr to id if (!empty($address['state_province_id'])) { - $default_country = wf_crm_get_civi_setting('defaultContactCountry', 1228); - if (!($address['state_province_id'] = wf_crm_state_abbr($address['state_province_id'], 'id', wf_crm_aval($address, 'country_id', $default_country)))) { + $config = CRM_Core_Config::singleton(); + if (!($address['state_province_id'] = wf_crm_state_abbr($address['state_province_id'], 'id', wf_crm_aval($address, 'country_id', $config->defaultContactCountry)))) { $address['state_province_id'] = ''; } } @@ -910,18 +911,14 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $params['method'] = 'Webform'; break; case 'tag': - $api = 'EntityTag'; + $api = 'entity_tag'; break; default: $api = $data_type; } if (!empty($add) || !empty($remove)) { // Retrieve current records for this entity - if ($api == 'EntityTag') { - $params['entity_id'] = $id; - $params['entity_table'] = 'civicrm_' . $entity_type; - } - elseif ($api == 'group_contact' && $entity_type == 'contact') { + if ($entity_type == 'contact') { $params['contact_id'] = $id; } else { @@ -1041,12 +1038,11 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $n = $this->data['participant_reg_type'] == 'separate' ? $c : 1; if ($p = wf_crm_aval($this->data, "participant:$n:participant")) { // Fetch existing participant records - $existing = wf_crm_apivalues('Participant', 'get', [ - 'return' => ["event_id"], - 'contact_id' => $cid, - 'is_test' => 0, - ]); - $existing = array_column($existing, 'id', 'event_id'); + $existing = array(); + $dao = CRM_Core_DAO::executeQuery("SELECT id, event_id FROM civicrm_participant WHERE contact_id = $cid AND is_test = 0"); + while ($dao->fetch()) { + $existing[$dao->event_id] = $dao->id; + } foreach ($p as $e => $params) { $remove = array(); $fid = "civicrm_{$c}_participant_{$e}_participant_event_id"; @@ -1108,8 +1104,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { unset($params['status_id']); } $result = wf_civicrm_api('participant', 'create', $params); - $this->ent['participant'][$n]['id'] = $result['id']; - // Update line-item foreach ($this->line_items as &$item) { if ($item['element'] == "civicrm_{$n}_participant_{$e}_participant_{$id_and_type}") { @@ -1278,8 +1272,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { if (is_array($data) && !empty($data['case'][1]['client_id'])) { $params = $data['case'][1]; // Set some defaults in create mode - // Create duplicate case based on existing case if 'duplicate_case' checkbox is checked - if (empty($this->ent['case'][$n]['id']) || !empty($this->data['case'][$n]['duplicate_case'])) { + if (empty($this->ent['case'][$n]['id'])) { if (empty($params['case_type_id'])) { // Abort if no case type. continue; @@ -1319,8 +1312,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $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 @@ -1429,8 +1420,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $activity = wf_civicrm_api('activity', 'create', $params); // Final processing if save was successful if (!empty($activity['id'])) { - // handle activity tags - $this->handleEntityTags('activity', $activity['id'], $n, $params); // Store id $this->ent['activity'][$n]['id'] = $activity['id']; // Save custom data & attachments @@ -1439,7 +1428,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $this->processAttachments('activity', $n, $activity['id'], empty($params['id'])); } if (!empty($params['assignee_contact_id'])) { - if (wf_crm_get_civi_setting('activity_assignee_notification')) { + if (CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::SYSTEM_PREFERENCES_NAME, 'activity_assignee_notification')) { // Send email to assignees. TODO: Move to CiviCRM API? $assignees = wf_crm_apivalues('contact', 'get', array( 'id' => array('IN' => (array) $params['assignee_contact_id']), @@ -1464,28 +1453,6 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { } } - /** - * Handle adding/updating tags for entities (cases, activity) - * - * @param $entityType - * @param $entityId - * @param $n - * @param $params - */ - function handleEntityTags($entityType, $entityId, $n, $params) { - foreach ($this->all_fields as $fid => $field) { - list($set, $type) = explode('_', $fid, 2); - if ($set == $entityType && isset($field['table']) && $field['table'] == 'tag') { - $field_name = 'civicrm_' . $n . '_' . $entityType. '_1_' . $fid; - if (isset($this->enabled[$field_name]) && isset($this->data[$entityType][$n])) { - $add = wf_crm_aval($this->data[$entityType][$n], $entityType . ":1:$type", array()); - $remove = $this->getExposedOptions($field_name, $add); - $this->addOrRemoveMultivaluedData('tag', $entityType, $entityId, $add, $remove); - } - } - } - } - /** * Process the submission into the details of the activity. */ @@ -1718,12 +1685,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { // Email for ($i = 1; $i <= $this->data['contact'][1]['number_of_email']; ++$i) { if (!empty($this->crmValues["civicrm_1_contact_{$i}_email_email"])) { - // Force email value to contain a string. - // For saved draft $this->form_state['storage']['submitted'] contains - // a form values wrapped with array and this causes a payment error - // (because email appears as array($email_value) instead of $email_value). - $emailArray = (array) $this->crmValues["civicrm_1_contact_{$i}_email_email"]; - $params['email'] = array_shift($emailArray); + $params['email'] = $this->crmValues["civicrm_1_contact_{$i}_email_email"]; break; } } @@ -1923,6 +1885,13 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $params = $this->contributionParams(); $params['contribution_status_id'] = 'Pending'; $params['is_pay_later'] = $this->contributionIsPayLater; + //Fix IPN payments marked as paid by cheque + if (empty($params['payment_instrument_id'])) { + if (!empty($params['payment_processor_id']) && $this->contribution_page['is_monetary']) { + $defaultPaymentInstrument = CRM_Core_OptionGroup::values('payment_instrument', FALSE, FALSE, FALSE, 'AND is_default = 1'); + $params['payment_instrument_id'] = key($defaultPaymentInstrument); + } + } $numInstallments = wf_crm_aval($params, 'installments', NULL, TRUE); $frequencyInterval = wf_crm_aval($params, 'frequency_unit'); @@ -1942,8 +1911,18 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { private function submitIPNPayment() { $params = $this->data['contribution'][1]['contribution'][1]; $processor_type = wf_civicrm_api('payment_processor', 'getsingle', array('id' => $params['payment_processor_id'])); - $paymentProcessor = \Civi\Payment\System::singleton()->getById($params['payment_processor_id']); - + if (version_compare($this->civicrm_version, 4.7, '<')) { + $mode = empty($params['is_test']) ? 'live' : 'test'; + $paymentProcessor = CRM_Core_Payment::singleton($mode, $processor_type); + } + else { + $paymentProcessor = \Civi\Payment\System::singleton()->getById($params['payment_processor_id']); + // Ideally we would pass the correct id for the test processor through but that seems not to be the + // case so load it here. + if (!empty($params['is_test'])) { + $paymentProcessor = \Civi\Payment\System::singleton()->getByName($processor_type['name'], TRUE); + } + } // Add contact details to params (most processors want a first_name and last_name) $contact = wf_civicrm_api('contact', 'getsingle', array('id' => $this->ent['contact'][1]['id'])); $params += $contact; @@ -1974,6 +1953,10 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $paymentProcessor->setSuccessUrl($this->getIpnRedirectUrl('success')); $paymentProcessor->setCancelUrl($this->getIpnRedirectUrl('cancel')); } + // Legacy paypal settings. Remove when dropping support for CiviCRM 4.6 and below. + // @see webform_civicrm_civicrm_alterPaymentProcessorParams + $params['webform_redirect_cancel'] = $this->getIpnRedirectUrl('cancel'); + $params['webform_redirect_success'] = $this->getIpnRedirectUrl('success'); if (method_exists($paymentProcessor, 'doTransferCheckout')) { //Paypal Express checkout @@ -2088,25 +2071,46 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { } } - if (empty($params['payment_instrument_id'])) { - $params['payment_instrument_id'] = $this->getPaymentInstrument($params['payment_processor_id']); + // Fix bug for testing. + if ($params['is_test'] == 1) { + $liveProcessorName = wf_civicrm_api('payment_processor', 'getvalue', array( + 'id' => $params['payment_processor_id'], + 'return' => 'name', + )); + // Lookup current domain for multisite support + static $domain = 0; + if (!$domain) { + $domain = wf_civicrm_api('domain', 'get', array('current_domain' => 1, 'return' => 'id')); + $domain = wf_crm_aval($domain, 'id', 1); + } + $params['payment_processor_id'] = wf_civicrm_api('payment_processor', 'getvalue', array( + 'return' => 'id', + 'name' => $liveProcessorName, + 'is_test' => 1, + 'domain_id' => $domain, + )); } // doPayment requries payment_processor and payment_processor_mode fields. - $params['payment_processor'] = wf_crm_aval($params, 'payment_processor_id'); - - if (!empty($params['credit_card_number'])) { - if (!empty($params['credit_card_type'])) { - $result = wf_civicrm_api('OptionValue', 'get', array( - 'return' => ['value'], - 'option_group_id.name' => 'accept_creditcard', - 'name' => ucfirst($params['credit_card_type']), - )); - if (!empty($result['id'])) { - $params['card_type_id'] = $result['values'][$result['id']]['value']; + if (version_compare($this->civicrm_version, '4.7', '>=')) { + $params['payment_processor'] = wf_crm_aval($params, 'payment_processor_id'); + } + + // Record additional parameters if we're processing a credit card after version 4.7.17 (CRM-20158) + if (version_compare($this->civicrm_version, '4.7.17', '>=')) { + if (!empty($params['credit_card_number'])) { + if (!empty($params['credit_card_type'])) { + $result = wf_civicrm_api('OptionValue', 'get', array( + 'return' => ['value'], + 'option_group_id.name' => 'accept_creditcard', + 'name' => ucfirst($params['credit_card_type']), + )); + if (!empty($result['id'])) { + $params['card_type_id'] = $result['values'][$result['id']]['value']; + } } + $params['pan_truncation'] = substr($params['credit_card_number'],-4); } - $params['pan_truncation'] = substr($params['credit_card_number'],-4); } // Save this stuff for later @@ -2326,7 +2330,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $val = array_unique(array_merge($val, $this->data[$ent][$c][$table][$n][$name])); } // 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) { + if ($table !== 'other' && $name !== 'event_id' && $name !== 'relationship_type_id' && $table !== 'contact' && $dataType != 'ContactReference') { $val = CRM_Utils_Array::implodePadded($val); } } @@ -2368,7 +2372,7 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { $val = $sum; } else { - $val = is_array($val) ? reset($val) : $val; + $val = isset($val[0]) ? $val[0] : ''; } if ($component['type'] == 'autocomplete' && is_string($val) && strlen($val)) { $options = wf_crm_field_options($component, '', $this->data); @@ -2377,7 +2381,8 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { // Fudge together date and time fields if ($field['type'] === 'time' && substr($name, -8) === 'timepart') { $name = str_replace('_timepart', '', $name); - $date = wf_crm_aval($this->data, "$ent:$c:$table:$n:$name", ''); + // Add date (default to today) + $date = wf_crm_aval($this->data, "$ent:$c:$table:$n:$name", date('Ymd')); $val = $date . str_replace(':', '', $val); } // Only known contacts are allowed to empty a field @@ -2611,9 +2616,4 @@ class wf_crm_webform_postprocess extends wf_crm_webform_base { return $values; } - - private function getPaymentInstrument($paymentProcessorId) { - $processor = \Civi\Payment\System::singleton()->getById($paymentProcessorId); - return $processor->getPaymentInstrumentID(); - } } diff --git a/includes/wf_crm_webform_preprocess.inc b/includes/wf_crm_webform_preprocess.inc index df2f0c892..629f4c8e4 100644 --- a/includes/wf_crm_webform_preprocess.inc +++ b/includes/wf_crm_webform_preprocess.inc @@ -21,7 +21,6 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { $this->node = $form['#node']; $this->settings = $this->node->webform_civicrm; $this->data = $this->settings['data']; - $this->fixPaymentProcessorID(); $this->ent['contact'] = array(); $this->all_fields = wf_crm_get_fields(); $this->all_sets = wf_crm_get_fields('sets'); @@ -176,15 +175,15 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { 'scope' => 'footer', ); $this->form['#attached']['css'][] = backdrop_get_path('module', 'webform_civicrm') . '/css/webform_civicrm_forms.css'; - $default_country = wf_crm_get_civi_setting('defaultContactCountry', 1228); + $config = CRM_Core_Config::singleton(); // Variables to push to the client-side $js_vars = array(); // JS Cache eliminates the need for most ajax state/province callbacks foreach ($this->data['contact'] as $c) { if (!empty($c['number_of_address'])) { $js_vars += array( - 'defaultCountry' => $default_country, - 'defaultStates' => wf_crm_get_states($default_country), + 'defaultCountry' => $config->defaultContactCountry, + 'defaultStates' => wf_crm_get_states($config->defaultContactCountry), 'noCountry' => t('- First Choose a Country -'), 'callbackPath' => url('webform-civicrm/js', array('alias' => TRUE)), ); @@ -198,10 +197,18 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { 'data' => backdrop_get_path('module', 'webform_civicrm') . '/js/webform_civicrm_payment.js', 'scope' => 'footer', ); - $currency = $this->contribution_page['currency']; - $contributionCallbackQuery = array('currency' => $currency, 'snippet' => 4); - $contributionCallbackUrl = 'civicrm/payment/form'; - $js_vars['processor_id_key'] = 'processor_id'; + $page_id = $this->data['contribution'][1]['contribution'][1]['contribution_page_id']; + if (version_compare($this->civicrm_version, '4.7', '>=')) { + $currency = $this->contribution_page['currency']; + $contributionCallbackQuery = array('currency' => $currency, 'snippet' => 4); + $contributionCallbackUrl = 'civicrm/payment/form'; + $js_vars['processor_id_key'] = 'processor_id'; + } + else { + $contributionCallbackQuery = array('reset' => 1, 'id' => $page_id, 'qfKey' => $this->getQfKey(), 'snippet' => 4); + $contributionCallbackUrl = 'civicrm/contribute/transact'; + $js_vars['processor_id_key'] = 'type'; + } if (!empty($this->data['contribution'][1]['contribution'][1]['is_test'])) { // RM: This is needed in order for CiviCRM to know that this is a 'test' (i.e. 'preview' action in CiviCRM) transaction - otherwise, CiviCRM defaults to 'live' and returns the payment form with public key for the live payment processor! $contributionCallbackQuery['action'] = CRM_Core_Action::description(CRM_Core_Action::PREVIEW); @@ -280,15 +287,15 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { $this->setMessage(t('Sorry, %event has ended.', array('%event' => $event['title'])), 'warning'); } } - elseif (!empty($event['is_full'])) { + elseif ($event['full']) { if (!empty($reg['show_remaining'])) { - $this->setMessage('' . check_plain($event['title']) . ': ' . check_plain($event['event_full_text']), 'warning'); + $this->setMessage('' . check_plain($event['title']) . ': ' . check_plain($event['full_message']), 'warning'); } } else { $reg['block_form'] = FALSE; - if (!empty($event['max_participants']) && ($reg['show_remaining'] == 'always' || intval($reg['show_remaining']) >= $event['available_places'])) { - $this->setMessage(format_plural($event['available_places'], + if ($event['max_participants'] && ($reg['show_remaining'] == 'always' || intval($reg['show_remaining']) >= $event['remaining'])) { + $this->setMessage(format_plural($event['remaining'], '%event has 1 remaining space.', '%event has @count remaining spaces.', array('%event' => $event['title']))); @@ -307,20 +314,23 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { * @param int $c */ private function loadParticipants($c) { + $select = array('id', 'event_id', 'role_id', 'status_id'); + if (array_key_exists('participant_campaign_id', $this->all_fields)) { + $select[] = 'campaign_id'; + } $status_types = wf_crm_apivalues('participant_status_type', 'get'); - $participants = wf_crm_apivalues('participant', 'get', [ - 'contact_id' => $this->ent['contact'][$c]['id'], - 'event_id' => ['IN' => array_keys($this->events)], - ]); - foreach ($participants as $row) { - $par = []; - // v3 participant api returns some non-standard keys with participant_ prepended - foreach (['id', 'event_id', 'role_id', 'status_id', 'campaign_id'] as $sel) { - $par['participant'][1][$sel] = $row[$sel] = $row[$sel] ?? $row['participant_' . $sel] ?? NULL; - } - $par += $this->getCustomData($row['id'], 'Participant'); - $status = $status_types[$row['status_id']]; - foreach ($this->events[$row['event_id']]['form'] as $event) { + $dao = CRM_Core_DAO::executeQuery('SELECT ' . implode(',', $select) . ' + FROM civicrm_participant + WHERE contact_id = ' . $this->ent['contact'][$c]['id'] . ' AND event_id IN (' . implode(',', array_keys($this->events)) . ")" + ); + while ($dao->fetch()) { + $par = array(); + foreach ($select as $sel) { + $par['participant'][1][$sel] = $dao->$sel; + } + $par += $this->getCustomData($dao->id, 'Participant'); + $status = $status_types[$dao->status_id]; + foreach ($this->events[$dao->event_id]['form'] as $event) { if ($event['contact'] == $c) { // If status has been set by admin or exposed to the form, use it as a filter if (in_array($status['id'], $event['status_id']) || @@ -342,6 +352,7 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { } } } + $dao->free(); } /** @@ -571,7 +582,7 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { if (!is_null($itemTaxRate)) { // Change the line item label to display the tax rate it contains - $taxSettings = wf_crm_get_civi_setting('contribution_invoice_settings'); + $taxSettings = CRM_Core_BAO_Setting::getItem(CRM_Core_BAO_Setting::CONTRIBUTE_PREFERENCES_NAME, 'contribution_invoice_settings'); if (($taxSettings['tax_display_settings'] != 'Do_not_show') && ($itemTaxRate !== 0)) { $item['label'] .= ' (' . t('includes !rate @tax', array('!rate' => (float)$itemTaxRate . '%', '@tax' => $taxSettings['tax_term'])) . ')'; @@ -775,7 +786,17 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { } } if ($items) { - $values = wf_crm_apivalues($type, 'get', array('id' => array('IN' => array_values($items)))); + // Todo: Remove when we drop support for 4.4 - https://www.drupal.org/node/2832331 + if (version_compare($this->civicrm_version, '4.6.0', '<')) { + $values = array(); + foreach ($items as $id) { + $value = wf_crm_apivalues($type, 'get', array('id' => $id)); + $values[$id] = $value[$id]; + } + } + else { + $values = wf_crm_apivalues($type, 'get', array('id' => array('IN' => array_values($items)))); + } foreach ($items as $n => $id) { if (isset($values[$id])) { // Load core + custom data @@ -786,14 +807,6 @@ class wf_crm_webform_preprocess extends wf_crm_webform_base { $this->info[$type][$n]["{$type}upload"][1]["file_$f"] = $file['file_id']; } } - // Load tags - $tags = NULL; - foreach (array_keys($this->enabled) as $fid) { - if (strpos($fid, "civicrm_{$n}_{$type}_1_{$type}_tag") === 0) { - $tags = $tags ?? wf_crm_apivalues('EntityTag', 'get', ['entity_id' => $id, 'entity_table' => "civicrm_" . $type, 'sequential' => 1], 'tag_id'); - $this->info[$type][$n][$type][1][str_replace("civicrm_{$n}_{$type}_1_{$type}_", '', $fid)] = $tags; - } - } } } } diff --git a/js/webform_civicrm_admin.js b/js/webform_civicrm_admin.js index 7fe2bbfb5..7a056a746 100644 --- a/js/webform_civicrm_admin.js +++ b/js/webform_civicrm_admin.js @@ -568,7 +568,7 @@ var wfCiviAdmin = (function ($, D) { * TODO: Move more code here! Backdrop's version of jQuery is ancient. * TODO: change 'cj' to 'CRM.$' when we drop support for Civi v4.4 */ - CRM.$(function($) { + cj(function($) { // Inline help $('#wf-crm-configure-form, #webform-component-edit-form').on('click', 'a.helpicon', function () { var topic = $(this).attr('href').substr(1); diff --git a/webform_civicrm.info b/webform_civicrm.info index 66e387d86..38a3426e9 100644 --- a/webform_civicrm.info +++ b/webform_civicrm.info @@ -3,6 +3,6 @@ description = A powerful, flexible, user-friendly form builder for CiviCRM. backdrop = 1.x type = module package = CiviCRM -php = 7.0 -dependencies[] = civicrm (>=5.12) -dependencies[] = webform (>=4.19) +dependencies[] = civicrm +dependencies[] = webform (>=4.12) + diff --git a/webform_civicrm.module b/webform_civicrm.module index e4bd7b9e5..3fc0e688b 100644 --- a/webform_civicrm.module +++ b/webform_civicrm.module @@ -10,10 +10,10 @@ /** * The versions of CiviCRM and WebForm. Min is >=. Max is <. FALSE = no MAX */ -define('WEBFORM_CIVICRM_CIVICRM_VERSION_MIN', '1.x-5.12.0'); +define('WEBFORM_CIVICRM_CIVICRM_VERSION_MIN', '1.x-4.7.0'); define('WEBFORM_CIVICRM_CIVICRM_VERSION_MAX', FALSE); -define('WEBFORM_CIVICRM_WEBFORM_VERSION', '1.x-4.19.0'); +define('WEBFORM_CIVICRM_WEBFORM_VERSION', '1.x-1.1.0'); /** * Implements hook_config_info(). @@ -390,13 +390,6 @@ function webform_civicrm_webform_submission_actions($node, $submission) { 'query' => array('action' => 'view', 'reset' => 1, 'cid' => $data['contact'][1]['id'], 'id' => $data['contribution'][1]['id']), ); } - if (!empty($data['participant'][1]['id'])) { - $actions['civicrm_action participant_view'] = array( - 'title' => t('View Participant'), - 'href' => 'civicrm/contact/view/participant', - 'query' => array('action' => 'view', 'reset' => 1, 'cid' => $data['contact'][1]['id'], 'id' => $data['participant'][1]['id']), - ); - } } } return $actions; @@ -608,6 +601,23 @@ function webform_civicrm_preprocess_webform_components_form(&$vars) { wf_crm_admin_component::preprocessComponentsForm($vars['form'], $vars['rows'], $vars['form']['#node']); } +/** + * Implements hook_civicrm_alterPaymentProcessorParams(). + * + * Legacy handling for paypal. + * We use it to override the return url so that the user gets redirected to the right place from paypal. + * + * Remove when dropping support for CiviCRM 4.6 and below. + */ +function webform_civicrm_civicrm_alterPaymentProcessorParams($paymentObj, $rawParams, &$cookedParams) { + if (!empty($rawParams['webform_redirect_cancel']) && !empty($rawParams['webform_redirect_success']) + && !empty($cookedParams['return']) && !empty($cookedParams['cancel_return']) + ) { + $cookedParams['return'] = $rawParams['webform_redirect_success']; + $cookedParams['cancel_return'] = $rawParams['webform_redirect_cancel']; + } +} + /** * Return a value from nested arrays or objects. *