preventAjaxSubmit();
//special case for custom search, directly give option to download csv file
$customSearchID = $this->get('customSearchID');
if ($customSearchID) {
CRM_Export_BAO_Export::exportCustom($this->get('customSearchClass'),
$this->get('formValues'),
$this->get(CRM_Utils_Sort::SORT_ORDER)
);
}
$this->_selectAll = FALSE;
$this->_exportMode = self::CONTACT_EXPORT;
$this->_componentIds = [];
$this->_componentClause = NULL;
// FIXME: This should use a modified version of CRM_Contact_Form_Search::getModeValue but it doesn't have all the contexts
// FIXME: Or better still, use CRM_Core_DAO_AllCoreTables::getBriefName($daoName) to get the $entityShortName
$entityShortname = $this->getEntityShortName();
if (!in_array($entityShortname, ['Contact', 'Contribute', 'Member', 'Event', 'Pledge', 'Case', 'Grant', 'Activity'], TRUE)) {
// This is never reached - the exception here is just to clarify that entityShortName MUST be one of the above
// to save future refactorers & reviewers from asking that question.
throw new CRM_Core_Exception('Unreachable code');
}
$this->_exportMode = constant('CRM_Export_Form_Select::' . strtoupper($entityShortname) . '_EXPORT');
$this::$entityShortname = strtolower($entityShortname);
$values = $this->getSearchFormValues();
$count = 0;
$this->_matchingContacts = FALSE;
if (CRM_Utils_Array::value('radio_ts', $values) == 'ts_sel') {
foreach ($values as $key => $value) {
if (strstr($key, 'mark_x')) {
$count++;
}
if ($count > 2) {
$this->_matchingContacts = TRUE;
break;
}
}
}
$this->callPreProcessing();
// $component is used on CRM/Export/Form/Select.tpl to display extra information for contact export
($this->_exportMode == self::CONTACT_EXPORT) ? $component = FALSE : $component = TRUE;
$this->assign('component', $component);
$this->assign('isShowMergeOptions', $this->isShowContactMergeOptions());
if ($this->_componentTable) {
$query = "
SELECT count(*)
FROM {$this->_componentTable}
";
$totalSelectedRecords = CRM_Core_DAO::singleValueQuery($query);
}
else {
$totalSelectedRecords = count($this->_componentIds);
}
$this->assign('totalSelectedRecords', $totalSelectedRecords);
// all records actions = save a search
if (($values['radio_ts'] == 'ts_all') || ($this->_task == CRM_Contact_Task::SAVE_SEARCH)) {
$this->_selectAll = TRUE;
$rowCount = $this->get('rowCount');
if ($rowCount > 2) {
$this->_matchingContacts = TRUE;
}
$this->assign('totalSelectedRecords', $rowCount);
}
$this->assign('matchingContacts', $this->_matchingContacts);
$this->set('componentIds', $this->_componentIds);
$this->set('selectAll', $this->_selectAll);
$this->set('exportMode', $this->_exportMode);
$this->set('componentClause', $this->_componentClause);
$this->set('componentTable', $this->getTableName());
}
/**
* Get the name of the table for the relevant entity.
*/
public function getTableName() {
throw new CRM_Core_Exception('should be over-riden');
}
/**
* Build the form object.
*
* @return void
*/
public function buildQuickForm() {
//export option
$exportOptions = $exportOptionsJS = $mergeOptions = $mergeOptionsJS = $postalMailing = [];
$exportOptions[self::EXPORT_ALL] = ts('Export PRIMARY fields');
$exportOptions[self::EXPORT_SELECTED] = ts('Select fields for export');
$mergeOptions[self::EXPORT_MERGE_DO_NOT_MERGE] = ts('Do not merge');
$mergeOptions[self::EXPORT_MERGE_SAME_ADDRESS] = ts('Merge All Contacts with the Same Address');
$mergeOptions[self::EXPORT_MERGE_HOUSEHOLD] = ts('Merge Household Members into their Households');
foreach (array_keys($exportOptions) as $key) {
$exportOptionsJS[$key] = ['onClick' => 'showMappingOption( );'];
}
foreach (array_keys($mergeOptions) as $key) {
$mergeOptionsJS[$key] = ['onclick' => 'showGreetingOptions( );'];
}
$this->addRadio('exportOption', ts('Export Type'), $exportOptions, [], '
', FALSE, $exportOptionsJS);
$postalMailing[] = $this->createElement('advcheckbox',
'postal_mailing_export',
NULL,
NULL
);
if ($this->_matchingContacts) {
$this->_greetingOptions = self::getGreetingOptions();
foreach ($this->_greetingOptions as $key => $value) {
$fieldLabel = ts('%1 (when merging contacts)', [1 => ucwords(str_replace('_', ' ', $key))]);
$this->addElement('select', $key, $fieldLabel,
$value, ['onchange' => "showOther(this);"]
);
$this->addElement('text', "{$key}_other", '');
}
}
if ($this->_exportMode == self::CONTACT_EXPORT) {
$this->addRadio('mergeOption', ts('Merge Options'), $mergeOptions, [], '
', FALSE, $mergeOptionsJS);
$this->addGroup($postalMailing, 'postal_mailing_export', ts('Postal Mailing Export'), '
');
$this->addElement('select', 'additional_group', ts('Additional Group for Export'),
['' => ts('- select group -')] + CRM_Core_PseudoConstant::nestedGroup(),
['class' => 'crm-select2 huge']
);
}
$this->buildMapping();
$this->setDefaults([
'exportOption' => self::EXPORT_ALL,
'mergeOption' => self::EXPORT_MERGE_DO_NOT_MERGE,
]);
$this->addButtons([
[
'type' => 'next',
'name' => ts('Continue'),
'spacing' => ' ',
'isDefault' => TRUE,
],
[
'type' => 'cancel',
'name' => ts('Cancel'),
],
]);
$this->addFormRule(['CRM_Export_Form_Select', 'formRule'], $this);
}
/**
* Validation.
*
* @param array $params
* (ref.) an assoc array of name/value pairs.
*
* @param $files
* @param $self
*
* @return bool|array
* mixed true or array of errors
*/
public static function formRule($params, $files, $self) {
$errors = [];
if (CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_SAME_ADDRESS &&
$self->_matchingContacts
) {
$greetings = [
'postal_greeting' => 'postal_greeting_other',
'addressee' => 'addressee_other',
];
foreach ($greetings as $key => $value) {
$otherOption = $params[$key] ?? NULL;
if ((CRM_Utils_Array::value($otherOption, $self->_greetingOptions[$key]) == ts('Other')) && empty($params[$value])) {
$label = ucwords(str_replace('_', ' ', $key));
$errors[$value] = ts('Please enter a value for %1 (when merging contacts), or select a pre-configured option from the list.', [1 => $label]);
}
}
}
return empty($errors) ? TRUE : $errors;
}
/**
* Process the uploaded file.
*
* @throws \CRM_Core_Exception
*/
public function postProcess() {
$params = $this->controller->exportValues($this->_name);
$exportOption = $params['exportOption'];
$mergeSameAddress = CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_SAME_ADDRESS ? 1 : 0;
$mergeSameHousehold = CRM_Utils_Array::value('mergeOption', $params) == self::EXPORT_MERGE_HOUSEHOLD ? 1 : 0;
$this->set('mergeSameAddress', $mergeSameAddress);
$this->set('mergeSameHousehold', $mergeSameHousehold);
// instead of increasing the number of arguments to exportComponents function, we
// will send $exportParams as another argument, which is an array and suppose to contain
// all submitted options or any other argument
$exportParams = $params;
$mappingId = $params['mapping'] ?? NULL;
if ($mappingId) {
$this->set('mappingId', $mappingId);
}
else {
$this->set('mappingId', NULL);
}
if ($exportOption == self::EXPORT_ALL) {
CRM_Export_BAO_Export::exportComponents($this->_selectAll,
$this->_componentIds,
(array) $this->get('queryParams'),
$this->get(CRM_Utils_Sort::SORT_ORDER),
NULL,
$this->get('returnProperties'),
$this->_exportMode,
$this->_componentClause,
$this->_componentTable,
$mergeSameAddress,
$mergeSameHousehold,
$exportParams,
$this->get('queryOperator')
);
}
//reset map page
$this->controller->resetPage('Map');
}
/**
* Return a descriptive name for the page, used in wizard header
*
* @return string
*/
public function getTitle() {
return ts('Export Options');
}
/**
* Build mapping form element.
*/
public function buildMapping() {
switch ($this->_exportMode) {
case CRM_Export_Form_Select::CONTACT_EXPORT:
$exportType = 'Export Contact';
break;
case CRM_Export_Form_Select::CONTRIBUTE_EXPORT:
$exportType = 'Export Contribution';
break;
case CRM_Export_Form_Select::MEMBER_EXPORT:
$exportType = 'Export Membership';
break;
case CRM_Export_Form_Select::EVENT_EXPORT:
$exportType = 'Export Participant';
break;
case CRM_Export_Form_Select::PLEDGE_EXPORT:
$exportType = 'Export Pledge';
break;
case CRM_Export_Form_Select::CASE_EXPORT:
$exportType = 'Export Case';
break;
case CRM_Export_Form_Select::GRANT_EXPORT:
$exportType = 'Export Grant';
break;
case CRM_Export_Form_Select::ACTIVITY_EXPORT:
$exportType = 'Export Activity';
break;
}
$this->set('mappingTypeId', CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', $exportType));
$mappings = CRM_Core_BAO_Mapping::getMappings($exportType, TRUE);
if (!empty($mappings)) {
$this->add('select2', 'mapping', ts('Use Saved Field Mapping'), $mappings, FALSE, ['placeholder' => ts('- select -')]);
}
}
/**
* @return array
*/
public static function getGreetingOptions() {
$options = [];
$greetings = [
'postal_greeting' => 'postal_greeting_other',
'addressee' => 'addressee_other',
];
foreach ($greetings as $key => $value) {
$params = [];
$optionGroupId = CRM_Core_DAO::getFieldValue('CRM_Core_DAO_OptionGroup', $key, 'id', 'name');
CRM_Core_DAO::commonRetrieveAll('CRM_Core_DAO_OptionValue', 'option_group_id', $optionGroupId,
$params, ['label', 'filter']
);
$greetingCount = 1;
$options[$key] = ["$greetingCount" => ts('List of names')];
foreach ($params as $id => $field) {
if (CRM_Utils_Array::value('filter', $field) == 4) {
$options[$key][++$greetingCount] = $field['label'];
}
}
$options[$key][++$greetingCount] = ts('Other');
}
return $options;
}
/**
* Get the query mode (eg. CRM_Contact_BAO_Query::MODE_CASE)
*
* @return int
*/
public function getQueryMode() {
return (int) ($this->queryMode ?: $this->controller->get('component_mode'));
}
/**
* Call the pre-processing function.
*/
protected function callPreProcessing(): void {
throw new CRM_Core_Exception('This must be over-ridden');
}
/**
* Assign the title of the task to the tpl.
*/
protected function isShowContactMergeOptions() {
throw new CRM_Core_Exception('This must be over-ridden');
}
/**
* Get the name of the component.
*
* @return array
*/
protected function getComponentName(): string {
// CRM_Export_Controller_Standalone has this method
if (method_exists($this->controller, 'getComponent')) {
return $this->controller->getComponent();
}
// For others, just guess based on the name of the controller
$formName = CRM_Utils_System::getClassName($this->controller->getStateMachine());
$componentName = explode('_', $formName);
return $componentName[1];
}
/**
* Get the DAO name for the given export.
*
* @return string
*/
protected function getDAOName(): string {
switch ($this->getQueryMode()) {
case CRM_Contact_BAO_Query::MODE_CONTRIBUTE:
return 'Contribute';
case CRM_Contact_BAO_Query::MODE_MEMBER:
return 'Membership';
case CRM_Contact_BAO_Query::MODE_EVENT:
return 'Event';
case CRM_Contact_BAO_Query::MODE_PLEDGE:
return 'Pledge';
case CRM_Contact_BAO_Query::MODE_CASE:
return 'Case';
case CRM_Contact_BAO_Query::MODE_GRANT:
return 'Grant';
case CRM_Contact_BAO_Query::MODE_ACTIVITY:
return 'Activity';
default:
return $this->controller->get('entity') ?? $this->getComponentName();
}
}
/**
* Get the entity short name for a given export.
*
* @return string
*/
protected function getEntityShortName(): string {
switch ($this->getQueryMode()) {
case CRM_Contact_BAO_Query::MODE_CONTRIBUTE:
return 'Contribute';
case CRM_Contact_BAO_Query::MODE_MEMBER:
return 'Member';
case CRM_Contact_BAO_Query::MODE_EVENT:
return 'Event';
case CRM_Contact_BAO_Query::MODE_PLEDGE:
return 'Pledge';
case CRM_Contact_BAO_Query::MODE_CASE:
return 'Case';
case CRM_Contact_BAO_Query::MODE_GRANT:
return 'Grant';
case CRM_Contact_BAO_Query::MODE_ACTIVITY:
return 'Activity';
default:
return $this->getComponentName();
}
}
}