コード例 #1
0
ファイル: Export.php プロジェクト: scardinius/civicrm-core
 /**
  * Get the list the export fields.
  *
  * @param int $selectAll
  *   User preference while export.
  * @param array $ids
  *   Contact ids.
  * @param array $params
  *   Associated array of fields.
  * @param string $order
  *   Order by clause.
  * @param array $fields
  *   Associated array of fields.
  * @param array $moreReturnProperties
  *   Additional return fields.
  * @param int $exportMode
  *   Export mode.
  * @param string $componentClause
  *   Component clause.
  * @param string $componentTable
  *   Component table.
  * @param bool $mergeSameAddress
  *   Merge records if they have same address.
  * @param bool $mergeSameHousehold
  *   Merge records if they belong to the same household.
  *
  * @param array $exportParams
  * @param string $queryOperator
  *
  */
 public static function exportComponents($selectAll, $ids, $params, $order = NULL, $fields = NULL, $moreReturnProperties = NULL, $exportMode = CRM_Export_Form_Select::CONTACT_EXPORT, $componentClause = NULL, $componentTable = NULL, $mergeSameAddress = FALSE, $mergeSameHousehold = FALSE, $exportParams = array(), $queryOperator = 'AND')
 {
     $returnProperties = array();
     $paymentFields = $selectedPaymentFields = FALSE;
     $relationField = NULL;
     $phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
     // Warning - this imProviders var is used in a somewhat fragile way - don't rename it
     // without manually testing the export of IM provider still works.
     $imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
     $contactRelationshipTypes = CRM_Contact_BAO_Relationship::getContactRelationshipType(NULL, NULL, NULL, NULL, TRUE, 'name', FALSE);
     $queryMode = self::getQueryMode($exportMode);
     if ($fields) {
         //construct return properties
         $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
         $locationTypeFields = array('street_address', 'supplemental_address_1', 'supplemental_address_2', 'city', 'postal_code', 'postal_code_suffix', 'geo_code_1', 'geo_code_2', 'state_province', 'country', 'phone', 'email', 'im');
         foreach ($fields as $key => $value) {
             $phoneTypeId = $imProviderId = NULL;
             $relationshipTypes = $fieldName = CRM_Utils_Array::value(1, $value);
             if (!$fieldName) {
                 continue;
             }
             // get phoneType id and IM service provider id separately
             if ($fieldName == 'phone') {
                 $phoneTypeId = CRM_Utils_Array::value(3, $value);
             } elseif ($fieldName == 'im') {
                 $imProviderId = CRM_Utils_Array::value(3, $value);
             }
             if (array_key_exists($relationshipTypes, $contactRelationshipTypes)) {
                 if (!empty($value[2])) {
                     $relationField = CRM_Utils_Array::value(2, $value);
                     if (trim(CRM_Utils_Array::value(3, $value))) {
                         $relLocTypeId = CRM_Utils_Array::value(3, $value);
                     } else {
                         $relLocTypeId = 'Primary';
                     }
                     if ($relationField == 'phone') {
                         $relPhoneTypeId = CRM_Utils_Array::value(4, $value);
                     } elseif ($relationField == 'im') {
                         $relIMProviderId = CRM_Utils_Array::value(4, $value);
                     }
                 } elseif (!empty($value[4])) {
                     $relationField = CRM_Utils_Array::value(4, $value);
                     $relLocTypeId = CRM_Utils_Array::value(5, $value);
                     if ($relationField == 'phone') {
                         $relPhoneTypeId = CRM_Utils_Array::value(6, $value);
                     } elseif ($relationField == 'im') {
                         $relIMProviderId = CRM_Utils_Array::value(6, $value);
                     }
                 }
             }
             $contactType = CRM_Utils_Array::value(0, $value);
             $locTypeId = CRM_Utils_Array::value(2, $value);
             if ($relationField) {
                 if (in_array($relationField, $locationTypeFields) && is_numeric($relLocTypeId)) {
                     if ($relPhoneTypeId) {
                         $returnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]]['phone-' . $relPhoneTypeId] = 1;
                     } elseif ($relIMProviderId) {
                         $returnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]]['im-' . $relIMProviderId] = 1;
                     } else {
                         $returnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]][$relationField] = 1;
                     }
                     $relPhoneTypeId = $relIMProviderId = NULL;
                 } else {
                     $returnProperties[$relationshipTypes][$relationField] = 1;
                 }
             } elseif (is_numeric($locTypeId)) {
                 if ($phoneTypeId) {
                     $returnProperties['location'][$locationTypes[$locTypeId]]['phone-' . $phoneTypeId] = 1;
                 } elseif ($imProviderId) {
                     $returnProperties['location'][$locationTypes[$locTypeId]]['im-' . $imProviderId] = 1;
                 } else {
                     $returnProperties['location'][$locationTypes[$locTypeId]][$fieldName] = 1;
                 }
             } else {
                 //hack to fix component fields
                 //revert mix of event_id and title
                 if ($fieldName == 'event_id') {
                     $returnProperties['event_id'] = 1;
                 } elseif ($exportMode == CRM_Export_Form_Select::EVENT_EXPORT && array_key_exists($fieldName, self::componentPaymentFields())) {
                     $selectedPaymentFields = TRUE;
                     $paymentTableId = 'participant_id';
                     $returnProperties[$fieldName] = 1;
                 } else {
                     $returnProperties[$fieldName] = 1;
                 }
             }
         }
         $defaultExportMode = self::defaultReturnProperty($exportMode);
         if ($defaultExportMode) {
             $returnProperties[$defaultExportMode] = 1;
         }
     } else {
         $primary = TRUE;
         $fields = CRM_Contact_BAO_Contact::exportableFields('All', TRUE, TRUE);
         foreach ($fields as $key => $var) {
             if ($key && substr($key, 0, 6) != 'custom') {
                 //for CRM=952
                 $returnProperties[$key] = 1;
             }
         }
         if ($primary) {
             $returnProperties['location_type'] = 1;
             $returnProperties['im_provider'] = 1;
             $returnProperties['phone_type_id'] = 1;
             $returnProperties['provider_id'] = 1;
             $returnProperties['current_employer'] = 1;
         }
         $extraProperties = self::defineExtraProperties($queryMode);
         $paymentFields = $extraProperties['paymentFields'];
         $extraReturnProperties = $extraProperties['extraReturnProperties'];
         $paymentTableId = $extraProperties['paymentTableId'];
         if ($queryMode != CRM_Contact_BAO_Query::MODE_CONTACTS) {
             $componentReturnProperties = CRM_Contact_BAO_Query::defaultReturnProperties($queryMode);
             if ($queryMode == CRM_Contact_BAO_Query::MODE_CONTRIBUTE) {
                 // soft credit columns are not automatically populated, because contribution search doesn't require them by default
                 $componentReturnProperties = array_merge($componentReturnProperties, CRM_Contribute_BAO_Query::softCreditReturnProperties(TRUE));
             }
             $returnProperties = array_merge($returnProperties, $componentReturnProperties);
             if (!empty($extraReturnProperties)) {
                 $returnProperties = array_merge($returnProperties, $extraReturnProperties);
             }
             // unset non exportable fields for components
             $nonExpoFields = array('groups', 'tags', 'notes', 'contribution_status_id', 'pledge_status_id', 'pledge_payment_status_id');
             foreach ($nonExpoFields as $value) {
                 unset($returnProperties[$value]);
             }
         }
     }
     if ($mergeSameAddress) {
         //make sure the addressee fields are selected
         //while using merge same address feature
         $returnProperties['addressee'] = 1;
         $returnProperties['postal_greeting'] = 1;
         $returnProperties['email_greeting'] = 1;
         $returnProperties['street_name'] = 1;
         $returnProperties['household_name'] = 1;
         $returnProperties['street_address'] = 1;
         $returnProperties['city'] = 1;
         $returnProperties['state_province'] = 1;
         // some columns are required for assistance incase they are not already present
         $exportParams['merge_same_address']['temp_columns'] = array();
         $tempColumns = array('id', 'master_id', 'state_province_id', 'postal_greeting_id', 'addressee_id');
         foreach ($tempColumns as $column) {
             if (!array_key_exists($column, $returnProperties)) {
                 $returnProperties[$column] = 1;
                 $column = $column == 'id' ? 'civicrm_primary_id' : $column;
                 $exportParams['merge_same_address']['temp_columns'][$column] = 1;
             }
         }
     }
     if (!$selectAll && $componentTable && !empty($exportParams['additional_group'])) {
         // If an Additional Group is selected, then all contacts in that group are
         // added to the export set (filtering out duplicates).
         $query = "\nINSERT INTO {$componentTable} SELECT distinct gc.contact_id FROM civicrm_group_contact gc WHERE gc.group_id = {$exportParams['additional_group']} ON DUPLICATE KEY UPDATE {$componentTable}.contact_id = gc.contact_id";
         CRM_Core_DAO::executeQuery($query);
     }
     if ($moreReturnProperties) {
         // fix for CRM-7066
         if (!empty($moreReturnProperties['group'])) {
             unset($moreReturnProperties['group']);
             $moreReturnProperties['groups'] = 1;
         }
         $returnProperties = array_merge($returnProperties, $moreReturnProperties);
     }
     $exportParams['postal_mailing_export']['temp_columns'] = array();
     if ($exportParams['exportOption'] == 2 && isset($exportParams['postal_mailing_export']) && CRM_Utils_Array::value('postal_mailing_export', $exportParams['postal_mailing_export']) == 1) {
         $postalColumns = array('is_deceased', 'do_not_mail', 'street_address', 'supplemental_address_1');
         foreach ($postalColumns as $column) {
             if (!array_key_exists($column, $returnProperties)) {
                 $returnProperties[$column] = 1;
                 $exportParams['postal_mailing_export']['temp_columns'][$column] = 1;
             }
         }
     }
     // rectify params to what proximity search expects if there is a value for prox_distance
     // CRM-7021
     if (!empty($params)) {
         CRM_Contact_BAO_ProximityQuery::fixInputParams($params);
     }
     $query = new CRM_Contact_BAO_Query($params, $returnProperties, NULL, FALSE, FALSE, $queryMode, FALSE, TRUE, TRUE, NULL, $queryOperator);
     //sort by state
     //CRM-15301
     $query->_sort = $order;
     list($select, $from, $where, $having) = $query->query();
     if ($mergeSameHousehold == 1) {
         if (empty($returnProperties['id'])) {
             $returnProperties['id'] = 1;
         }
         //also merge Head of Household
         $relationKeyMOH = CRM_Utils_Array::key('Household Member of', $contactRelationshipTypes);
         $relationKeyHOH = CRM_Utils_Array::key('Head of Household for', $contactRelationshipTypes);
         foreach ($returnProperties as $key => $value) {
             if (!array_key_exists($key, $contactRelationshipTypes)) {
                 $returnProperties[$relationKeyMOH][$key] = $value;
                 $returnProperties[$relationKeyHOH][$key] = $value;
             }
         }
         unset($returnProperties[$relationKeyMOH]['location_type']);
         unset($returnProperties[$relationKeyMOH]['im_provider']);
         unset($returnProperties[$relationKeyHOH]['location_type']);
         unset($returnProperties[$relationKeyHOH]['im_provider']);
     }
     $allRelContactArray = $relationQuery = array();
     foreach ($contactRelationshipTypes as $rel => $dnt) {
         if ($relationReturnProperties = CRM_Utils_Array::value($rel, $returnProperties)) {
             $allRelContactArray[$rel] = array();
             // build Query for each relationship
             $relationQuery[$rel] = new CRM_Contact_BAO_Query(NULL, $relationReturnProperties, NULL, FALSE, FALSE, $queryMode);
             list($relationSelect, $relationFrom, $relationWhere, $relationHaving) = $relationQuery[$rel]->query();
             list($id, $direction) = explode('_', $rel, 2);
             // identify the relationship direction
             $contactA = 'contact_id_a';
             $contactB = 'contact_id_b';
             if ($direction == 'b_a') {
                 $contactA = 'contact_id_b';
                 $contactB = 'contact_id_a';
             }
             if ($exportMode == CRM_Export_Form_Select::CONTACT_EXPORT) {
                 $relIDs = $ids;
             } elseif ($exportMode == CRM_Export_Form_Select::ACTIVITY_EXPORT) {
                 $sourceID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Source');
                 $query = "SELECT contact_id FROM civicrm_activity_contact\n                              WHERE activity_id IN ( " . implode(',', $ids) . ") AND\n                              record_type_id = {$sourceID}";
                 $dao = CRM_Core_DAO::executeQuery($query);
                 while ($dao->fetch()) {
                     $relIDs[] = $dao->contact_id;
                 }
             } else {
                 $component = self::exportComponent($exportMode);
                 if ($exportMode == CRM_Export_Form_Select::CASE_EXPORT) {
                     $relIDs = CRM_Case_BAO_Case::retrieveContactIdsByCaseId($ids);
                 } else {
                     $relIDs = CRM_Core_DAO::getContactIDsFromComponent($ids, $component);
                 }
             }
             $relationshipJoin = $relationshipClause = '';
             if (!$selectAll && $componentTable) {
                 $relationshipJoin = " INNER JOIN {$componentTable} ctTable ON ctTable.contact_id = {$contactA}";
             } elseif (!empty($relIDs)) {
                 $relID = implode(',', $relIDs);
                 $relationshipClause = " AND crel.{$contactA} IN ( {$relID} )";
             }
             $relationFrom = " {$relationFrom}\n                INNER JOIN civicrm_relationship crel ON crel.{$contactB} = contact_a.id AND crel.relationship_type_id = {$id}\n                {$relationshipJoin} ";
             //check for active relationship status only
             $today = date('Ymd');
             $relationActive = " AND (crel.is_active = 1 AND ( crel.end_date is NULL OR crel.end_date >= {$today} ) )";
             $relationWhere = " WHERE contact_a.is_deleted = 0 {$relationshipClause} {$relationActive}";
             $relationGroupBy = " GROUP BY crel.{$contactA}";
             $relationSelect = "{$relationSelect}, {$contactA} as refContact ";
             $relationQueryString = "{$relationSelect} {$relationFrom} {$relationWhere} {$relationHaving} {$relationGroupBy}";
             $allRelContactDAO = CRM_Core_DAO::executeQuery($relationQueryString);
             while ($allRelContactDAO->fetch()) {
                 //FIX Me: Migrate this to table rather than array
                 // build the array of all related contacts
                 $allRelContactArray[$rel][$allRelContactDAO->refContact] = clone $allRelContactDAO;
             }
             $allRelContactDAO->free();
         }
     }
     // make sure the groups stuff is included only if specifically specified
     // by the fields param (CRM-1969), else we limit the contacts outputted to only
     // ones that are part of a group
     if (!empty($returnProperties['groups'])) {
         $oldClause = "( contact_a.id = civicrm_group_contact.contact_id )";
         $newClause = " ( {$oldClause} AND ( civicrm_group_contact.status = 'Added' OR civicrm_group_contact.status IS NULL ) )";
         // total hack for export, CRM-3618
         $from = str_replace($oldClause, $newClause, $from);
     }
     if (!$selectAll && $componentTable) {
         $from .= " INNER JOIN {$componentTable} ctTable ON ctTable.contact_id = contact_a.id ";
     } elseif ($componentClause) {
         if (empty($where)) {
             $where = "WHERE {$componentClause}";
         } else {
             $where .= " AND {$componentClause}";
         }
     }
     // CRM-13982 - check if is deleted
     $excludeTrashed = TRUE;
     foreach ($params as $value) {
         if ($value[0] == 'contact_is_deleted') {
             $excludeTrashed = FALSE;
         }
     }
     $trashClause = $excludeTrashed ? "contact_a.is_deleted != 1" : "( 1 )";
     if (empty($where)) {
         $where = "WHERE {$trashClause}";
     } else {
         $where .= " AND {$trashClause}";
     }
     $queryString = "{$select} {$from} {$where} {$having}";
     $groupBy = self::getGroupBy($exportMode, $queryMode, $returnProperties, $query);
     $queryString .= $groupBy;
     // always add contact_a.id to the ORDER clause
     // so the order is deterministic
     //CRM-15301
     if (strpos('contact_a.id', $order) === FALSE) {
         $order .= ", contact_a.id";
     }
     if ($order) {
         list($field, $dir) = explode(' ', $order, 2);
         $field = trim($field);
         if (!empty($returnProperties[$field])) {
             //CRM-15301
             $queryString .= " ORDER BY {$order}";
         }
     }
     $multipleSelectFields = array('preferred_communication_method' => 1);
     $addPaymentHeader = FALSE;
     $paymentDetails = array();
     if ($paymentFields || $selectedPaymentFields) {
         // get payment related in for event and members
         $paymentDetails = CRM_Contribute_BAO_Contribution::getContributionDetails($exportMode, $ids);
         //get all payment headers.
         // If we haven't selected specific payment fields, load in all the
         // payment headers.
         if (!$selectedPaymentFields) {
             $paymentHeaders = self::componentPaymentFields();
             if (!empty($paymentDetails)) {
                 $addPaymentHeader = TRUE;
             }
         } else {
             $paymentHeaders = array();
         }
         $nullContributionDetails = array_fill_keys(array_keys($paymentHeaders), NULL);
     }
     $componentDetails = array();
     $setHeader = TRUE;
     $rowCount = self::EXPORT_ROW_COUNT;
     $offset = 0;
     // we write to temp table often to avoid using too much memory
     $tempRowCount = 100;
     $count = -1;
     // for CRM-3157 purposes
     $i18n = CRM_Core_I18n::singleton();
     list($outputColumns, $headerRows, $sqlColumns, $metadata) = self::getExportStructureArrays($returnProperties, $query, $phoneTypes, $imProviders, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields);
     $limitReached = FALSE;
     while (!$limitReached) {
         $limitQuery = "{$queryString} LIMIT {$offset}, {$rowCount}";
         $dao = CRM_Core_DAO::executeUnbufferedQuery($limitQuery);
         // If this is less than our limit by the end of the iteration we do not need to run the query again to
         // check if some remain.
         $rowsThisIteration = 0;
         while ($dao->fetch()) {
             $count++;
             $rowsThisIteration++;
             $row = array();
             //convert the pseudo constants
             // CRM-14398 there is problem in this architecture that is not easily solved. For now we are using the cloned
             // temporary iterationDAO object to get around it.
             // the issue is that the convertToPseudoNames function is adding additional properties (e.g for campaign) to the DAO object
             // these additional properties are NOT reset when the $dao cycles through the while loop
             // nor are they overwritten as they are not in the loop
             // the convertToPseudoNames will not adequately over-write them either as it doesn't 'kick-in' unless the
             // relevant property is set.
             // It may be that a long-term fix could be introduced there - however, it's probably necessary to figure out how to test the
             // export class before tackling a better architectural fix
             $iterationDAO = clone $dao;
             $query->convertToPseudoNames($iterationDAO);
             //first loop through output columns so that we return what is required, and in same order.
             $relationshipField = 0;
             foreach ($outputColumns as $field => $value) {
                 // add im_provider to $dao object
                 if ($field == 'im_provider' && property_exists($iterationDAO, 'provider_id')) {
                     $iterationDAO->im_provider = $iterationDAO->provider_id;
                 }
                 //build row values (data)
                 $fieldValue = NULL;
                 if (property_exists($iterationDAO, $field)) {
                     $fieldValue = $iterationDAO->{$field};
                     // to get phone type from phone type id
                     if ($field == 'phone_type_id' && isset($phoneTypes[$fieldValue])) {
                         $fieldValue = $phoneTypes[$fieldValue];
                     } elseif ($field == 'provider_id' || $field == 'im_provider') {
                         $fieldValue = CRM_Utils_Array::value($fieldValue, $imProviders);
                     } elseif ($field == 'master_id') {
                         $masterAddressId = NULL;
                         if (isset($iterationDAO->master_id)) {
                             $masterAddressId = $iterationDAO->master_id;
                         }
                         // get display name of contact that address is shared.
                         $fieldValue = CRM_Contact_BAO_Contact::getMasterDisplayName($masterAddressId, $iterationDAO->contact_id);
                     }
                 }
                 if ($field == 'id') {
                     $row[$field] = $iterationDAO->contact_id;
                     // special case for calculated field
                 } elseif ($field == 'source_contact_id') {
                     $row[$field] = $iterationDAO->contact_id;
                 } elseif ($field == 'pledge_balance_amount') {
                     $row[$field] = $iterationDAO->pledge_amount - $iterationDAO->pledge_total_paid;
                     // special case for calculated field
                 } elseif ($field == 'pledge_next_pay_amount') {
                     $row[$field] = $iterationDAO->pledge_next_pay_amount + $iterationDAO->pledge_outstanding_amount;
                 } elseif (array_key_exists($field, $contactRelationshipTypes)) {
                     $relDAO = CRM_Utils_Array::value($iterationDAO->contact_id, $allRelContactArray[$field]);
                     $relationQuery[$field]->convertToPseudoNames($relDAO);
                     foreach ($value as $relationField => $relationValue) {
                         if (is_object($relDAO) && property_exists($relDAO, $relationField)) {
                             $fieldValue = $relDAO->{$relationField};
                             if ($relationField == 'phone_type_id') {
                                 $fieldValue = $phoneTypes[$relationValue];
                             } elseif ($relationField == 'provider_id') {
                                 $fieldValue = CRM_Utils_Array::value($relationValue, $imProviders);
                             } elseif (is_object($relDAO) && in_array($relationField, array('email_greeting', 'postal_greeting', 'addressee'))) {
                                 //special case for greeting replacement
                                 $fldValue = "{$relationField}_display";
                                 $fieldValue = $relDAO->{$fldValue};
                             }
                         } elseif (is_object($relDAO) && $relationField == 'state_province') {
                             $fieldValue = CRM_Core_PseudoConstant::stateProvince($relDAO->state_province_id);
                         } elseif (is_object($relDAO) && $relationField == 'country') {
                             $fieldValue = CRM_Core_PseudoConstant::country($relDAO->country_id);
                         } else {
                             $fieldValue = '';
                         }
                         $field = $field . '_';
                         if (array_key_exists($relationField, $multipleSelectFields)) {
                             $param = array($relationField => $fieldValue);
                             $names = array($relationField => array('newName' => $relationField, 'groupName' => $relationField));
                             CRM_Core_OptionGroup::lookupValues($param, $names, FALSE);
                             $fieldValue = $param[$relationField];
                         }
                         if (is_object($relDAO) && $relationField == 'id') {
                             $row[$field . $relationField] = $relDAO->contact_id;
                         } elseif (is_array($relationValue) && $relationField == 'location') {
                             foreach ($relationValue as $ltype => $val) {
                                 foreach (array_keys($val) as $fld) {
                                     $type = explode('-', $fld);
                                     $fldValue = "{$ltype}-" . $type[0];
                                     if (!empty($type[1])) {
                                         $fldValue .= "-" . $type[1];
                                     }
                                     // CRM-3157: localise country, region (both have ‘country’ context)
                                     // and state_province (‘province’ context)
                                     switch (TRUE) {
                                         case !is_object($relDAO):
                                             $row[$field . '_' . $fldValue] = '';
                                             break;
                                         case in_array('country', $type):
                                         case in_array('world_region', $type):
                                             $row[$field . '_' . $fldValue] = $i18n->crm_translate($relDAO->{$fldValue}, array('context' => 'country'));
                                             break;
                                         case in_array('state_province', $type):
                                             $row[$field . '_' . $fldValue] = $i18n->crm_translate($relDAO->{$fldValue}, array('context' => 'province'));
                                             break;
                                         default:
                                             $row[$field . '_' . $fldValue] = $relDAO->{$fldValue};
                                             break;
                                     }
                                 }
                             }
                         } elseif (isset($fieldValue) && $fieldValue != '') {
                             //check for custom data
                             if ($cfID = CRM_Core_BAO_CustomField::getKeyID($relationField)) {
                                 $row[$field . $relationField] = CRM_Core_BAO_CustomField::displayValue($fieldValue, $cfID);
                             } else {
                                 //normal relationship fields
                                 // CRM-3157: localise country, region (both have ‘country’ context) and state_province (‘province’ context)
                                 switch ($relationField) {
                                     case 'country':
                                     case 'world_region':
                                         $row[$field . $relationField] = $i18n->crm_translate($fieldValue, array('context' => 'country'));
                                         break;
                                     case 'state_province':
                                         $row[$field . $relationField] = $i18n->crm_translate($fieldValue, array('context' => 'province'));
                                         break;
                                     default:
                                         $row[$field . $relationField] = $fieldValue;
                                         break;
                                 }
                             }
                         } else {
                             // if relation field is empty or null
                             $row[$field . $relationField] = '';
                         }
                     }
                 } elseif (isset($fieldValue) && $fieldValue != '') {
                     //check for custom data
                     if ($cfID = CRM_Core_BAO_CustomField::getKeyID($field)) {
                         $row[$field] = CRM_Core_BAO_CustomField::displayValue($fieldValue, $cfID);
                     } elseif (array_key_exists($field, $multipleSelectFields)) {
                         //option group fixes
                         $paramsNew = array($field => $fieldValue);
                         if ($field == 'test_tutoring') {
                             $name = array($field => array('newName' => $field, 'groupName' => 'test'));
                             // for  readers group
                         } elseif (substr($field, 0, 4) == 'cmr_') {
                             $name = array($field => array('newName' => $field, 'groupName' => substr($field, 0, -3)));
                         } else {
                             $name = array($field => array('newName' => $field, 'groupName' => $field));
                         }
                         CRM_Core_OptionGroup::lookupValues($paramsNew, $name, FALSE);
                         $row[$field] = $paramsNew[$field];
                     } elseif (in_array($field, array('email_greeting', 'postal_greeting', 'addressee'))) {
                         //special case for greeting replacement
                         $fldValue = "{$field}_display";
                         $row[$field] = $iterationDAO->{$fldValue};
                     } else {
                         //normal fields with a touch of CRM-3157
                         switch ($field) {
                             case 'country':
                             case 'world_region':
                                 $row[$field] = $i18n->crm_translate($fieldValue, array('context' => 'country'));
                                 break;
                             case 'state_province':
                                 $row[$field] = $i18n->crm_translate($fieldValue, array('context' => 'province'));
                                 break;
                             case 'gender':
                             case 'preferred_communication_method':
                             case 'preferred_mail_format':
                             case 'communication_style':
                                 $row[$field] = $i18n->crm_translate($fieldValue);
                                 break;
                             default:
                                 if (isset($metadata[$field])) {
                                     // No I don't know why we do it this way & whether we could
                                     // make better use of pseudoConstants.
                                     if (!empty($metadata[$field]['context'])) {
                                         $row[$field] = $i18n->crm_translate($fieldValue, $metadata[$field]);
                                         break;
                                     }
                                     if (!empty($metadata[$field]['pseudoconstant'])) {
                                         // This is not our normal syntax for pseudoconstants but I am a bit loath to
                                         // call an external function until sure it is not increasing php processing given this
                                         // may be iterated 100,000 times & we already have the $imProvider var loaded.
                                         // That can be next refactor...
                                         // Yes - definitely feeling hatred for this bit of code - I know you will beat me up over it's awfulness
                                         // but I have to reach a stable point....
                                         $varName = $metadata[$field]['pseudoconstant']['var'];
                                         $labels = ${$varName};
                                         $row[$field] = $labels[$fieldValue];
                                         break;
                                     }
                                 }
                                 $row[$field] = $fieldValue;
                                 break;
                         }
                     }
                 } elseif ($selectedPaymentFields && array_key_exists($field, self::componentPaymentFields())) {
                     $paymentData = CRM_Utils_Array::value($iterationDAO->{$paymentTableId}, $paymentDetails);
                     $payFieldMapper = array('componentPaymentField_total_amount' => 'total_amount', 'componentPaymentField_contribution_status' => 'contribution_status', 'componentPaymentField_payment_instrument' => 'pay_instru', 'componentPaymentField_transaction_id' => 'trxn_id', 'componentPaymentField_received_date' => 'receive_date');
                     $row[$field] = CRM_Utils_Array::value($payFieldMapper[$field], $paymentData, '');
                 } else {
                     // if field is empty or null
                     $row[$field] = '';
                 }
             }
             // add payment headers if required
             if ($addPaymentHeader && $paymentFields) {
                 // @todo rather than do this for every single row do it before the loop starts.
                 // where other header definitions take place.
                 $headerRows = array_merge($headerRows, $paymentHeaders);
                 foreach (array_keys($paymentHeaders) as $paymentHdr) {
                     self::sqlColumnDefn($query, $sqlColumns, $paymentHdr);
                 }
             }
             if ($setHeader) {
                 $exportTempTable = self::createTempTable($sqlColumns);
             }
             //build header only once
             $setHeader = FALSE;
             // If specific payment fields have been selected for export, payment
             // data will already be in $row. Otherwise, add payment related
             // information, if appropriate.
             if ($addPaymentHeader) {
                 if (!$selectedPaymentFields) {
                     if ($paymentFields) {
                         $paymentData = CRM_Utils_Array::value($row[$paymentTableId], $paymentDetails);
                         if (!is_array($paymentData) || empty($paymentData)) {
                             $paymentData = $nullContributionDetails;
                         }
                         $row = array_merge($row, $paymentData);
                     } elseif (!empty($paymentDetails)) {
                         $row = array_merge($row, $nullContributionDetails);
                     }
                 }
             }
             //remove organization name for individuals if it is set for current employer
             if (!empty($row['contact_type']) && $row['contact_type'] == 'Individual' && array_key_exists('organization_name', $row)) {
                 $row['organization_name'] = '';
             }
             // add component info
             // write the row to a file
             $componentDetails[] = $row;
             // output every $tempRowCount rows
             if ($count % $tempRowCount == 0) {
                 self::writeDetailsToTable($exportTempTable, $componentDetails, $sqlColumns);
                 $componentDetails = array();
             }
         }
         $dao->free();
         if ($rowsThisIteration < self::EXPORT_ROW_COUNT) {
             $limitReached = TRUE;
         }
         $offset += $rowCount;
     }
     if ($exportTempTable) {
         self::writeDetailsToTable($exportTempTable, $componentDetails, $sqlColumns);
         // do merge same address and merge same household processing
         if ($mergeSameAddress) {
             self::mergeSameAddress($exportTempTable, $headerRows, $sqlColumns, $exportParams);
         }
         // merge the records if they have corresponding households
         if ($mergeSameHousehold) {
             self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyMOH);
             self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyHOH);
         }
         // if postalMailing option is checked, exclude contacts who are deceased, have
         // "Do not mail" privacy setting, or have no street address
         if (isset($exportParams['postal_mailing_export']['postal_mailing_export']) && $exportParams['postal_mailing_export']['postal_mailing_export'] == 1) {
             self::postalMailingFormat($exportTempTable, $headerRows, $sqlColumns, $exportMode);
         }
         // call export hook
         CRM_Utils_Hook::export($exportTempTable, $headerRows, $sqlColumns, $exportMode);
         // In order to be able to write a unit test against this function we need to suppress
         // the csv writing. In future hopefully the csv writing & the main processing will be in separate functions.
         if (empty($exportParams['suppress_csv_for_testing'])) {
             self::writeCSVFromTable($exportTempTable, $headerRows, $sqlColumns, $exportMode);
         }
         // delete the export temp table and component table
         $sql = "DROP TABLE IF EXISTS {$exportTempTable}";
         CRM_Core_DAO::executeQuery($sql);
         // Do not exit in test context.
         if (empty($exportParams['suppress_csv_for_testing'])) {
             CRM_Utils_System::civiExit();
         }
     } else {
         CRM_Core_Error::fatal(ts('No records to export'));
     }
 }