Merge pull request #23567 from kurund/honor-roll-fixes
[civicrm-core.git] / CRM / Contact / Import / Form / DataSource.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 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 |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
bc77d7c0 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17
18/**
f12c6f7d 19 * This class delegates to the chosen DataSource to grab the data to be imported.
6a488035 20 */
39dc35d4 21class CRM_Contact_Import_Form_DataSource extends CRM_Import_Forms {
6a488035 22
0a6789e4
EM
23 /**
24 * Get any smarty elements that may not be present in the form.
25 *
26 * To make life simpler for smarty we ensure they are set to null
27 * rather than unset. This is done at the last minute when $this
28 * is converted to an array to be assigned to the form.
29 *
30 * @return array
31 */
a1a6b259 32 public function getOptionalQuickFormElements(): array {
0a6789e4
EM
33 return ['disableUSPS'];
34 }
35
6a488035 36 /**
fe482240 37 * Set variables up before form is built.
54c32137 38 *
39 * @throws \CRM_Core_Exception
6a488035
TO
40 */
41 public function preProcess() {
be2fb01f 42 $results = [];
353ffa53
TO
43 $config = CRM_Core_Config::singleton();
44 $handler = opendir($config->uploadDir);
be2fb01f 45 $errorFiles = ['sqlImport.errors', 'sqlImport.conflicts', 'sqlImport.duplicates', 'sqlImport.mismatch'];
6a488035 46
f4a17080 47 // check for post max size avoid when called twice
2975f0aa 48 $snippet = $_GET['snippet'] ?? 0;
f4a17080 49 if (empty($snippet)) {
2e966dd5 50 CRM_Utils_Number::formatUnitSize(ini_get('post_max_size'), TRUE);
f4a17080 51 }
66dc6009 52
6a488035 53 while ($file = readdir($handler)) {
2e68a233 54 if ($file !== '.' && $file !== '..' &&
6a488035
TO
55 in_array($file, $errorFiles) && !is_writable($config->uploadDir . $file)
56 ) {
57 $results[] = $file;
58 }
59 }
60 closedir($handler);
61 if (!empty($results)) {
15f71590 62 $this->invalidConfig(ts('<b>%1</b> file(s) in %2 directory are not writable. Listed file(s) might be used during the import to log the errors occurred during Import process. Contact your site administrator for assistance.', [
69078420
SL
63 1 => implode(', ', $results),
64 2 => $config->uploadDir,
65 ]));
6a488035 66 }
6a488035
TO
67 }
68
69 /**
fe482240 70 * Build the form object.
d452dfe6
EM
71 *
72 * @throws \CRM_Core_Exception
6a488035 73 */
6a488035
TO
74 public function buildQuickForm() {
75
d452dfe6 76 $this->assign('urlPath', 'civicrm/import/datasource');
7b057b66 77 $this->assign('urlPathVar', 'snippet=4&user_job_id=' . $this->get('user_job_id'));
6a488035 78
39dc35d4 79 $this->add('select', 'dataSource', ts('Data Source'), $this->getDataSources(), TRUE,
be2fb01f 80 ['onchange' => 'buildDataSourceFormBlock(this.value);']
6a488035
TO
81 );
82
83 // duplicate handling options
39405208
SL
84 $this->addRadio('onDuplicate', ts('For Duplicate Contacts'), [
85 CRM_Import_Parser::DUPLICATE_SKIP => ts('Skip'),
86 CRM_Import_Parser::DUPLICATE_UPDATE => ts('Update'),
87 CRM_Import_Parser::DUPLICATE_FILL => ts('Fill'),
88 CRM_Import_Parser::DUPLICATE_NOCHECK => ts('No Duplicate Checking'),
89 ]);
6a488035 90
f8df7165 91 $mappingArray = CRM_Core_BAO_Mapping::getMappings('Import Contact');
6a488035
TO
92
93 $this->assign('savedMapping', $mappingArray);
5658157f 94 $this->addElement('select', 'savedMapping', ts('Saved Field Mapping'), ['' => ts('- select -')] + $mappingArray);
6a488035 95
be2fb01f 96 $js = ['onClick' => "buildSubTypes();buildDedupeRules();"];
6a488035 97 // contact types option
39405208 98 $contactTypeOptions = $contactTypeAttributes = [];
6a488035 99 if (CRM_Contact_BAO_ContactType::isActive('Individual')) {
39405208
SL
100 $contactTypeOptions[CRM_Import_Parser::CONTACT_INDIVIDUAL] = ts('Individual');
101 $contactTypeAttributes[CRM_Import_Parser::CONTACT_INDIVIDUAL] = $js;
6a488035
TO
102 }
103 if (CRM_Contact_BAO_ContactType::isActive('Household')) {
39405208
SL
104 $contactTypeOptions[CRM_Import_Parser::CONTACT_HOUSEHOLD] = ts('Household');
105 $contactTypeAttributes[CRM_Import_Parser::CONTACT_HOUSEHOLD] = $js;
6a488035
TO
106 }
107 if (CRM_Contact_BAO_ContactType::isActive('Organization')) {
39405208
SL
108 $contactTypeOptions[CRM_Import_Parser::CONTACT_ORGANIZATION] = ts('Organization');
109 $contactTypeAttributes[CRM_Import_Parser::CONTACT_ORGANIZATION] = $js;
6a488035 110 }
39405208 111 $this->addRadio('contactType', ts('Contact Type'), $contactTypeOptions, [], NULL, FALSE, $contactTypeAttributes);
6a488035 112
80cb71bb 113 $this->addElement('select', 'contactSubType', ts('Subtype'));
dfa2f16c 114 $this->addElement('select', 'dedupe_rule_id', ts('Dedupe Rule'));
6a488035
TO
115
116 CRM_Core_Form_Date::buildAllowedDateFormats($this);
117
6a488035 118 $geoCode = FALSE;
4882d275 119 if (CRM_Utils_GeocodeProvider::getUsableClassName()) {
6a488035 120 $geoCode = TRUE;
3255187a 121 $this->addElement('checkbox', 'doGeocodeAddress', ts('Geocode addresses during import?'));
6a488035
TO
122 }
123 $this->assign('geoCode', $geoCode);
124
be2fb01f 125 $this->addElement('text', 'fieldSeparator', ts('Import Field Separator'), ['size' => 2]);
6a488035 126
ceda4d90 127 if (Civi::settings()->get('address_standardization_provider') === 'USPS') {
fd830836
DRJ
128 $this->addElement('checkbox', 'disableUSPS', ts('Disable USPS address validation during import?'));
129 }
d452dfe6 130 $this->buildDataSourceFields();
fd830836 131
be2fb01f 132 $this->addButtons([
69078420
SL
133 [
134 'type' => 'upload',
135 'name' => ts('Continue'),
136 'spacing' => '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;',
137 'isDefault' => TRUE,
138 ],
139 [
140 'type' => 'cancel',
141 'name' => ts('Cancel'),
142 ],
143 ]);
6a488035
TO
144 }
145
86538308 146 /**
2b4bc760 147 * Set the default values of various form elements.
86538308 148 *
a6c01b45
CW
149 * @return array
150 * reference to the array of default values
86538308 151 */
00be9182 152 public function setDefaultValues() {
be2fb01f 153 $defaults = [
d452dfe6 154 'dataSource' => $this->getDefaultDataSource(),
a05662ef
CW
155 'onDuplicate' => CRM_Import_Parser::DUPLICATE_SKIP,
156 'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
2e68a233 157 'fieldSeparator' => CRM_Core_Config::singleton()->fieldSeparator,
be2fb01f 158 ];
6a488035 159
29c42168
EM
160 if ($this->get('loadedMapping')) {
161 $defaults['savedMapping'] = $this->get('loadedMapping');
6a488035
TO
162 }
163
164 return $defaults;
165 }
166
6a488035 167 /**
f12c6f7d 168 * Call the DataSource's postProcess method.
d452dfe6
EM
169 *
170 * @throws \CRM_Core_Exception
7b057b66 171 * @throws \API_Exception
6a488035
TO
172 */
173 public function postProcess() {
174 $this->controller->resetPage('MapField');
7b057b66
EM
175 if (!$this->getUserJobID()) {
176 $this->createUserJob();
177 }
178 else {
1163561b 179 $this->flushDataSource();
7b057b66
EM
180 $this->updateUserJobMetadata('submitted_values', $this->getSubmittedValues());
181 }
d69fecb9 182
80cb71bb
EM
183 // @todo - this params are being set here because they were / possibly still
184 // are in some places being accessed by forms later in the flow
185 // ie CRM_Contact_Import_Form_MapField, CRM_Contact_Import_Form_Preview
186 // or CRM_Contact_Import_Form_Summary using `$this->get()
187 // which was the old way of saving values submitted on this form such that
188 // the other forms could access them. Now they should use
189 // `getSubmittedValue` or simply not get them if the only
190 // reason is to pass to the Parser which can itself
191 // call 'getSubmittedValue'
192 // Once the mentioned forms no longer call $this->get() all this 'setting'
193 // is obsolete.
d69fecb9 194 $storeParams = [
dfa2f16c
EM
195 'dateFormats' => $this->getSubmittedValue('dateFormats'),
196 'savedMapping' => $this->getSubmittedValue('savedMapping'),
d69fecb9 197 ];
6a488035 198
d69fecb9
EM
199 foreach ($storeParams as $storeName => $value) {
200 $this->set($storeName, $value);
201 }
d69fecb9
EM
202 CRM_Core_Session::singleton()->set('dateTypes', $storeParams['dateFormats']);
203
d69fecb9 204 $this->instantiateDataSource();
d452dfe6
EM
205 }
206
207 /**
208 * Instantiate the datasource.
209 *
210 * This gives the datasource a chance to do any table creation etc.
211 *
1a783cdb 212 * @throws \API_Exception
d452dfe6
EM
213 * @throws \CRM_Core_Exception
214 */
215 private function instantiateDataSource(): void {
1a783cdb 216 $this->getDataSourceObject()->initialize();
6a488035
TO
217 }
218
15f71590 219 /**
220 * General function for handling invalid configuration.
221 *
222 * I was going to statusBounce them all but when I tested I was 'bouncing' to weird places
223 * whereas throwing an exception gave no behaviour change. So, I decided to centralise
224 * and we can 'flip the switch' later.
225 *
226 * @param $message
227 *
228 * @throws \CRM_Core_Exception
229 */
230 protected function invalidConfig($message) {
231 throw new CRM_Core_Exception($message);
232 }
233
6a488035
TO
234 /**
235 * Return a descriptive name for the page, used in wizard header
236 *
6a488035 237 * @return string
6a488035 238 */
ceda4d90 239 public function getTitle(): string {
6a488035
TO
240 return ts('Choose Data Source');
241 }
96025800 242
6a488035 243}