3 +--------------------------------------------------------------------+
4 | Copyright CiviCRM LLC. All rights reserved. |
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
9 +--------------------------------------------------------------------+
15 * @copyright CiviCRM LLC https://civicrm.org/licensing
19 * This class gets the name of the file to upload
21 class CRM_Event_Import_Form_MapField
extends CRM_Import_Form_MapField
{
24 * Set variables up before form is built.
28 public function preProcess() {
29 $this->_mapperFields
= $this->get('fields');
30 asort($this->_mapperFields
);
31 unset($this->_mapperFields
['participant_is_test']);
32 $this->_columnCount
= $this->get('columnCount');
33 $this->assign('columnCount', $this->_columnCount
);
34 $this->_dataValues
= $this->get('dataValues');
35 $this->assign('dataValues', $this->_dataValues
);
37 $skipColumnHeader = $this->controller
->exportValue('DataSource', 'skipColumnHeader');
38 $this->_onDuplicate
= $this->get('onDuplicate');
39 $highlightedFields = [];
40 if ($skipColumnHeader) {
41 $this->assign('skipColumnHeader', $skipColumnHeader);
42 $this->assign('rowDisplayCount', 3);
43 /* if we had a column header to skip, stash it for later */
45 $this->_columnHeaders
= $this->_dataValues
[0];
48 $this->assign('rowDisplayCount', 2);
50 if ($this->_onDuplicate
== CRM_Import_Parser
::DUPLICATE_UPDATE
) {
51 $remove = array('participant_contact_id', 'email', 'first_name', 'last_name', 'external_identifier');
52 foreach ($remove as $value) {
53 unset($this->_mapperFields
[$value]);
55 $highlightedFieldsArray = array('participant_id', 'event_id', 'event_title', 'participant_status_id');
56 foreach ($highlightedFieldsArray as $name) {
57 $highlightedFields[] = $name;
60 elseif ($this->_onDuplicate
== CRM_Import_Parser
::DUPLICATE_SKIP ||
61 $this->_onDuplicate
== CRM_Import_Parser
::DUPLICATE_NOCHECK
63 unset($this->_mapperFields
['participant_id']);
64 $highlightedFieldsArray = array(
65 'participant_contact_id',
70 'external_identifier',
71 'participant_status_id',
73 foreach ($highlightedFieldsArray as $name) {
74 $highlightedFields[] = $name;
77 $this->assign('highlightedFields', $highlightedFields);
81 * Build the form object.
85 public function buildQuickForm() {
87 //to save the current mappings
88 if (!$this->get('savedMapping')) {
89 $saveDetailsName = ts('Save this field mapping');
90 $this->applyFilter('saveMappingName', 'trim');
91 $this->add('text', 'saveMappingName', ts('Name'));
92 $this->add('text', 'saveMappingDesc', ts('Description'));
95 $savedMapping = $this->get('savedMapping');
97 list($mappingName, $mappingContactType, $mappingLocation, $mappingPhoneType, $mappingRelation) = CRM_Core_BAO_Mapping
::getMappingFields($savedMapping);
99 $mappingName = $mappingName[1];
100 $mappingContactType = $mappingContactType[1];
101 $mappingLocation = $mappingLocation['1'] ??
NULL;
102 $mappingPhoneType = $mappingPhoneType['1'] ??
NULL;
103 $mappingRelation = $mappingRelation['1'] ??
NULL;
105 //mapping is to be loaded from database
107 $this->set('loadedMapping', $savedMapping);
109 $getMappingName = new CRM_Core_DAO_Mapping();
110 $getMappingName->id
= $savedMapping;
111 $getMappingName->mapping_type
= 'Import Participants';
112 $getMappingName->find();
113 while ($getMappingName->fetch()) {
114 $mapperName = $getMappingName->name
;
117 $this->assign('savedMappingName', $mapperName);
119 $this->add('hidden', 'mappingId', $savedMapping);
121 $this->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
122 $saveDetailsName = ts('Save as a new field mapping');
123 $this->add('text', 'saveMappingName', ts('Name'));
124 $this->add('text', 'saveMappingDesc', ts('Description'));
127 $this->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, array('onclick' => "showSaveDetails(this)"));
129 $this->addFormRule(array('CRM_Event_Import_Form_MapField', 'formRule'), $this);
132 $mapperKeys = array_keys($this->_mapperFields
);
133 $hasHeaders = !empty($this->_columnHeaders
);
134 $headerPatterns = $this->get('headerPatterns');
135 $dataPatterns = $this->get('dataPatterns');
136 $hasLocationTypes = $this->get('fieldTypes');
137 /* Initialize all field usages to false */
139 foreach ($mapperKeys as $key) {
140 $this->_fieldUsed
[$key] = FALSE;
142 $this->_location_types
= CRM_Core_PseudoConstant
::get('CRM_Core_DAO_Address', 'location_type_id');
143 $sel1 = $this->_mapperFields
;
146 $js = "<script type='text/javascript'>\n";
147 $formName = 'document.forms.' . $this->_name
;
149 //used to warn for mismatch column count or mismatch mapping
151 for ($i = 0; $i < $this->_columnCount
; $i++
) {
152 $sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', array(1 => $i)), NULL);
154 if ($this->get('savedMapping')) {
155 if (isset($mappingName[$i])) {
156 if ($mappingName[$i] != ts('- do not import -')) {
158 $mappingHeader = array_keys($this->_mapperFields
, $mappingName[$i]);
160 if (!isset($locationId) ||
!$locationId) {
161 $js .= "{$formName}['mapper[$i][1]'].style.display = 'none';\n";
164 if (!isset($phoneType) ||
!$phoneType) {
165 $js .= "{$formName}['mapper[$i][2]'].style.display = 'none';\n";
168 $js .= "{$formName}['mapper[$i][3]'].style.display = 'none';\n";
169 $defaults["mapper[$i]"] = array(
171 (isset($locationId)) ?
$locationId : "",
172 (isset($phoneType)) ?
$phoneType : "",
177 $defaults["mapper[$i]"] = [];
180 for ($k = 1; $k < 4; $k++
) {
181 $js .= "{$formName}['mapper[$i][$k]'].style.display = 'none';\n";
186 // this load section to help mapping if we ran out of saved columns when doing Load Mapping
187 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_" . $i . "_');\n";
190 $defaults["mapper[$i]"] = array($this->defaultFromHeader($this->_columnHeaders
[$i], $headerPatterns));
193 $defaults["mapper[$i]"] = array($this->defaultFromData($dataPatterns, $i));
196 //end of load mapping
199 $js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_" . $i . "_');\n";
201 // Infer the default from the skipped headers if we have them
202 $defaults["mapper[$i]"] = array(
203 $this->defaultFromHeader($this->_columnHeaders
[$i],
206 // $defaultLocationType->id
211 // Otherwise guess the default from the form of the data
212 $defaults["mapper[$i]"] = array(
213 $this->defaultFromData($dataPatterns, $i),
214 // $defaultLocationType->id
219 $sel->setOptions(array($sel1, $sel2, (isset($sel3)) ?
$sel3 : "", (isset($sel4)) ?
$sel4 : ""));
221 $js .= "</script>\n";
222 $this->assign('initHideBoxes', $js);
224 //set warning if mismatch in more than
225 if (isset($mappingName)) {
226 if (($this->_columnCount
!= count($mappingName))) {
230 if ($warning != 0 && $this->get('savedMapping')) {
231 $session = CRM_Core_Session
::singleton();
232 $session->setStatus(ts('The data columns in this import file appear to be different from the saved mapping. Please verify that you have selected the correct saved mapping before continuing.'));
235 $session = CRM_Core_Session
::singleton();
236 $session->setStatus(NULL);
239 $this->setDefaults($defaults);
241 $this->addButtons(array(
244 'name' => ts('Previous'),
248 'name' => ts('Continue'),
249 'spacing' => ' ',
254 'name' => ts('Cancel'),
260 * Global validation rules for the form.
262 * @param array $fields
263 * Posted values of the form.
269 * list of errors to be posted back to the form
271 public static function formRule($fields, $files, $self) {
273 // define so we avoid notices below
274 $errors['_qf_default'] = '';
275 $contactFieldsBelowWeightMessage = NULL;
276 if (!array_key_exists('savedMapping', $fields)) {
278 foreach ($fields['mapper'] as $mapperPart) {
279 $importKeys[] = $mapperPart[0];
281 // FIXME: should use the schema titles, not redeclare them
282 $requiredFields = array(
283 'participant_contact_id' => ts('Contact ID'),
284 'event_id' => ts('Event ID'),
287 $contactTypeId = $self->get('contactType');
288 $contactTypes = array(
289 CRM_Import_Parser
::CONTACT_INDIVIDUAL
=> 'Individual',
290 CRM_Import_Parser
::CONTACT_HOUSEHOLD
=> 'Household',
291 CRM_Import_Parser
::CONTACT_ORGANIZATION
=> 'Organization',
293 $contactFieldsBelowWeightMessage = self
::validateRequiredContactMatchFields($contactTypes[$contactTypeId], $importKeys);
295 foreach ($requiredFields as $field => $title) {
296 if (!in_array($field, $importKeys)) {
297 if ($field == 'participant_contact_id') {
298 if (!$contactFieldsBelowWeightMessage ||
in_array('external_identifier', $importKeys) ||
299 in_array('participant_id', $importKeys)
303 if ($self->_onDuplicate
== CRM_Import_Parser
::DUPLICATE_UPDATE
) {
304 $errors['_qf_default'] .= ts('Missing required field: Provide Participant ID') . '<br />';
307 $errors['_qf_default'] .= ts('Missing required contact matching fields.') . " $contactFieldsBelowWeightMessage " . ' ' . ts('Or Provide Contact ID or External ID.') . '<br />';
310 elseif (!in_array('event_title', $importKeys)) {
311 $errors['_qf_default'] .= ts('Missing required field: Provide %1 or %2',
312 array(1 => $title, 2 => 'Event Title')
319 if (!empty($fields['saveMapping'])) {
320 $nameField = $fields['saveMappingName'] ??
NULL;
321 if (empty($nameField)) {
322 $errors['saveMappingName'] = ts('Name is required to save Import Mapping');
325 if (CRM_Core_BAO_Mapping
::checkMapping($nameField, CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Participant'))) {
326 $errors['saveMappingName'] = ts('Duplicate Import Participant Mapping Name');
331 //display Error if loaded mapping is not selected
332 if (array_key_exists('loadMapping', $fields)) {
333 $getMapName = $fields['savedMapping'] ??
NULL;
334 if (empty($getMapName)) {
335 $errors['savedMapping'] = ts('Select saved mapping');
339 if (empty($errors['_qf_default'])) {
340 unset($errors['_qf_default']);
342 if (!empty($errors)) {
343 if (!empty($errors['saveMappingName'])) {
345 $assignError = new CRM_Core_Page();
346 $assignError->assign('mappingDetailsError', $_flag);
355 * Process the mapped fields and map it into the uploaded file
356 * preview the file and extract some summary statistics
360 public function postProcess() {
361 $params = $this->controller
->exportValues('MapField');
362 //reload the mapfield if load mapping is pressed
363 if (!empty($params['savedMapping'])) {
364 $this->set('savedMapping', $params['savedMapping']);
365 $this->controller
->resetPage($this->_name
);
370 $mapperKeys = $this->controller
->exportValue($this->_name
, 'mapper');
371 $mapperKeysMain = [];
373 for ($i = 0; $i < $this->_columnCount
; $i++
) {
374 $mapper[$i] = $this->_mapperFields
[$mapperKeys[$i][0]];
375 $mapperKeysMain[$i] = $mapperKeys[$i][0];
378 $this->set('mapper', $mapper);
380 // store mapping Id to display it in the preview page
381 $this->set('loadMappingId', CRM_Utils_Array
::value('mappingId', $params));
383 //Updating Mapping Records
384 if (!empty($params['updateMapping'])) {
386 $mappingFields = new CRM_Core_DAO_MappingField();
387 $mappingFields->mapping_id
= $params['mappingId'];
388 $mappingFields->find();
390 $mappingFieldsId = [];
391 while ($mappingFields->fetch()) {
392 if ($mappingFields->id
) {
393 $mappingFieldsId[$mappingFields->column_number
] = $mappingFields->id
;
397 for ($i = 0; $i < $this->_columnCount
; $i++
) {
398 $updateMappingFields = new CRM_Core_DAO_MappingField();
399 $updateMappingFields->id
= $mappingFieldsId[$i];
400 $updateMappingFields->mapping_id
= $params['mappingId'];
401 $updateMappingFields->column_number
= $i;
402 $updateMappingFields->name
= $mapper[$i];
403 $updateMappingFields->save();
407 //Saving Mapping Details and Records
408 if (!empty($params['saveMapping'])) {
409 $mappingParams = array(
410 'name' => $params['saveMappingName'],
411 'description' => $params['saveMappingDesc'],
412 'mapping_type_id' => CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Participant'),
414 $saveMapping = CRM_Core_BAO_Mapping
::add($mappingParams);
416 for ($i = 0; $i < $this->_columnCount
; $i++
) {
417 $saveMappingFields = new CRM_Core_DAO_MappingField();
418 $saveMappingFields->mapping_id
= $saveMapping->id
;
419 $saveMappingFields->column_number
= $i;
420 $saveMappingFields->name
= $mapper[$i];
421 $saveMappingFields->save();
423 $this->set('savedMapping', $saveMappingFields->mapping_id
);
426 $parser = new CRM_Event_Import_Parser_Participant($mapperKeysMain);
427 $parser->run($this->getSubmittedValue('uploadFile'), $this->getSubmittedValue('fieldSeparator'), $mapper, $this->getSubmittedValue('skipColumnHeader'),
428 CRM_Import_Parser
::MODE_PREVIEW
, $this->get('contactType')
430 // add all the necessary variables to the form