Move setImportStatus to parent
[civicrm-core.git] / CRM / Import / Form / MapField.php
CommitLineData
b26295b8
CW
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
b26295b8 5 | |
bc77d7c0
TO
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 |
b26295b8 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
b26295b8
CW
11
12/**
b26295b8 13 * @package CRM
ca5cec67 14 * @copyright CiviCRM LLC https://civicrm.org/licensing
b26295b8
CW
15 */
16
17/**
2b4bc760 18 * This class gets the name of the file to upload.
19 *
b26295b8
CW
20 * TODO: CRM-11254 - There's still a lot of duplicate code in the 5 child classes that should be moved here
21 */
5e8faabc 22abstract class CRM_Import_Form_MapField extends CRM_Import_Forms {
b26295b8
CW
23
24 /**
100fef9d 25 * Cache of preview data values
b26295b8
CW
26 *
27 * @var array
b26295b8
CW
28 */
29 protected $_dataValues;
30
31 /**
100fef9d 32 * Mapper fields
b26295b8
CW
33 *
34 * @var array
b26295b8
CW
35 */
36 protected $_mapperFields;
37
b26295b8 38 /**
100fef9d 39 * Number of columns in import file
b26295b8
CW
40 *
41 * @var int
b26295b8
CW
42 */
43 protected $_columnCount;
44
45 /**
100fef9d 46 * Column headers, if we have them
b26295b8
CW
47 *
48 * @var array
b26295b8
CW
49 */
50 protected $_columnHeaders;
51
52 /**
100fef9d 53 * An array of booleans to keep track of whether a field has been used in
b26295b8
CW
54 * form building already.
55 *
56 * @var array
b26295b8
CW
57 */
58 protected $_fieldUsed;
59
60 /**
2b4bc760 61 * Return a descriptive name for the page, used in wizard header.
b26295b8
CW
62 *
63 * @return string
b26295b8
CW
64 */
65 public function getTitle() {
66 return ts('Match Fields');
67 }
68
69 /**
fe482240 70 * Attempt to match header labels with our mapper fields.
b26295b8 71 *
79d7553f 72 * @param string $header
73 * @param array $patterns
b26295b8
CW
74 *
75 * @return string
b26295b8
CW
76 */
77 public function defaultFromHeader($header, &$patterns) {
78 foreach ($patterns as $key => $re) {
79 // Skip empty key/patterns
80 if (!$key || !$re || strlen("$re") < 5) {
81 continue;
82 }
83
84 // Scan through the headerPatterns defined in the schema for a match
85 if (preg_match($re, $header)) {
86 $this->_fieldUsed[$key] = TRUE;
87 return $key;
88 }
89 }
90 return '';
91 }
92
93 /**
fe482240 94 * Guess at the field names given the data and patterns from the schema.
b26295b8 95 *
79d7553f 96 * @param array $patterns
97 * @param string $index
b26295b8
CW
98 *
99 * @return string
b26295b8 100 */
56dd62a0 101 public function defaultFromData($patterns, $index) {
353ffa53 102 $best = '';
b26295b8 103 $bestHits = 0;
353ffa53 104 $n = count($this->_dataValues);
b26295b8
CW
105
106 foreach ($patterns as $key => $re) {
107 // Skip empty key/patterns
108 if (!$key || !$re || strlen("$re") < 5) {
109 continue;
110 }
111
112 /* Take a vote over the preview data set */
113 $hits = 0;
114 for ($i = 0; $i < $n; $i++) {
115 if (isset($this->_dataValues[$i][$index])) {
116 if (preg_match($re, $this->_dataValues[$i][$index])) {
117 $hits++;
118 }
119 }
120 }
121 if ($hits > $bestHits) {
122 $bestHits = $hits;
123 $best = $key;
124 }
125 }
126
127 if ($best != '') {
128 $this->_fieldUsed[$best] = TRUE;
129 }
130 return $best;
131 }
132
ad05d047 133 /**
134 * Add the saved mapping fields to the form.
135 *
136 * @param int|null $savedMappingID
137 *
138 * @throws \CiviCRM_API3_Exception
139 */
140 protected function buildSavedMappingFields($savedMappingID) {
141 //to save the current mappings
142 if (!$savedMappingID) {
143 $saveDetailsName = ts('Save this field mapping');
144 $this->applyFilter('saveMappingName', 'trim');
145 $this->add('text', 'saveMappingName', ts('Name'));
146 $this->add('text', 'saveMappingDesc', ts('Description'));
147 }
148 else {
149 $savedMapping = $this->get('savedMapping');
150
151 $mappingName = (string) civicrm_api3('Mapping', 'getvalue', ['id' => $savedMappingID, 'return' => 'name']);
152 $this->set('loadedMapping', $savedMapping);
ad05d047 153 $this->add('hidden', 'mappingId', $savedMappingID);
154
155 $this->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
156 $saveDetailsName = ts('Save as a new field mapping');
157 $this->add('text', 'saveMappingName', ts('Name'));
158 $this->add('text', 'saveMappingDesc', ts('Description'));
159 }
262b7f26 160 $this->assign('savedMappingName', $mappingName ?? NULL);
ad05d047 161 $this->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, ['onclick' => "showSaveDetails(this)"]);
162 }
163
02a237ce 164 /**
165 * Validate that sufficient fields have been supplied to match to a contact.
166 *
167 * @param string $contactType
168 * @param array $importKeys
169 *
170 * @return string
171 * Message if insufficient fields are present. Empty string otherwise.
172 */
173 protected static function validateRequiredContactMatchFields(string $contactType, array $importKeys): string {
61194d45 174 [$ruleFields, $threshold] = CRM_Dedupe_BAO_DedupeRuleGroup::dedupeRuleFieldsWeight([
02a237ce 175 'used' => 'Unsupervised',
176 'contact_type' => $contactType,
177 ]);
178 $weightSum = 0;
179 foreach ($importKeys as $key => $val) {
180 if (array_key_exists($val, $ruleFields)) {
181 $weightSum += $ruleFields[$val];
182 }
183 }
184 $fieldMessage = '';
185 foreach ($ruleFields as $field => $weight) {
186 $fieldMessage .= ' ' . $field . '(weight ' . $weight . ')';
187 }
188 if ($weightSum < $threshold) {
189 return $fieldMessage . ' ' . ts('(Sum of all weights should be greater than or equal to threshold: %1).', array(
190 1 => $threshold,
191 ));
192 }
193 return '';
194 }
195
73edfc10
EM
196 /**
197 * Get the field mapped to the savable format.
198 *
199 * @param array $fieldMapping
200 * @param int $mappingID
201 * @param int $columnNumber
202 *
203 * @return array
204 * @throws \CRM_Core_Exception
205 */
206 protected function getMappedField(array $fieldMapping, int $mappingID, int $columnNumber): array {
207 return $this->getParser()->getMappingFieldFromMapperInput($fieldMapping, $mappingID, $columnNumber);
208 }
209
210 /**
211 * Save the mapping field.
212 *
213 * @param int $mappingID
214 * @param int $columnNumber
215 * @param bool $isUpdate
216 *
217 * @throws \API_Exception
218 * @throws \CRM_Core_Exception
219 */
220 protected function saveMappingField(int $mappingID, int $columnNumber, bool $isUpdate = FALSE): void {
221 $fieldMapping = (array) $this->getSubmittedValue('mapper')[$columnNumber];
222 $mappedField = $this->getMappedField($fieldMapping, $mappingID, $columnNumber);
223 if ($isUpdate) {
224 Civi\Api4\MappingField::update(FALSE)
225 ->setValues($mappedField)
226 ->addWhere('column_number', '=', $columnNumber)
227 ->addWhere('mapping_id', '=', $mappingID)
228 ->execute();
229 }
230 else {
231 Civi\Api4\MappingField::create(FALSE)
232 ->setValues($mappedField)->execute();
233 }
234 }
235
b26295b8 236}