// CRM-7675
const EXPORT_ROW_COUNT = 100000;
+ protected static $relationshipReturnProperties = [];
+
/**
- * Get Querymode based on ExportMode
+ * Key representing the head of household in the relationship array.
*
- * @param int $exportMode
- * Export mode.
+ * e.g. 8_a_b.
*
- * @return string $Querymode
- * Query Mode
+ * @var string
*/
- public static function getQueryMode($exportMode) {
- $queryMode = CRM_Contact_BAO_Query::MODE_CONTACTS;
+ protected static $headOfHouseholdRelationshipKey;
- switch ($exportMode) {
- case CRM_Export_Form_Select::CONTRIBUTE_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_CONTRIBUTE;
- break;
-
- case CRM_Export_Form_Select::EVENT_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_EVENT;
- break;
-
- case CRM_Export_Form_Select::MEMBER_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_MEMBER;
- break;
-
- case CRM_Export_Form_Select::PLEDGE_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_PLEDGE;
- break;
+ /**
+ * Key representing the head of household in the relationship array.
+ *
+ * e.g. 8_a_b.
+ *
+ * @var string
+ */
+ protected static $memberOfHouseholdRelationshipKey;
- case CRM_Export_Form_Select::CASE_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_CASE;
- break;
+ /**
+ * Key representing the head of household in the relationship array.
+ *
+ * e.g. ['8_b_a' => 'Household Member Is', '8_a_b = 'Household Member Of'.....]
+ *
+ * @var
+ */
+ protected static $relationshipTypes = [];
- case CRM_Export_Form_Select::GRANT_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_GRANT;
- break;
+ /**
+ * @param $value
+ * @param $locationTypeFields
+ * @param $relationshipTypes
+ *
+ * @return array
+ */
+ protected static function setRelationshipReturnProperties($value, $locationTypeFields, $relationshipTypes) {
+ $locationTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Address', 'location_type_id');
+ $relPhoneTypeId = $relIMProviderId = NULL;
+ 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';
+ }
- case CRM_Export_Form_Select::ACTIVITY_EXPORT:
- $queryMode = CRM_Contact_BAO_Query::MODE_ACTIVITY;
- break;
+ if ($relationField == 'phone') {
+ $relPhoneTypeId = CRM_Utils_Array::value(4, $value);
+ }
+ elseif ($relationField == 'im') {
+ $relIMProviderId = CRM_Utils_Array::value(4, $value);
+ }
}
- return $queryMode;
+ 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);
+ }
+ }
+ if (in_array($relationField, $locationTypeFields) && is_numeric($relLocTypeId)) {
+ if ($relPhoneTypeId) {
+ self::$relationshipReturnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]]['phone-' . $relPhoneTypeId] = 1;
+ }
+ elseif ($relIMProviderId) {
+ self::$relationshipReturnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]]['im-' . $relIMProviderId] = 1;
+ }
+ else {
+ self::$relationshipReturnProperties[$relationshipTypes]['location'][$locationTypes[$relLocTypeId]][$relationField] = 1;
+ }
+ }
+ else {
+ self::$relationshipReturnProperties[$relationshipTypes][$relationField] = 1;
+ }
+ return array($relationField);
+ }
+
+ /**
+ * @return array
+ */
+ public static function getRelationshipReturnProperties() {
+ return self::relationshipReturnProperties;
}
/**
case CRM_Contact_BAO_Query::MODE_EVENT:
$paymentFields = TRUE;
$paymentTableId = 'participant_id';
- $extraReturnProperties = array();
break;
case CRM_Contact_BAO_Query::MODE_MEMBER:
$paymentFields = TRUE;
$paymentTableId = 'membership_id';
- $extraReturnProperties = array();
break;
case CRM_Contact_BAO_Query::MODE_PLEDGE:
- $extraReturnProperties = CRM_Pledge_BAO_Query::extraReturnProperties($queryMode);
$paymentFields = TRUE;
$paymentTableId = 'pledge_payment_id';
break;
case CRM_Contact_BAO_Query::MODE_CASE:
- $extraReturnProperties = CRM_Case_BAO_Query::extraReturnProperties($queryMode);
$paymentFields = FALSE;
$paymentTableId = '';
break;
default:
$paymentFields = FALSE;
$paymentTableId = '';
- $extraReturnProperties = array();
}
$extraProperties = array(
'paymentFields' => $paymentFields,
'paymentTableId' => $paymentTableId,
- 'extraReturnProperties' => $extraReturnProperties,
);
return $extraProperties;
}
$queryOperator = 'AND'
) {
+ $processor = new CRM_Export_BAO_ExportProcessor($exportMode, $queryOperator);
$returnProperties = array();
- $paymentFields = $selectedPaymentFields = FALSE;
+ $paymentFields = $selectedPaymentFields = $paymentTableId = FALSE;
$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(
+ self::$relationshipTypes = CRM_Contact_BAO_Relationship::getContactRelationshipType(
NULL,
NULL,
NULL,
'name',
FALSE
);
+ //also merge Head of Household
+ self::$memberOfHouseholdRelationshipKey = CRM_Utils_Array::key('Household Member of', self::$relationshipTypes);
+ self::$headOfHouseholdRelationshipKey = CRM_Utils_Array::key('Head of Household for', self::$relationshipTypes);
- $queryMode = self::getQueryMode($exportMode);
+ $queryMode = $processor->getQueryMode();
if ($fields) {
//construct return properties
);
foreach ($fields as $key => $value) {
- $relationField = NULL;
- $relationshipTypes = $fieldName = CRM_Utils_Array::value(1, $value);
+ $fieldName = CRM_Utils_Array::value(1, $value);
if (!$fieldName) {
continue;
}
- if (array_key_exists($relationshipTypes, $contactRelationshipTypes) && (!empty($value[2]) || !empty($value[4]))) {
- $relPhoneTypeId = $relIMProviderId = NULL;
- 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);
- }
- }
- 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;
- }
- }
- else {
- $returnProperties[$relationshipTypes][$relationField] = 1;
- }
- }
-
- if ($relationField) {
- // already handled.
+ if (array_key_exists($fieldName, self::$relationshipTypes) && (!empty($value[2]) || !empty($value[4]))) {
+ self::setRelationshipReturnProperties($value, $locationTypeFields, $fieldName);
+ // @todo we can later not add this to this array but maintain a separate array.
+ $returnProperties = array_merge($returnProperties, self::$relationshipReturnProperties);
}
elseif (is_numeric(CRM_Utils_Array::value(2, $value))) {
$locTypeId = $value[2];
}
}
else {
- $primary = TRUE;
+ $returnProperties = [];
$fields = CRM_Contact_BAO_Contact::exportableFields('All', TRUE, TRUE);
foreach ($fields as $key => $var) {
if ($key && (substr($key, 0, 6) != 'custom')) {
}
}
- 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);
- }
+ $returnProperties = array_merge($returnProperties, $processor->getAdditionalReturnProperties());
+ if ($queryMode != CRM_Contact_BAO_Query::MODE_CONTACTS) {
// unset non exportable fields for components
$nonExpoFields = array(
'groups',
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();
+ list($query, $select, $from, $where, $having) = $processor->runQuery($params, $order, $returnProperties);
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;
+ if (!array_key_exists($key, self::$relationshipTypes)) {
+ $returnProperties[self::$memberOfHouseholdRelationshipKey][$key] = $value;
+ $returnProperties[self::$headOfHouseholdRelationshipKey][$key] = $value;
}
}
- unset($returnProperties[$relationKeyMOH]['location_type']);
- unset($returnProperties[$relationKeyMOH]['im_provider']);
- unset($returnProperties[$relationKeyHOH]['location_type']);
- unset($returnProperties[$relationKeyHOH]['im_provider']);
+ unset($returnProperties[self::$memberOfHouseholdRelationshipKey]['location_type']);
+ unset($returnProperties[self::$memberOfHouseholdRelationshipKey]['im_provider']);
+ unset($returnProperties[self::$headOfHouseholdRelationshipKey]['location_type']);
+ unset($returnProperties[self::$headOfHouseholdRelationshipKey]['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');
- $dao = CRM_Core_DAO::executeQuery("
- SELECT contact_id FROM civicrm_activity_contact
- WHERE activity_id IN ( " . implode(',', $ids) . ") AND
- record_type_id = {$sourceID}
- ");
-
- 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}
- INNER JOIN civicrm_relationship crel ON crel.{$contactB} = contact_a.id AND crel.relationship_type_id = {$id}
- {$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 = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($relationQuery[$rel]->_select, "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();
- }
- }
+ list($relationQuery, $allRelContactArray) = self::buildRelatedContactArray($selectAll, $ids, $exportMode, $componentTable, $returnProperties, $queryMode);
// 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
// for CRM-3157 purposes
$i18n = CRM_Core_I18n::singleton();
- list($outputColumns, $headerRows, $sqlColumns, $metadata) = self::getExportStructureArrays($returnProperties, $query, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields);
+ list($outputColumns, $headerRows, $sqlColumns, $metadata) = self::getExportStructureArrays($returnProperties, $processor, $relationQuery, $selectedPaymentFields);
$limitReached = FALSE;
while (!$limitReached) {
}
}
- 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)) {
+ if (array_key_exists($field, self::$relationshipTypes)) {
$relDAO = CRM_Utils_Array::value($iterationDAO->contact_id, $allRelContactArray[$field]);
$relationQuery[$field]->convertToPseudoNames($relDAO);
self::fetchRelationshipDetails($relDAO, $value, $field, $row);
}
- 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 (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] = '';
+ $row[$field] = self::getTransformedFieldValue($field, $iterationDAO, $fieldValue, $i18n, $metadata, $selectedPaymentFields, $paymentDetails, $paymentTableId);
}
}
// where other header definitions take place.
$headerRows = array_merge($headerRows, $paymentHeaders);
foreach (array_keys($paymentHeaders) as $paymentHdr) {
- self::sqlColumnDefn($query, $sqlColumns, $paymentHdr);
+ self::sqlColumnDefn($processor, $sqlColumns, $paymentHdr);
}
}
// merge the records if they have corresponding households
if ($mergeSameHousehold) {
- self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyMOH);
- self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, $relationKeyHOH);
+ self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, self::$memberOfHouseholdRelationshipKey);
+ self::mergeSameHousehold($exportTempTable, $headerRows, $sqlColumns, self::$headOfHouseholdRelationshipKey);
}
// call export hook
}
/**
- * @param $query
+ * @param \CRM_Export_BAO_ExportProcessor $processor
* @param $sqlColumns
* @param $field
*/
- public static function sqlColumnDefn($query, &$sqlColumns, $field) {
+ public static function sqlColumnDefn($processor, &$sqlColumns, $field) {
if (substr($field, -4) == '_a_b' || substr($field, -4) == '_b_a') {
return;
}
+ $queryFields = $processor->getQueryFields();
$fieldName = CRM_Utils_String::munge(strtolower($field), '_', 64);
if ($fieldName == 'id') {
$lookUp = array('prefix_id', 'suffix_id');
// set the sql columns
- if (isset($query->_fields[$field]['type'])) {
- switch ($query->_fields[$field]['type']) {
+ if (isset($queryFields[$field]['type'])) {
+ switch ($queryFields[$field]['type']) {
case CRM_Utils_Type::T_INT:
case CRM_Utils_Type::T_BOOLEAN:
if (in_array($field, $lookUp)) {
break;
case CRM_Utils_Type::T_STRING:
- if (isset($query->_fields[$field]['maxlength'])) {
- $sqlColumns[$fieldName] = "$fieldName varchar({$query->_fields[$field]['maxlength']})";
+ if (isset($queryFields[$field]['maxlength'])) {
+ $sqlColumns[$fieldName] = "$fieldName varchar({$queryFields[$field]['maxlength']})";
}
else {
$sqlColumns[$fieldName] = "$fieldName varchar(255)";
}
else {
// set the sql columns for custom data
- if (isset($query->_fields[$field]['data_type'])) {
+ if (isset($queryFields[$field]['data_type'])) {
- switch ($query->_fields[$field]['data_type']) {
+ switch ($queryFields[$field]['data_type']) {
case 'String':
// May be option labels, which could be up to 512 characters
- $length = max(512, CRM_Utils_Array::value('text_length', $query->_fields[$field]));
+ $length = max(512, CRM_Utils_Array::value('text_length', $queryFields[$field]));
$sqlColumns[$fieldName] = "$fieldName varchar($length)";
break;
*/
public static function createTempTable(&$sqlColumns) {
//creating a temporary table for the search result that need be exported
- $exportTempTable = CRM_Core_DAO::createTempTableName('civicrm_export', TRUE);
+ $exportTempTable = CRM_Utils_SQL_TempTable::build()->setDurable()->setCategory('export')->getName();
// also create the sql table
$sql = "DROP TABLE IF EXISTS {$exportTempTable}";
* Manipulate header rows for relationship fields.
*
* @param $headerRows
- * @param $contactRelationshipTypes
*/
- public static function manipulateHeaderRows(&$headerRows, $contactRelationshipTypes) {
+ public static function manipulateHeaderRows(&$headerRows) {
foreach ($headerRows as & $header) {
$split = explode('-', $header);
- if ($relationTypeName = CRM_Utils_Array::value($split[0], $contactRelationshipTypes)) {
+ if ($relationTypeName = CRM_Utils_Array::value($split[0], self::$relationshipTypes)) {
$split[0] = $relationTypeName;
$header = implode('-', $split);
}
* @param array $headerRows
* @param array $sqlColumns
* Columns to go in the temp table.
- * @param CRM_Contact_BAO_Query $query
+ * @param \CRM_Export_BAO_ExportProcessor $processor
* @param array|string $value
* @param array $phoneTypes
* @param array $imProviders
- * @param array $contactRelationshipTypes
* @param string $relationQuery
* @param array $selectedPaymentFields
* @return array
*/
- public static function setHeaderRows($field, $headerRows, $sqlColumns, $query, $value, $phoneTypes, $imProviders, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields) {
+ public static function setHeaderRows($field, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders, $relationQuery, $selectedPaymentFields) {
+ $queryFields = $processor->getQueryFields();
// Split campaign into 2 fields for id and title
if (substr($field, -14) == 'campaign_title') {
$headerRows[] = ts('Campaign Title');
elseif (substr($field, -11) == 'campaign_id') {
$headerRows[] = ts('Campaign ID');
}
- elseif (isset($query->_fields[$field]['title'])) {
- $headerRows[] = $query->_fields[$field]['title'];
+ elseif (isset($queryFields[$field]['title'])) {
+ $headerRows[] = $queryFields[$field]['title'];
}
elseif ($field == 'phone_type_id') {
$headerRows[] = ts('Phone Type');
elseif ($field == 'provider_id') {
$headerRows[] = ts('IM Service Provider');
}
- elseif (substr($field, 0, 5) == 'case_' && $query->_fields['case'][$field]['title']) {
- $headerRows[] = $query->_fields['case'][$field]['title'];
- }
- elseif (array_key_exists($field, $contactRelationshipTypes)) {
+ elseif (array_key_exists($field, self::$relationshipTypes)) {
foreach ($value as $relationField => $relationValue) {
// below block is same as primary block (duplicate)
if (isset($relationQuery[$field]->_fields[$relationField]['title'])) {
$headerRows[] = $headerName;
- self::sqlColumnDefn($query, $sqlColumns, $headerName);
+ self::sqlColumnDefn($processor, $sqlColumns, $headerName);
}
elseif ($relationField == 'phone_type_id') {
$headerName = $field . '-' . 'Phone Type';
$headerRows[] = $headerName;
- self::sqlColumnDefn($query, $sqlColumns, $headerName);
+ self::sqlColumnDefn($processor, $sqlColumns, $headerName);
}
elseif ($relationField == 'provider_id') {
$headerName = $field . '-' . 'Im Service Provider';
$headerRows[] = $headerName;
- self::sqlColumnDefn($query, $sqlColumns, $headerName);
+ self::sqlColumnDefn($processor, $sqlColumns, $headerName);
}
elseif ($relationField == 'state_province_id') {
$headerName = $field . '-' . 'state_province_id';
$headerRows[] = $headerName;
- self::sqlColumnDefn($query, $sqlColumns, $headerName);
+ self::sqlColumnDefn($processor, $sqlColumns, $headerName);
}
elseif (is_array($relationValue) && $relationField == 'location') {
// fix header for location type case
}
$headerName = $field . '-' . $hdr;
$headerRows[] = $headerName;
- self::sqlColumnDefn($query, $sqlColumns, $headerName);
+ self::sqlColumnDefn($processor, $sqlColumns, $headerName);
}
}
}
}
- self::manipulateHeaderRows($headerRows, $contactRelationshipTypes);
+ self::manipulateHeaderRows($headerRows);
}
elseif ($selectedPaymentFields && array_key_exists($field, self::componentPaymentFields())) {
$headerRows[] = CRM_Utils_Array::value($field, self::componentPaymentFields());
$headerRows[] = $field;
}
- self::sqlColumnDefn($query, $sqlColumns, $field);
+ self::sqlColumnDefn($processor, $sqlColumns, $field);
return array($headerRows, $sqlColumns);
}
* as a step on the refactoring path rather than how it should be.
*
* @param array $returnProperties
- * @param CRM_Contact_BAO_Contact $query
- * @param array $contactRelationshipTypes
+ * @param \CRM_Export_BAO_ExportProcessor $processor
* @param string $relationQuery
* @param array $selectedPaymentFields
* @return array
* - b) this code is old & outdated. Submit your answers to circular bin or better
* yet find a way to comment them for posterity.
*/
- public static function getExportStructureArrays($returnProperties, $query, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields) {
+ public static function getExportStructureArrays($returnProperties, $processor, $relationQuery, $selectedPaymentFields) {
$metadata = $headerRows = $outputColumns = $sqlColumns = array();
$phoneTypes = CRM_Core_PseudoConstant::get('CRM_Core_DAO_Phone', 'phone_type_id');
$imProviders = CRM_Core_PseudoConstant::get('CRM_Core_DAO_IM', 'provider_id');
+ $queryFields = $processor->getQueryFields();
foreach ($returnProperties as $key => $value) {
if ($key != 'location' || !is_array($value)) {
$outputColumns[$key] = $value;
- list($headerRows, $sqlColumns) = self::setHeaderRows($key, $headerRows, $sqlColumns, $query, $value, $phoneTypes, $imProviders, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields);
+ list($headerRows, $sqlColumns) = self::setHeaderRows($key, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders, $relationQuery, $selectedPaymentFields);
}
else {
foreach ($value as $locationType => $locationFields) {
$type = explode('-', $locationFieldName);
$actualDBFieldName = $type[0];
- $outputFieldName = $locationType . '-' . $query->_fields[$actualDBFieldName]['title'];
+ $outputFieldName = $locationType . '-' . $queryFields[$actualDBFieldName]['title'];
$daoFieldName = CRM_Utils_String::munge($locationType) . '-' . $actualDBFieldName;
if (!empty($type[1])) {
// Warning: shame inducing hack.
$metadata[$daoFieldName]['pseudoconstant']['var'] = 'imProviders';
}
- self::sqlColumnDefn($query, $sqlColumns, $outputFieldName);
- list($headerRows, $sqlColumns) = self::setHeaderRows($outputFieldName, $headerRows, $sqlColumns, $query, $value, $phoneTypes, $imProviders, $contactRelationshipTypes, $relationQuery, $selectedPaymentFields);
+ self::sqlColumnDefn($processor, $sqlColumns, $outputFieldName);
+ list($headerRows, $sqlColumns) = self::setHeaderRows($outputFieldName, $headerRows, $sqlColumns, $processor, $value, $phoneTypes, $imProviders, $relationQuery, $selectedPaymentFields);
if ($actualDBFieldName == 'country' || $actualDBFieldName == 'world_region') {
$metadata[$daoFieldName] = array('context' => 'country');
}
}
}
+ /**
+ * Get the ids that we want to get related contact details for.
+ *
+ * @param array $ids
+ * @param int $exportMode
+ *
+ * @return array
+ */
+ protected static function getIDsForRelatedContact($ids, $exportMode) {
+ if ($exportMode == CRM_Export_Form_Select::CONTACT_EXPORT) {
+ return $ids;
+ }
+ if ($exportMode == CRM_Export_Form_Select::ACTIVITY_EXPORT) {
+ $relIDs = [];
+ $sourceID = CRM_Core_PseudoConstant::getKey('CRM_Activity_BAO_ActivityContact', 'record_type_id', 'Activity Source');
+ $dao = CRM_Core_DAO::executeQuery("
+ SELECT contact_id FROM civicrm_activity_contact
+ WHERE activity_id IN ( " . implode(',', $ids) . ") AND
+ record_type_id = {$sourceID}
+ ");
+
+ while ($dao->fetch()) {
+ $relIDs[] = $dao->contact_id;
+ }
+ return $relIDs;
+ }
+ $component = self::exportComponent($exportMode);
+
+ if ($exportMode == CRM_Export_Form_Select::CASE_EXPORT) {
+ return CRM_Case_BAO_Case::retrieveContactIdsByCaseId($ids);
+ }
+ else {
+ return CRM_Core_DAO::getContactIDsFromComponent($ids, $component);
+ }
+ }
+
+ /**
+ * @param $selectAll
+ * @param $ids
+ * @param $exportMode
+ * @param $componentTable
+ * @param $returnProperties
+ * @param $queryMode
+ * @return array
+ */
+ protected static function buildRelatedContactArray($selectAll, $ids, $exportMode, $componentTable, $returnProperties, $queryMode) {
+ $allRelContactArray = $relationQuery = array();
+
+ foreach (self::$relationshipTypes 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';
+ }
+ $relIDs = self::getIDsForRelatedContact($ids, $exportMode);
+
+ $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}
+ INNER JOIN civicrm_relationship crel ON crel.{$contactB} = contact_a.id AND crel.relationship_type_id = {$id}
+ {$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 = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($relationQuery[$rel]->_select, "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();
+ }
+ }
+ return array($relationQuery, $allRelContactArray);
+ }
+
+ /**
+ * @param $field
+ * @param $iterationDAO
+ * @param $fieldValue
+ * @param $i18n
+ * @param $metadata
+ * @param $selectedPaymentFields
+ * @param $paymentDetails
+ * @param string $paymentTableId
+ * @return string
+ */
+ protected static function getTransformedFieldValue($field, $iterationDAO, $fieldValue, $i18n, $metadata, $selectedPaymentFields, $paymentDetails, $paymentTableId) {
+
+ if ($field == 'id') {
+ return $iterationDAO->contact_id;
+ // special case for calculated field
+ }
+ elseif ($field == 'source_contact_id') {
+ return $iterationDAO->contact_id;
+ }
+ elseif ($field == 'pledge_balance_amount') {
+ return $iterationDAO->pledge_amount - $iterationDAO->pledge_total_paid;
+ // special case for calculated field
+ }
+ elseif ($field == 'pledge_next_pay_amount') {
+ return $iterationDAO->pledge_next_pay_amount + $iterationDAO->pledge_outstanding_amount;
+ }
+ elseif (isset($fieldValue) &&
+ $fieldValue != ''
+ ) {
+ //check for custom data
+ if ($cfID = CRM_Core_BAO_CustomField::getKeyID($field)) {
+ return CRM_Core_BAO_CustomField::displayValue($fieldValue, $cfID);
+ }
+
+ elseif (in_array($field, array(
+ 'email_greeting',
+ 'postal_greeting',
+ 'addressee',
+ ))) {
+ //special case for greeting replacement
+ $fldValue = "{$field}_display";
+ return $iterationDAO->$fldValue;
+ }
+ else {
+ //normal fields with a touch of CRM-3157
+ switch ($field) {
+ case 'country':
+ case 'world_region':
+ return $i18n->crm_translate($fieldValue, array('context' => 'country'));
+
+ case 'state_province':
+ return $i18n->crm_translate($fieldValue, array('context' => 'province'));
+
+ case 'gender':
+ case 'preferred_communication_method':
+ case 'preferred_mail_format':
+ case 'communication_style':
+ return $i18n->crm_translate($fieldValue);
+
+ 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'])) {
+ return $i18n->crm_translate($fieldValue, $metadata[$field]);
+ }
+ 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'];
+ if ($varName === 'imProviders') {
+ return CRM_Core_PseudoConstant::getLabel('CRM_Core_DAO_IM', 'provider_id', $fieldValue);
+ }
+ if ($varName === 'phoneTypes') {
+ return CRM_Core_PseudoConstant::getLabel('CRM_Core_DAO_Phone', 'phone_type_id', $fieldValue);
+ }
+ }
+
+ }
+ return $fieldValue;
+ }
+ }
+ }
+ 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',
+ );
+ return CRM_Utils_Array::value($payFieldMapper[$field], $paymentData, '');
+ }
+ else {
+ // if field is empty or null
+ return '';
+ }
+ }
+
}