$this->assign('groupAdditions', $this->getUserJob()['metadata']['summary_info']['groups']);
$this->assign('tagAdditions', $this->getUserJob()['metadata']['summary_info']['tags']);
- $this->assign('totalRowCount', $this->getRowCount());
- $this->assign('validRowCount', $this->getRowCount(CRM_Import_Parser::VALID) + $this->getRowCount(CRM_Import_Parser::UNPARSED_ADDRESS_WARNING));
- $this->assign('invalidRowCount', $this->getRowCount(CRM_Import_Parser::ERROR));
- $this->assign('duplicateRowCount', $this->getRowCount(CRM_Import_Parser::DUPLICATE));
- $this->assign('unMatchCount', $this->getRowCount(CRM_Import_Parser::NO_MATCH));
- $this->assign('unparsedAddressCount', $this->getRowCount(CRM_Import_Parser::UNPARSED_ADDRESS_WARNING));
- $this->assign('downloadDuplicateRecordsUrl', $this->getDownloadURL(CRM_Import_Parser::DUPLICATE));
- $this->assign('downloadErrorRecordsUrl', $this->getDownloadURL(CRM_Import_Parser::ERROR));
- $this->assign('downloadMismatchRecordsUrl', $this->getDownloadURL(CRM_Import_Parser::NO_MATCH));
- $this->assign('downloadAddressRecordsUrl', $this->getDownloadURL(CRM_Import_Parser::UNPARSED_ADDRESS_WARNING));
+ $this->assignOutputURLs();
$session = CRM_Core_Session::singleton();
$session->pushUserContext(CRM_Utils_System::url('civicrm/import/contact', 'reset=1'));
}
*/
class CRM_Member_Import_Form_MapField extends CRM_Import_Form_MapField {
- /**
- * Set variables up before form is built.
- *
- * @return void
- */
- public function preProcess() {
- $this->_mapperFields = $this->get('fields');
- asort($this->_mapperFields);
- parent::preProcess();
-
- $skipColumnHeader = $this->controller->exportValue('DataSource', 'skipColumnHeader');
- $this->_onDuplicate = $this->get('onDuplicate', $onDuplicate ?? "");
-
- $highlightedFields = [];
- if ($this->getSubmittedValue('skipColumnHeader')) {
- $this->assign('skipColumnHeader', $skipColumnHeader);
- $this->assign('rowDisplayCount', 3);
- }
- else {
- $this->assign('rowDisplayCount', 2);
- }
-
- //CRM-2219 removing other required fields since for updation only
- //membership id is required.
- if ($this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_UPDATE) {
- $remove = array('membership_contact_id', 'email', 'first_name', 'last_name', 'external_identifier');
- foreach ($remove as $value) {
- unset($this->_mapperFields[$value]);
- }
- $highlightedFieldsArray = array('membership_id', 'membership_start_date', 'membership_type_id');
- foreach ($highlightedFieldsArray as $name) {
- $highlightedFields[] = $name;
- }
- }
- elseif ($this->_onDuplicate == CRM_Import_Parser::DUPLICATE_SKIP) {
- unset($this->_mapperFields['membership_id']);
- $highlightedFieldsArray = array(
- 'membership_contact_id',
- 'email',
- 'external_identifier',
- 'membership_start_date',
- 'membership_type_id',
- );
- foreach ($highlightedFieldsArray as $name) {
- $highlightedFields[] = $name;
- }
- }
-
- // modify field title
- $this->_mapperFields['status_id'] = ts('Membership Status');
- $this->_mapperFields['membership_type_id'] = ts('Membership Type');
- $this->assign('highlightedFields', $highlightedFields);
- }
-
/**
* Build the form object.
*
* @return void
*/
public function buildQuickForm() {
- //to save the current mappings
- if (!$this->get('savedMapping')) {
- $saveDetailsName = ts('Save this field mapping');
- $this->applyFilter('saveMappingName', 'trim');
- $this->add('text', 'saveMappingName', ts('Name'));
- $this->add('text', 'saveMappingDesc', ts('Description'));
- }
- else {
- $savedMapping = $this->get('savedMapping');
-
- [$mappingName] = CRM_Core_BAO_Mapping::getMappingFields($savedMapping);
-
- $mappingName = $mappingName[1];
-
- //mapping is to be loaded from database
-
- $this->set('loadedMapping', $savedMapping);
-
- $getMappingName = new CRM_Core_DAO_Mapping();
- $getMappingName->id = $savedMapping;
- $getMappingName->mapping_type = 'Import Memberships';
- $getMappingName->find();
- while ($getMappingName->fetch()) {
- $mapperName = $getMappingName->name;
- }
-
- $this->assign('savedMappingName', $mapperName);
-
- $this->add('hidden', 'mappingId', $savedMapping);
-
- $this->addElement('checkbox', 'updateMapping', ts('Update this field mapping'), NULL);
- $saveDetailsName = ts('Save as a new field mapping');
- $this->add('text', 'saveMappingName', ts('Name'));
- $this->add('text', 'saveMappingDesc', ts('Description'));
- }
-
- $this->addElement('checkbox', 'saveMapping', $saveDetailsName, NULL, array('onclick' => "showSaveDetails(this)"));
-
+ $this->buildSavedMappingFields($this->getSubmittedValue('savedMapping'));
$this->addFormRule(array('CRM_Member_Import_Form_MapField', 'formRule'), $this);
//-------- end of saved mapping stuff ---------
$defaults = [];
$mapperKeys = array_keys($this->_mapperFields);
- $hasHeaders = !empty($this->_columnHeaders);
+ $columnHeaders = $this->getColumnHeaders();
+ $hasHeaders = $this->getSubmittedValue('skipColumnHeader');
$headerPatterns = $this->getHeaderPatterns();
$dataPatterns = $this->getDataPatterns();
}
$this->_location_types = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
$sel1 = $this->_mapperFields;
- if (!$this->get('onDuplicate')) {
+ if (!$this->getSubmittedValue('onDuplicate')) {
unset($sel1['id']);
unset($sel1['membership_id']);
}
//used to warn for mismatch column count or mismatch mapping
$warning = 0;
- for ($i = 0; $i < $this->_columnCount; $i++) {
+ foreach ($columnHeaders as $i => $columnHeader) {
$sel = &$this->addElement('hierselect', "mapper[$i]", ts('Mapper for Field %1', array(1 => $i)), NULL);
$jsSet = FALSE;
if ($this->get('savedMapping')) {
$js .= "swapOptions($formName, 'mapper[$i]', 0, 3, 'hs_mapper_" . $i . "_');\n";
if ($hasHeaders) {
- $defaults["mapper[$i]"] = array($this->defaultFromHeader($this->_columnHeaders[$i], $headerPatterns));
+ $defaults["mapper[$i]"] = array($this->defaultFromHeader($columnHeader, $headerPatterns));
}
else {
$defaults["mapper[$i]"] = array($this->defaultFromData($dataPatterns, $i));
if ($this->getSubmittedValue('skipColumnHeader')) {
// Infer the default from the skipped headers if we have them
$defaults["mapper[$i]"] = array(
- $this->defaultFromHeader($this->_columnHeaders[$i],
+ $this->defaultFromHeader($columnHeader,
$headerPatterns
),
// $defaultLocationType->id
'used' => 'Unsupervised',
'contact_type' => $self->getContactType(),
);
- list($ruleFields, $threshold) = CRM_Dedupe_BAO_DedupeRuleGroup::dedupeRuleFieldsWeight($params);
- $weightSum = 0;
- foreach ($importKeys as $key => $val) {
- if (array_key_exists($val, $ruleFields)) {
- $weightSum += $ruleFields[$val];
- }
- }
- $fieldMessage = '';
- foreach ($ruleFields as $field => $weight) {
- $fieldMessage .= ' ' . $field . '(weight ' . $weight . ')';
+ [$ruleFields, $threshold] = CRM_Dedupe_BAO_DedupeRuleGroup::dedupeRuleFieldsWeight($params);
+ $weightSum = 0;
+ foreach ($importKeys as $key => $val) {
+ if (array_key_exists($val, $ruleFields)) {
+ $weightSum += $ruleFields[$val];
}
+ }
+ $fieldMessage = '';
+ foreach ($ruleFields as $field => $weight) {
+ $fieldMessage .= ' ' . $field . '(weight ' . $weight . ')';
+ }
foreach ($requiredFields as $field => $title) {
if (!in_array($field, $importKeys)) {
if ($field == 'membership_contact_id') {
if ((($weightSum >= $threshold || in_array('external_identifier', $importKeys)) &&
- $self->_onDuplicate != CRM_Import_Parser::DUPLICATE_UPDATE
+ $self->getSubmittedValue('onDuplicate') != CRM_Import_Parser::DUPLICATE_UPDATE
) ||
in_array('membership_id', $importKeys)
) {
}
/**
- * Process the mapped fields and map it into the uploaded file
- * preview the file and extract some summary statistics
+ * Get the mapping name per the civicrm_mapping_field.type_id option group.
*
- * @return void
+ * @return string
*/
- public function postProcess() {
- $params = $this->controller->exportValues('MapField');
- $this->updateUserJobMetadata('submitted_values', $this->getSubmittedValues());
- $mapper = [];
- $mapperKeys = $this->controller->exportValue($this->_name, 'mapper');
- $mapperKeysMain = [];
-
- for ($i = 0; $i < $this->_columnCount; $i++) {
- $mapper[$i] = $this->_mapperFields[$mapperKeys[$i][0]];
- $mapperKeysMain[$i] = $mapperKeys[$i][0];
- }
-
- $this->set('mapper', $mapper);
-
- // store mapping Id to display it in the preview page
- if (!empty($params['mappingId'])) {
- $this->set('loadMappingId', $params['mappingId']);
- }
- //Updating Mapping Records
- if (!empty($params['updateMapping'])) {
- for ($i = 0; $i < $this->_columnCount; $i++) {
- $this->saveMappingField($params['mappingId'], $i, TRUE);
- }
- }
-
- //Saving Mapping Details and Records
- if (!empty($params['saveMapping'])) {
- $mappingParams = array(
- 'name' => $params['saveMappingName'],
- 'description' => $params['saveMappingDesc'],
- 'mapping_type_id' => CRM_Core_PseudoConstant::getKey('CRM_Core_BAO_Mapping', 'mapping_type_id', 'Import Membership'),
- );
- $saveMapping = CRM_Core_BAO_Mapping::add($mappingParams);
-
- for ($i = 0; $i < $this->_columnCount; $i++) {
- $this->saveMappingField($saveMapping->id, $i);
- }
- $this->set('savedMapping', $saveMapping->id);
- }
-
- $parser = new CRM_Member_Import_Parser_Membership($mapperKeysMain);
- $parser->setUserJobID($this->getUserJobID());
- $parser->run($this->getSubmittedValue('uploadFile'), $this->getSubmittedValue('fieldSeparator'), $mapper, $this->getSubmittedValue('skipColumnHeader'),
- CRM_Import_Parser::MODE_PREVIEW
- );
- // add all the necessary variables to the form
- $parser->set($this);
+ public function getMappingTypeName(): string {
+ return 'Import Membership';
}
/**
return $this->parser;
}
+ /**
+ * Get the fields to be highlighted in the UI.
+ *
+ * @return array
+ * @throws \CRM_Core_Exception
+ */
+ protected function getHighlightedFields(): array {
+ $highlightedFields = [];
+ //CRM-2219 removing other required fields since for updation only
+ //membership id is required.
+ if ($this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_UPDATE) {
+ $remove = [
+ 'membership_contact_id',
+ 'email',
+ 'first_name',
+ 'last_name',
+ 'external_identifier',
+ ];
+ foreach ($remove as $value) {
+ unset($this->_mapperFields[$value]);
+ }
+ $highlightedFieldsArray = [
+ 'membership_id',
+ 'membership_start_date',
+ 'membership_type_id',
+ ];
+ foreach ($highlightedFieldsArray as $name) {
+ $highlightedFields[] = $name;
+ }
+ }
+ elseif ($this->getSubmittedValue('onDuplicate') == CRM_Import_Parser::DUPLICATE_SKIP) {
+ unset($this->_mapperFields['membership_id']);
+ $highlightedFieldsArray = [
+ 'membership_contact_id',
+ 'email',
+ 'external_identifier',
+ 'membership_start_date',
+ 'membership_type_id',
+ ];
+ foreach ($highlightedFieldsArray as $name) {
+ $highlightedFields[] = $name;
+ }
+ }
+ return $highlightedFields;
+ }
+
}
*/
public function preProcess() {
parent::preProcess();
- $invalidRowCount = $this->get('invalidRowCount');
- if ($invalidRowCount) {
- $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Member_Import_Parser_Membership';
- $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
- }
$this->setStatusUrl();
}
- /**
- * Process the mapped fields and map it into the uploaded file
- * preview the file and extract some summary statistics
- *
- * @return void
- */
- public function postProcess() {
- $fileName = $this->getSubmittedValue('uploadFile');
- $invalidRowCount = $this->get('invalidRowCount');
- $onDuplicate = $this->get('onDuplicate');
-
- $mapper = $this->controller->exportValue('MapField', 'mapper');
-
- $parser = $this->getParser();
-
- $mapFields = $this->get('fields');
-
- foreach ($mapper as $key => $value) {
- $header = [];
- if (isset($mapFields[$mapper[$key][0]])) {
- $header[] = $mapFields[$mapper[$key][0]];
- }
- $mapperFields[] = implode(' - ', $header);
- }
- $parser->run($this->getSubmittedValue('uploadFile'), $this->getSubmittedValue('fieldSeparator'),
- $mapperFields,
- NULL,
- CRM_Import_Parser::MODE_IMPORT,
- NULL,
- NULL,
- $this->get('statusID')
- );
-
- // add all the necessary variables to the form
- $parser->set($this, CRM_Import_Parser::MODE_IMPORT);
-
- // check if there is any error occurred
- $errorStack = CRM_Core_Error::singleton();
- $errors = $errorStack->getErrors();
- $errorMessage = [];
-
- if (is_array($errors)) {
- foreach ($errors as $key => $value) {
- $errorMessage[] = $value['message'];
- }
-
- $errorFile = $fileName['name'] . '.error.log';
-
- if ($fd = fopen($errorFile, 'w')) {
- fwrite($fd, implode('\n', $errorMessage));
- }
- fclose($fd);
-
- $this->set('errorFile', $errorFile);
- $urlParams = 'type=' . CRM_Import_Parser::ERROR . '&parser=CRM_Member_Import_Parser_Membership';
- $this->set('downloadErrorRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
- }
- }
-
/**
* @return \CRM_Member_Import_Parser_Membership
*/
*/
class CRM_Member_Import_Form_Summary extends CRM_Import_Form_Summary {
- /**
- * Set variables up before form is built.
- *
- * @return void
- */
- public function preProcess() {
- // set the error message path to display
- $this->assign('errorFile', $this->get('errorFile'));
-
- $totalRowCount = $this->get('totalRowCount');
- $this->set('totalRowCount', $totalRowCount);
-
- $invalidRowCount = $this->get('invalidRowCount');
- $duplicateRowCount = $this->get('duplicateRowCount');
- $onDuplicate = $this->get('onDuplicate');
-
- if ($duplicateRowCount > 0) {
- $urlParams = 'type=' . CRM_Import_Parser::DUPLICATE . '&parser=CRM_Member_Import_Parser_Membership';
- $this->set('downloadDuplicateRecordsUrl', CRM_Utils_System::url('civicrm/export', $urlParams));
- }
- else {
- $duplicateRowCount = 0;
- $this->set('duplicateRowCount', $duplicateRowCount);
- }
-
- $this->assign('dupeError', FALSE);
-
- if ($onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE) {
- $dupeActionString = ts('These records have been updated with the imported data.');
- }
- elseif ($onDuplicate == CRM_Import_Parser::DUPLICATE_FILL) {
- $dupeActionString = ts('These records have been filled in with the imported data.');
- }
- else {
- /* Skip by default */
-
- $dupeActionString = ts('These records have not been imported.');
-
- $this->assign('dupeError', TRUE);
-
- /* only subtract dupes from successful import if we're skipping */
-
- $this->set('validRowCount', $totalRowCount - $invalidRowCount -
- $duplicateRowCount
- );
- }
- $this->assign('dupeActionString', $dupeActionString);
-
- $properties = [
- 'totalRowCount',
- 'validRowCount',
- 'invalidRowCount',
- 'downloadErrorRecordsUrl',
- 'duplicateRowCount',
- 'downloadDuplicateRecordsUrl',
- 'groupAdditions',
- ];
- foreach ($properties as $property) {
- $this->assign($property, $this->get($property));
- }
- }
-
}
* @param int $contactType
* @param int $onDuplicate
* @param int $statusID
- * @param int $totalRowCount
*
* @return mixed
* @throws Exception
$this->_errors = [];
$this->_warnings = [];
-
- if ($mode == self::MODE_MAPFIELD) {
- $this->_rows = [];
- }
- else {
- $this->_activeFieldCount = count($this->_activeFields);
- }
if ($statusID) {
$this->progressImport($statusID);
$startTimestamp = $currTimestamp = $prevTimestamp = CRM_Utils_Time::time();
$dataSource->setStatuses(['new']);
while ($row = $dataSource->getRow()) {
$values = array_values($row);
- $this->_lineCount++;
-
- $this->_totalCount++;
-
- if ($mode == self::MODE_MAPFIELD) {
- $returnCode = CRM_Import_Parser::VALID;
- }
- elseif ($mode == self::MODE_PREVIEW) {
- $returnCode = $this->preview($values);
- }
- elseif ($mode == self::MODE_SUMMARY) {
- $returnCode = $this->summary($values);
- }
- elseif ($mode == self::MODE_IMPORT) {
- $returnCode = $this->import($this->getSubmittedValue('onDuplicate'), $values);
+ if ($mode == self::MODE_IMPORT) {
+ $this->import($this->getSubmittedValue('onDuplicate'), $values);
if ($statusID && (($this->_lineCount % 50) == 0)) {
$prevTimestamp = $this->progressImport($statusID, FALSE, $startTimestamp, $prevTimestamp, $totalRowCount);
}
}
- else {
- $returnCode = self::ERROR;
- }
-
- // note that a line could be valid but still produce a warning
- if ($returnCode & self::VALID) {
- $this->_validCount++;
- if ($mode == self::MODE_MAPFIELD) {
- $this->_rows[] = $values;
- $this->_activeFieldCount = max($this->_activeFieldCount, count($values));
- }
- }
-
- if ($returnCode & self::ERROR) {
- $this->_invalidRowCount++;
- $recordNumber = $this->_lineCount;
- array_unshift($values, $recordNumber);
- $this->_errors[] = $values;
- }
-
- if ($returnCode & self::DUPLICATE) {
- $this->_duplicateCount++;
- $recordNumber = $this->_lineCount;
- array_unshift($values, $recordNumber);
- $this->_duplicates[] = $values;
- if ($this->getSubmittedValue('onDuplicate') != self::DUPLICATE_SKIP) {
- $this->_validCount++;
- }
- }
- }
-
- if ($mode == self::MODE_PREVIEW || $mode == self::MODE_IMPORT) {
- $customHeaders = $mapper;
-
- $customfields = CRM_Core_BAO_CustomField::getFields('Membership');
- foreach ($customHeaders as $key => $value) {
- if ($id = CRM_Core_BAO_CustomField::getKeyID($value)) {
- $customHeaders[$key] = $customfields[$id][0];
- }
- }
- if ($this->_invalidRowCount) {
- // removed view url for invlaid contacts
- $headers = array_merge([
- ts('Line Number'),
- ts('Reason'),
- ], $customHeaders);
- $this->_errorFileName = self::errorFileName(self::ERROR);
-
- self::exportCSV($this->_errorFileName, $headers, $this->_errors);
- }
- if ($this->_duplicateCount) {
- $headers = array_merge([
- ts('Line Number'),
- ts('View Membership URL'),
- ], $customHeaders);
-
- $this->_duplicateFileName = self::errorFileName(self::DUPLICATE);
- self::exportCSV($this->_duplicateFileName, $headers, $this->_duplicates);
- }
}
}
return $params;
}
- /**
- * Get the row from the csv mapped to our parameters.
- *
- * @param array $values
- *
- * @return array
- * @throws \API_Exception
- */
- public function getMappedRow(array $values): array {
- $params = [];
- foreach ($this->getFieldMappings() as $i => $mappedField) {
- if ($mappedField['name']) {
- $params[$this->getFieldMetadata($mappedField['name'])['name']] = $this->getTransformedFieldValue($mappedField['name'], $values[$i]);
- }
- }
- return $params;
- }
-
/**
* @param string $name
* @param $title
*/
public function set($store, $mode = self::MODE_SUMMARY) {
$store->set('lineCount', $this->_lineCount);
-
- $store->set('dataPatterns', $this->getDataPatterns());
- $store->set('columnCount', $this->_activeFieldCount);
-
- $store->set('totalRowCount', $this->_totalCount);
$store->set('validRowCount', $this->_validCount);
$store->set('invalidRowCount', $this->_invalidRowCount);
- switch ($this->_contactType) {
- case 'Individual':
- $store->set('contactType', CRM_Import_Parser::CONTACT_INDIVIDUAL);
- break;
-
- case 'Household':
- $store->set('contactType', CRM_Import_Parser::CONTACT_HOUSEHOLD);
- break;
-
- case 'Organization':
- $store->set('contactType', CRM_Import_Parser::CONTACT_ORGANIZATION);
- }
-
if ($this->_invalidRowCount) {
$store->set('errorsFileName', $this->_errorFileName);
}
- if (isset($this->_rows) && !empty($this->_rows)) {
- $store->set('dataValues', $this->_rows);
- }
if ($mode == self::MODE_IMPORT) {
$store->set('duplicateRowCount', $this->_duplicateCount);
}
/**
- * Handle the values in preview mode.
- *
- * @param array $values
- * The array of values belonging to this line.
- *
- * @return bool
- * the result of this processing
- */
- public function preview(&$values) {
- return $this->summary($values);
- }
-
- /**
- * Handle the values in summary mode.
+ * Validate the values.
*
* @param array $values
* The array of values belonging to this line.
* @return bool
* the result of this processing
*/
- public function summary(&$values) {
+ public function validateValues($values) {
$params = $this->getMappedRow($values);
+ $errors = [];
+ foreach ($params as $key => $value) {
+ $errors = array_merge($this->getInvalidValues($value, $key), $errors);
+ }
if (empty($params['membership_type_id'])) {
- array_unshift($values, ts('Missing required fields'));
- return CRM_Import_Parser::ERROR;
+ $errors[] = ts('Missing required fields');
+ return NULL;
}
- $errorMessage = NULL;
//To check whether start date or join date is provided
if (empty($params['start_date']) && empty($params['join_date'])) {
- $errorMessage = 'Membership Start Date is required to create a memberships.';
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
- }
-
- //for date-Formats
- $session = CRM_Core_Session::singleton();
- $dateType = $session->get('dateTypes');
- foreach ($params as $key => $val) {
-
- if ($val) {
- switch ($key) {
- case 'join_date':
- if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
- if (!CRM_Utils_Rule::date($params[$key])) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Member Since', $errorMessage);
- }
- }
- else {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Member Since', $errorMessage);
- }
- break;
-
- case 'start_date':
- if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
- if (!CRM_Utils_Rule::date($params[$key])) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
- }
- }
- else {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Start Date', $errorMessage);
- }
- break;
-
- case 'end_date':
- if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
- if (!CRM_Utils_Rule::date($params[$key])) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('End date', $errorMessage);
- }
- }
- else {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('End date', $errorMessage);
- }
- break;
-
- case 'status_override_end_date':
- if (CRM_Utils_Date::convertToDefaultDate($params, $dateType, $key)) {
- if (!CRM_Utils_Rule::date($params[$key])) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Status Override End Date', $errorMessage);
- }
- }
- else {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Status Override End Date', $errorMessage);
- }
- break;
-
- case 'membership_type_id':
- // @todo - squish into membership status - can use same lines here too.
- $membershipTypes = CRM_Member_PseudoConstant::membershipType();
- if (!CRM_Utils_Array::crmInArray($val, $membershipTypes) &&
- !array_key_exists($val, $membershipTypes)
- ) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Membership Type', $errorMessage);
- }
- break;
-
- case 'status_id':
- if (!empty($val) && !$this->parsePseudoConstantField($val, $this->fieldMetadata[$key])) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Membership Status', $errorMessage);
- }
- break;
-
- case 'email':
- if (!CRM_Utils_Rule::email($val)) {
- CRM_Contact_Import_Parser_Contact::addToErrorMsg('Email Address', $errorMessage);
- }
- }
- }
+ $errors[] = 'Membership Start Date is required to create a memberships.';
}
- //date-Format part ends
-
- $params['contact_type'] = 'Membership';
-
- //checking error in custom data
- $this->isErrorInCustomData($params, $errorMessage);
-
- if ($errorMessage) {
- $tempMsg = "Invalid value for field(s) : $errorMessage";
- array_unshift($values, $tempMsg);
- $errorMessage = NULL;
- return CRM_Import_Parser::ERROR;
+ if ($errors) {
+ throw new CRM_Core_Exception('Invalid value for field(s) : ' . implode(',', $errors));
}
return CRM_Import_Parser::VALID;
* the result of this processing
*/
public function import($onDuplicate, &$values) {
+ $rowNumber = (int) ($values[array_key_last($values)]);
try {
- // first make sure this is a valid line
- $response = $this->summary($values);
- if ($response != CRM_Import_Parser::VALID) {
- return $response;
- }
$params = $this->getMappedRow($values);
//assign join date equal to start date if join date is not provided
// onDuplicate == CRM_Import_Parser::DUPLICATE_UPDATE
if (!empty($formatted['is_override']) && empty($formatted['status_id'])) {
array_unshift($values, 'Required parameter missing: Status');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Required parameter missing: Status');
return CRM_Import_Parser::ERROR;
}
$newMembership = civicrm_api3('Membership', 'create', $formatted);
$this->_newMemberships[] = $newMembership['id'];
+ $this->setImportStatus($rowNumber, 'IMPORTED', 'Required parameter missing: Status');
return CRM_Import_Parser::VALID;
}
else {
array_unshift($values, 'Matching Membership record not found for Membership ID ' . $formatValues['membership_id'] . '. Row was skipped.');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Matching Membership record not found for Membership ID ' . $formatValues['membership_id'] . '. Row was skipped.');
return CRM_Import_Parser::ERROR;
}
}
$matchedIDs = explode(',', $error['error_message']['params'][0]);
if (count($matchedIDs) > 1) {
array_unshift($values, 'Multiple matching contact records detected for this row. The membership was not imported');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Multiple matching contact records detected for this row. The membership was not imported');
return CRM_Import_Parser::ERROR;
}
else {
}
elseif (empty($formatted['is_override'])) {
if (empty($calcStatus)) {
- array_unshift($values, 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
return CRM_Import_Parser::ERROR;
}
- elseif ($formatted['status_id'] != $calcStatus['id']) {
+ if ($formatted['status_id'] != $calcStatus['id']) {
//Status Hold" is either NOT mapped or is FALSE
- array_unshift($values, 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Status in import row (' . $formatValues['status_id'] . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
return CRM_Import_Parser::ERROR;
}
}
$newMembership = civicrm_api3('membership', 'create', $formatted);
$this->_newMemberships[] = $newMembership['id'];
+ $this->setImportStatus($rowNumber, 'IMPORTED', '');
return CRM_Import_Parser::VALID;
}
}
$disp = $params['external_identifier'];
}
}
-
- array_unshift($values, 'No matching Contact found for (' . $disp . ')');
+ $this->setImportStatus($rowNumber, 'ERROR', 'No matching Contact found for (' . $disp . ')');
return CRM_Import_Parser::ERROR;
}
}
$checkCid->find(TRUE);
if ($checkCid->id != $formatted['contact_id']) {
array_unshift($values, 'Mismatch of External ID:' . $formatValues['external_identifier'] . ' and Contact Id:' . $formatted['contact_id']);
+ $this->setImportStatus($rowNumber, 'ERROR', 'Mismatch of External ID:' . $formatValues['external_identifier'] . ' and Contact Id:' . $formatted['contact_id']);
return CRM_Import_Parser::ERROR;
}
}
elseif (empty($formatted['is_override'])) {
if (empty($calcStatus)) {
array_unshift($values, 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules. Record was not imported.');
return CRM_Import_Parser::ERROR;
}
elseif ($formatted['status_id'] != $calcStatus['id']) {
//Status Hold" is either NOT mapped or is FALSE
array_unshift($values, 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
+ $this->setImportStatus($rowNumber, 'ERROR', 'Status in import row (' . CRM_Utils_Array::value('status_id', $formatValues) . ') does not match calculated status based on your configured Membership Status Rules (' . $calcStatus['name'] . '). Record was not imported.');
return CRM_Import_Parser::ERROR;
}
}
$newMembership = civicrm_api3('membership', 'create', $formatted);
$this->_newMemberships[] = $newMembership['id'];
+ $this->setImportStatus($rowNumber, 'IMPORTED', '');
return CRM_Import_Parser::VALID;
}
}
catch (Exception $e) {
array_unshift($values, $e->getMessage());
+ $this->setImportStatus($rowNumber, 'ERROR', $e->getMessage());
return CRM_Import_Parser::ERROR;
}
}
}
}
+ /**
+ * Get the metadata field for which importable fields does not key the actual field name.
+ *
+ * @return string[]
+ */
+ protected function getOddlyMappedMetadataFields(): array {
+ $uniqueNames = ['membership_id', 'membership_contact_id'];
+ $fields = [];
+ foreach ($uniqueNames as $name) {
+ $fields[$this->importableFieldsMetadata[$name]['name']] = $name;
+ }
+ // Include the parent fields as they could be present if required for matching ...in theory.
+ return array_merge($fields, parent::getOddlyMappedMetadataFields());
+ }
+
}
{* @var $form Contains the array for the form elements and other form associated information assigned to the template by the controller *}
{* Table for mapping data to CRM fields *}
- {include file="CRM/Import/Form/MapTable.tpl"}
+ {include file="CRM/Import/Form/MapTableCommon.tpl" mapper=$form.mapper}
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
</div>
{* Table for mapping preview *}
- {include file="CRM/Import/Form/MapTable.tpl"}
+ {include file="CRM/Import/Form/MapTableCommon.tpl"}
<div class="crm-submit-buttons">{include file="CRM/common/formButtons.tpl" location="bottom"}</div>
class CRM_Member_Import_Parser_MembershipTest extends CiviUnitTestCase {
use CRMTraits_Custom_CustomDataTrait;
+ /**
+ * @var int
+ */
+ protected $userJobID;
+
/**
* Membership type name used in test function.
*
'civicrm_membership_payment',
'civicrm_contact',
'civicrm_email',
+ 'civicrm_user_job',
+ 'civicrm_queue',
+ 'civicrm_queue_item',
];
$this->relationshipTypeDelete($this->_relationshipTypeId);
$this->membershipTypeDelete(['id' => $this->_membershipTypeID]);
$this->assertEquals('R', $membership[$this->getCustomFieldName('select_string')]);
}
+ /**
+ * Test the full form-flow import.
+ */
+ public function testImportCSV() :void {
+ $this->importCSV('memberships.csv', [
+ ['name' => 'membership_contact_id'],
+ ['name' => 'membership_source'],
+ ['name' => 'membership_type_id'],
+ ['name' => 'membership_start_date'],
+ ['name' => 'do_not_import'],
+ ]);
+ $dataSource = new CRM_Import_DataSource_CSV($this->userJobID);
+ $row = $dataSource->getRow();
+ $this->assertEquals('ERROR', $row['_status']);
+ $this->assertEquals('Invalid value for field(s) : Membership Type', $row['_status_message']);
+ }
+
+ /**
+ * Import the csv file values.
+ *
+ * This function uses a flow that mimics the UI flow.
+ *
+ * @param string $csv Name of csv file.
+ * @param array $fieldMappings
+ * @param array $submittedValues
+ */
+ protected function importCSV(string $csv, array $fieldMappings, array $submittedValues = []): void {
+ $submittedValues = array_merge([
+ 'uploadFile' => ['name' => __DIR__ . '/data/' . $csv],
+ 'skipColumnHeader' => TRUE,
+ 'fieldSeparator' => ',',
+ 'contactType' => CRM_Import_Parser::CONTACT_INDIVIDUAL,
+ 'mapper' => $this->getMapperFromFieldMappings($fieldMappings),
+ 'dataSource' => 'CRM_Import_DataSource_CSV',
+ 'file' => ['name' => $csv],
+ 'dateFormats' => CRM_Core_Form_Date::DATE_yyyy_mm_dd,
+ 'onDuplicate' => CRM_Import_Parser::DUPLICATE_UPDATE,
+ 'groups' => [],
+ ], $submittedValues);
+ $form = $this->getFormObject('CRM_Member_Import_Form_DataSource', $submittedValues);
+ $form->buildForm();
+ $form->postProcess();
+ $this->userJobID = $form->getUserJobID();
+ $form = $this->getFormObject('CRM_Member_Import_Form_MapField', $submittedValues);
+ $form->setUserJobID($this->userJobID);
+ $form->buildForm();
+ $form->postProcess();
+ /* @var CRM_Member_Import_Form_MapField $form */
+ $form = $this->getFormObject('CRM_Member_Import_Form_Preview', $submittedValues);
+ $form->setUserJobID($this->userJobID);
+ $form->buildForm();
+ $form->postProcess();
+ }
+
+ /**
+ * @param array $mappings
+ *
+ * @return array
+ */
+ protected function getMapperFromFieldMappings(array $mappings): array {
+ $mapper = [];
+ foreach ($mappings as $mapping) {
+ $fieldInput = [$mapping['name']];
+ $mapper[] = $fieldInput;
+ }
+ return $mapper;
+ }
+
}
$_SESSION['_' . $form->controller->_name . '_container']['values']['Preview'] = $formValues;
return $form;
+ case 'CRM_Member_Import_Form_DataSource':
+ case 'CRM_Member_Import_Form_MapField':
+ case 'CRM_Member_Import_Form_Preview':
+ $form->controller = new CRM_Member_Import_Controller();
+ $form->controller->setStateMachine(new CRM_Core_StateMachine($form->controller));
+ // The submitted values should be set on one or the other of the forms in the flow.
+ // For test simplicity we set on all rather than figuring out which ones go where....
+ $_SESSION['_' . $form->controller->_name . '_container']['values']['DataSource'] = $formValues;
+ $_SESSION['_' . $form->controller->_name . '_container']['values']['MapField'] = $formValues;
+ $_SESSION['_' . $form->controller->_name . '_container']['values']['Preview'] = $formValues;
+ return $form;
+
case strpos($class, '_Form_') !== FALSE:
$form->controller = new CRM_Core_Controller_Simple($class, $pageName);
break;