Commit | Line | Data |
---|---|---|
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 | |
ca5cec67 | 15 | * @copyright CiviCRM LLC https://civicrm.org/licensing |
6a488035 TO |
16 | */ |
17 | ||
18 | /** | |
19 | * This class gets the name of the file to upload | |
20 | */ | |
31aaf096 | 21 | class CRM_Export_Form_Select extends CRM_Core_Form_Task { |
6a488035 TO |
22 | |
23 | /** | |
fe482240 | 24 | * Various Contact types. |
6a488035 | 25 | */ |
7da04cde | 26 | const |
0e6e8724 DL |
27 | EXPORT_ALL = 1, |
28 | EXPORT_SELECTED = 2, | |
29 | EXPORT_MERGE_DO_NOT_MERGE = 0, | |
30 | EXPORT_MERGE_SAME_ADDRESS = 1, | |
31 | EXPORT_MERGE_HOUSEHOLD = 2; | |
6a488035 TO |
32 | |
33 | /** | |
fe482240 | 34 | * Export modes. |
6a488035 | 35 | */ |
7da04cde | 36 | const |
0e6e8724 DL |
37 | CONTACT_EXPORT = 1, |
38 | CONTRIBUTE_EXPORT = 2, | |
39 | MEMBER_EXPORT = 3, | |
40 | EVENT_EXPORT = 4, | |
41 | PLEDGE_EXPORT = 5, | |
42 | CASE_EXPORT = 6, | |
43 | GRANT_EXPORT = 7, | |
44 | ACTIVITY_EXPORT = 8; | |
6a488035 TO |
45 | |
46 | /** | |
fe482240 | 47 | * Current export mode. |
6a488035 TO |
48 | * |
49 | * @var int | |
50 | */ | |
51 | public $_exportMode; | |
52 | ||
53 | public $_componentTable; | |
54 | ||
e2710fee | 55 | /** |
56 | * Use the form name to create the tpl file name. | |
57 | * | |
58 | * @return string | |
59 | */ | |
60 | public function getTemplateFileName() { | |
61 | return 'CRM/Export/Form/Select.tpl'; | |
62 | } | |
63 | ||
6a488035 | 64 | /** |
fe482240 | 65 | * Build all the data structures needed to build the form. |
6a488035 TO |
66 | * |
67 | * @param | |
68 | * | |
69 | * @return void | |
6a488035 | 70 | */ |
00be9182 | 71 | public function preProcess() { |
df4c8e9c CW |
72 | $this->preventAjaxSubmit(); |
73 | ||
6a488035 | 74 | //special case for custom search, directly give option to download csv file |
7b845814 | 75 | $customSearchID = $this->get('customSearchID'); |
76 | if ($customSearchID) { | |
77 | CRM_Export_BAO_Export::exportCustom($this->get('customSearchClass'), | |
78 | $this->get('formValues'), | |
79 | $this->get(CRM_Utils_Sort::SORT_ORDER) | |
80 | ); | |
81 | } | |
6a488035 TO |
82 | |
83 | $this->_selectAll = FALSE; | |
84 | $this->_exportMode = self::CONTACT_EXPORT; | |
be2fb01f | 85 | $this->_componentIds = []; |
6a488035 TO |
86 | $this->_componentClause = NULL; |
87 | ||
3b4adc92 | 88 | // FIXME: This should use a modified version of CRM_Contact_Form_Search::getModeValue but it doesn't have all the contexts |
ae70f47e | 89 | // FIXME: Or better still, use CRM_Core_DAO_AllCoreTables::getBriefName($daoName) to get the $entityShortName |
dabe5cd5 | 90 | $entityShortname = $this->getEntityShortName(); |
3b4adc92 | 91 | |
6ec388a8 | 92 | if (!in_array($entityShortname, ['Contact', 'Contribute', 'Member', 'Event', 'Pledge', 'Case', 'Grant', 'Activity'], TRUE)) { |
93 | // This is never reached - the exception here is just to clarify that entityShortName MUST be one of the above | |
94 | // to save future refactorers & reviewers from asking that question. | |
95 | throw new CRM_Core_Exception('Unreachable code'); | |
96 | } | |
97 | $this->_exportMode = constant('CRM_Export_Form_Select::' . strtoupper($entityShortname) . '_EXPORT'); | |
3b4adc92 | 98 | |
ab3e9e4c | 99 | $this::$entityShortname = strtolower($entityShortname); |
2d09a0c3 | 100 | $values = $this->getSearchFormValues(); |
6a488035 TO |
101 | |
102 | $count = 0; | |
103 | $this->_matchingContacts = FALSE; | |
104 | if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_sel') { | |
105 | foreach ($values as $key => $value) { | |
106 | if (strstr($key, 'mark_x')) { | |
107 | $count++; | |
108 | } | |
109 | if ($count > 2) { | |
110 | $this->_matchingContacts = TRUE; | |
111 | break; | |
112 | } | |
113 | } | |
114 | } | |
115 | ||
f95d7a08 | 116 | $this->callPreProcessing(); |
6886d6f2 | 117 | |
3b4adc92 MW |
118 | // $component is used on CRM/Export/Form/Select.tpl to display extra information for contact export |
119 | ($this->_exportMode == self::CONTACT_EXPORT) ? $component = FALSE : $component = TRUE; | |
120 | $this->assign('component', $component); | |
6a488035 | 121 | |
f95d7a08 | 122 | $this->assign('isShowMergeOptions', $this->isShowContactMergeOptions()); |
6a488035 TO |
123 | |
124 | if ($this->_componentTable) { | |
125 | $query = " | |
126 | SELECT count(*) | |
127 | FROM {$this->_componentTable} | |
128 | "; | |
129 | $totalSelectedRecords = CRM_Core_DAO::singleValueQuery($query); | |
130 | } | |
131 | else { | |
132 | $totalSelectedRecords = count($this->_componentIds); | |
133 | } | |
134 | $this->assign('totalSelectedRecords', $totalSelectedRecords); | |
3b4adc92 | 135 | |
6a488035 TO |
136 | // all records actions = save a search |
137 | if (($values['radio_ts'] == 'ts_all') || ($this->_task == CRM_Contact_Task::SAVE_SEARCH)) { | |
138 | $this->_selectAll = TRUE; | |
139 | $rowCount = $this->get('rowCount'); | |
140 | if ($rowCount > 2) { | |
141 | $this->_matchingContacts = TRUE; | |
142 | } | |
143 | $this->assign('totalSelectedRecords', $rowCount); | |
144 | } | |
145 | ||
146 | $this->assign('matchingContacts', $this->_matchingContacts); | |
147 | $this->set('componentIds', $this->_componentIds); | |
148 | $this->set('selectAll', $this->_selectAll); | |
149 | $this->set('exportMode', $this->_exportMode); | |
150 | $this->set('componentClause', $this->_componentClause); | |
ab3e9e4c | 151 | $this->set('componentTable', $this->getTableName()); |
152 | } | |
153 | ||
154 | /** | |
155 | * Get the name of the table for the relevant entity. | |
156 | */ | |
157 | public function getTableName() { | |
158 | throw new CRM_Core_Exception('should be over-riden'); | |
6a488035 TO |
159 | } |
160 | ||
161 | /** | |
fe482240 | 162 | * Build the form object. |
6a488035 TO |
163 | * |
164 | * @return void | |
6a488035 TO |
165 | */ |
166 | public function buildQuickForm() { | |
167 | //export option | |
2428bd14 SL |
168 | $exportOptions = $exportOptionsJS = $mergeOptions = $mergeOptionsJS = $postalMailing = []; |
169 | $exportOptions[self::EXPORT_ALL] = ts('Export PRIMARY fields'); | |
170 | $exportOptions[self::EXPORT_SELECTED] = ts('Select fields for export'); | |
171 | $mergeOptions[self::EXPORT_MERGE_DO_NOT_MERGE] = ts('Do not merge'); | |
172 | $mergeOptions[self::EXPORT_MERGE_SAME_ADDRESS] = ts('Merge All Contacts with the Same Address'); | |
173 | $mergeOptions[self::EXPORT_MERGE_HOUSEHOLD] = ts('Merge Household Members into their Households'); | |
174 | foreach (array_keys($exportOptions) as $key) { | |
175 | $exportOptionsJS[$key] = ['onClick' => 'showMappingOption( );']; | |
176 | } | |
177 | foreach (array_keys($mergeOptions) as $key) { | |
178 | $mergeOptionsJS[$key] = ['onclick' => 'showGreetingOptions( );']; | |
179 | } | |
180 | $this->addRadio('exportOption', ts('Export Type'), $exportOptions, [], '<br/>', FALSE, $exportOptionsJS); | |
6a488035 TO |
181 | $postalMailing[] = $this->createElement('advcheckbox', |
182 | 'postal_mailing_export', | |
183 | NULL, | |
184 | NULL | |
185 | ); | |
186 | ||
6a488035 TO |
187 | if ($this->_matchingContacts) { |
188 | $this->_greetingOptions = self::getGreetingOptions(); | |
189 | ||
190 | foreach ($this->_greetingOptions as $key => $value) { | |
ee769c00 | 191 | $fieldLabel = ts('%1 (when merging contacts)', [1 => ucwords(str_replace('_', ' ', $key))]); |
6a488035 | 192 | $this->addElement('select', $key, $fieldLabel, |
be2fb01f | 193 | $value, ['onchange' => "showOther(this);"] |
6a488035 TO |
194 | ); |
195 | $this->addElement('text', "{$key}_other", ''); | |
196 | } | |
197 | } | |
198 | ||
199 | if ($this->_exportMode == self::CONTACT_EXPORT) { | |
2428bd14 | 200 | $this->addRadio('mergeOption', ts('Merge Options'), $mergeOptions, [], '<br/>', FALSE, $mergeOptionsJS); |
6a488035 TO |
201 | $this->addGroup($postalMailing, 'postal_mailing_export', ts('Postal Mailing Export'), '<br/>'); |
202 | ||
203 | $this->addElement('select', 'additional_group', ts('Additional Group for Export'), | |
be2fb01f CW |
204 | ['' => ts('- select group -')] + CRM_Core_PseudoConstant::nestedGroup(), |
205 | ['class' => 'crm-select2 huge'] | |
6a488035 TO |
206 | ); |
207 | } | |
208 | ||
209 | $this->buildMapping(); | |
210 | ||
be2fb01f | 211 | $this->setDefaults([ |
6a488035 | 212 | 'exportOption' => self::EXPORT_ALL, |
353ffa53 | 213 | 'mergeOption' => self::EXPORT_MERGE_DO_NOT_MERGE, |
be2fb01f | 214 | ]); |
6a488035 | 215 | |
be2fb01f | 216 | $this->addButtons([ |
7b966967 SL |
217 | [ |
218 | 'type' => 'next', | |
219 | 'name' => ts('Continue'), | |
220 | 'spacing' => ' ', | |
221 | 'isDefault' => TRUE, | |
222 | ], | |
223 | [ | |
224 | 'type' => 'cancel', | |
225 | 'name' => ts('Cancel'), | |
226 | ], | |
227 | ]); | |
6a488035 | 228 | |
be2fb01f | 229 | $this->addFormRule(['CRM_Export_Form_Select', 'formRule'], $this); |
6a488035 TO |
230 | } |
231 | ||
232 | /** | |
fe482240 | 233 | * Validation. |
6a488035 | 234 | * |
b9add4b3 TO |
235 | * @param array $params |
236 | * (ref.) an assoc array of name/value pairs. | |
6a488035 | 237 | * |
fd31fa4c EM |
238 | * @param $files |
239 | * @param $self | |
240 | * | |
72b3a70c CW |
241 | * @return bool|array |
242 | * mixed true or array of errors | |
6a488035 | 243 | */ |
a0174743 | 244 | public static function formRule($params, $files, $self) { |
be2fb01f | 245 | $errors = []; |
6a488035 TO |
246 | |
247 | if (CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_SAME_ADDRESS && | |
248 | $self->_matchingContacts | |
249 | ) { | |
be2fb01f | 250 | $greetings = [ |
6a488035 TO |
251 | 'postal_greeting' => 'postal_greeting_other', |
252 | 'addressee' => 'addressee_other', | |
be2fb01f | 253 | ]; |
6a488035 TO |
254 | |
255 | foreach ($greetings as $key => $value) { | |
9c1bc317 | 256 | $otherOption = $params[$key] ?? NULL; |
6a488035 | 257 | |
8cc574cf | 258 | if ((CRM_Utils_Array::value($otherOption, $self->_greetingOptions[$key]) == ts('Other')) && empty($params[$value])) { |
6a488035 TO |
259 | |
260 | $label = ucwords(str_replace('_', ' ', $key)); | |
ee769c00 | 261 | $errors[$value] = ts('Please enter a value for %1 (when merging contacts), or select a pre-configured option from the list.', [1 => $label]); |
6a488035 TO |
262 | } |
263 | } | |
264 | } | |
265 | ||
266 | return empty($errors) ? TRUE : $errors; | |
267 | } | |
268 | ||
269 | /** | |
fe482240 | 270 | * Process the uploaded file. |
6a488035 | 271 | * |
a0174743 | 272 | * @throws \CRM_Core_Exception |
6a488035 TO |
273 | */ |
274 | public function postProcess() { | |
353ffa53 TO |
275 | $params = $this->controller->exportValues($this->_name); |
276 | $exportOption = $params['exportOption']; | |
277 | $mergeSameAddress = CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_SAME_ADDRESS ? 1 : 0; | |
6a488035 TO |
278 | $mergeSameHousehold = CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_HOUSEHOLD ? 1 : 0; |
279 | ||
280 | $this->set('mergeSameAddress', $mergeSameAddress); | |
281 | $this->set('mergeSameHousehold', $mergeSameHousehold); | |
282 | ||
283 | // instead of increasing the number of arguments to exportComponents function, we | |
284 | // will send $exportParams as another argument, which is an array and suppose to contain | |
285 | // all submitted options or any other argument | |
286 | $exportParams = $params; | |
287 | ||
9c1bc317 | 288 | $mappingId = $params['mapping'] ?? NULL; |
6a488035 TO |
289 | if ($mappingId) { |
290 | $this->set('mappingId', $mappingId); | |
291 | } | |
292 | else { | |
293 | $this->set('mappingId', NULL); | |
294 | } | |
295 | ||
6a488035 | 296 | if ($exportOption == self::EXPORT_ALL) { |
7b845814 | 297 | CRM_Export_BAO_Export::exportComponents($this->_selectAll, |
298 | $this->_componentIds, | |
299 | (array) $this->get('queryParams'), | |
300 | $this->get(CRM_Utils_Sort::SORT_ORDER), | |
301 | NULL, | |
302 | $this->get('returnProperties'), | |
303 | $this->_exportMode, | |
304 | $this->_componentClause, | |
305 | $this->_componentTable, | |
306 | $mergeSameAddress, | |
307 | $mergeSameHousehold, | |
308 | $exportParams, | |
309 | $this->get('queryOperator') | |
310 | ); | |
6a488035 TO |
311 | } |
312 | ||
313 | //reset map page | |
314 | $this->controller->resetPage('Map'); | |
315 | } | |
316 | ||
317 | /** | |
318 | * Return a descriptive name for the page, used in wizard header | |
319 | * | |
320 | * @return string | |
6a488035 TO |
321 | */ |
322 | public function getTitle() { | |
653f9ec1 | 323 | return ts('Export Options'); |
6a488035 TO |
324 | } |
325 | ||
326 | /** | |
fe482240 | 327 | * Build mapping form element. |
6a488035 | 328 | */ |
00be9182 | 329 | public function buildMapping() { |
6a488035 TO |
330 | switch ($this->_exportMode) { |
331 | case CRM_Export_Form_Select::CONTACT_EXPORT: | |
332 | $exportType = 'Export Contact'; | |
333 | break; | |
334 | ||
335 | case CRM_Export_Form_Select::CONTRIBUTE_EXPORT: | |
336 | $exportType = 'Export Contribution'; | |
337 | break; | |
338 | ||
339 | case CRM_Export_Form_Select::MEMBER_EXPORT: | |
340 | $exportType = 'Export Membership'; | |
341 | break; | |
342 | ||
343 | case CRM_Export_Form_Select::EVENT_EXPORT: | |
344 | $exportType = 'Export Participant'; | |
345 | break; | |
346 | ||
347 | case CRM_Export_Form_Select::PLEDGE_EXPORT: | |
348 | $exportType = 'Export Pledge'; | |
349 | break; | |
350 | ||
351 | case CRM_Export_Form_Select::CASE_EXPORT: | |
352 | $exportType = 'Export Case'; | |
353 | break; | |
354 | ||
355 | case CRM_Export_Form_Select::GRANT_EXPORT: | |
356 | $exportType = 'Export Grant'; | |
357 | break; | |
358 | ||
359 | case CRM_Export_Form_Select::ACTIVITY_EXPORT: | |
360 | $exportType = 'Export Activity'; | |
361 | break; | |
362 | } | |
363 | ||
95f52e3b | 364 | $this->set('mappingTypeId', CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', $exportType)); |
6a488035 | 365 | |
4f55a797 | 366 | $mappings = CRM_Core_BAO_Mapping::getMappings($exportType, TRUE); |
6a488035 | 367 | if (!empty($mappings)) { |
4f55a797 | 368 | $this->add('select2', 'mapping', ts('Use Saved Field Mapping'), $mappings, FALSE, ['placeholder' => ts('- select -')]); |
6a488035 TO |
369 | } |
370 | } | |
371 | ||
e0ef6999 EM |
372 | /** |
373 | * @return array | |
374 | */ | |
00be9182 | 375 | public static function getGreetingOptions() { |
be2fb01f CW |
376 | $options = []; |
377 | $greetings = [ | |
6a488035 TO |
378 | 'postal_greeting' => 'postal_greeting_other', |
379 | 'addressee' => 'addressee_other', | |
be2fb01f | 380 | ]; |
6a488035 TO |
381 | |
382 | foreach ($greetings as $key => $value) { | |
be2fb01f | 383 | $params = []; |
6a488035 TO |
384 | $optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $key, 'id', 'name'); |
385 | ||
386 | CRM_Core_DAO::commonRetrieveAll('CRM_Core_DAO_OptionValue', 'option_group_id', $optionGroupId, | |
be2fb01f | 387 | $params, ['label', 'filter'] |
6a488035 TO |
388 | ); |
389 | ||
390 | $greetingCount = 1; | |
be2fb01f | 391 | $options[$key] = ["$greetingCount" => ts('List of names')]; |
6a488035 TO |
392 | |
393 | foreach ($params as $id => $field) { | |
394 | if (CRM_Utils_Array::value('filter', $field) == 4) { | |
395 | $options[$key][++$greetingCount] = $field['label']; | |
396 | } | |
397 | } | |
398 | ||
399 | $options[$key][++$greetingCount] = ts('Other'); | |
400 | } | |
401 | ||
402 | return $options; | |
403 | } | |
96025800 | 404 | |
a0174743 | 405 | /** |
acc45bb8 | 406 | * Get the query mode (eg. CRM_Contact_BAO_Query::MODE_CASE) |
a0174743 MW |
407 | * |
408 | * @return int | |
409 | */ | |
410 | public function getQueryMode() { | |
d5fd18f6 | 411 | return (int) ($this->queryMode ?: $this->controller->get('component_mode')); |
a0174743 MW |
412 | } |
413 | ||
f95d7a08 | 414 | /** |
415 | * Call the pre-processing function. | |
416 | */ | |
417 | protected function callPreProcessing(): void { | |
418 | throw new CRM_Core_Exception('This must be over-ridden'); | |
419 | } | |
420 | ||
421 | /** | |
422 | * Assign the title of the task to the tpl. | |
423 | */ | |
424 | protected function isShowContactMergeOptions() { | |
425 | throw new CRM_Core_Exception('This must be over-ridden'); | |
426 | } | |
427 | ||
239d4cf8 | 428 | /** |
429 | * Get the name of the component. | |
430 | * | |
431 | * @return array | |
432 | */ | |
433 | protected function getComponentName(): string { | |
d532b686 | 434 | // CRM_Export_Controller_Standalone has this method |
239d4cf8 | 435 | if (method_exists($this->controller, 'getComponent')) { |
436 | return $this->controller->getComponent(); | |
437 | } | |
d532b686 | 438 | // For others, just guess based on the name of the controller |
239d4cf8 | 439 | $formName = CRM_Utils_System::getClassName($this->controller->getStateMachine()); |
440 | $componentName = explode('_', $formName); | |
441 | return $componentName[1]; | |
442 | } | |
443 | ||
dabe5cd5 | 444 | /** |
445 | * Get the DAO name for the given export. | |
446 | * | |
447 | * @return string | |
448 | */ | |
449 | protected function getDAOName(): string { | |
450 | switch ($this->getQueryMode()) { | |
451 | case CRM_Contact_BAO_Query::MODE_CONTRIBUTE: | |
452 | return 'Contribute'; | |
453 | ||
454 | case CRM_Contact_BAO_Query::MODE_MEMBER: | |
455 | return 'Membership'; | |
456 | ||
457 | case CRM_Contact_BAO_Query::MODE_EVENT: | |
458 | return 'Event'; | |
459 | ||
460 | case CRM_Contact_BAO_Query::MODE_PLEDGE: | |
461 | return 'Pledge'; | |
462 | ||
463 | case CRM_Contact_BAO_Query::MODE_CASE: | |
464 | return 'Case'; | |
465 | ||
466 | case CRM_Contact_BAO_Query::MODE_GRANT: | |
467 | return 'Grant'; | |
468 | ||
469 | case CRM_Contact_BAO_Query::MODE_ACTIVITY: | |
470 | return 'Activity'; | |
471 | ||
472 | default: | |
473 | return $this->controller->get('entity') ?? $this->getComponentName(); | |
474 | } | |
475 | } | |
476 | ||
477 | /** | |
478 | * Get the entity short name for a given export. | |
479 | * | |
480 | * @return string | |
481 | */ | |
482 | protected function getEntityShortName(): string { | |
483 | switch ($this->getQueryMode()) { | |
484 | case CRM_Contact_BAO_Query::MODE_CONTRIBUTE: | |
485 | return 'Contribute'; | |
486 | ||
487 | case CRM_Contact_BAO_Query::MODE_MEMBER: | |
488 | return 'Member'; | |
489 | ||
490 | case CRM_Contact_BAO_Query::MODE_EVENT: | |
491 | return 'Event'; | |
492 | ||
493 | case CRM_Contact_BAO_Query::MODE_PLEDGE: | |
494 | return 'Pledge'; | |
495 | ||
496 | case CRM_Contact_BAO_Query::MODE_CASE: | |
497 | return 'Case'; | |
498 | ||
499 | case CRM_Contact_BAO_Query::MODE_GRANT: | |
500 | return 'Grant'; | |
501 | ||
502 | case CRM_Contact_BAO_Query::MODE_ACTIVITY: | |
503 | return 'Activity'; | |
504 | ||
505 | default: | |
506 | return $this->getComponentName(); | |
507 | } | |
508 | } | |
509 | ||
6a488035 | 510 | } |