4 * Class CRM_Core_DAOTest
8 class CRM_Export_BAO_ExportTest
extends CiviUnitTestCase
{
11 * Contact IDs created for testing.
15 protected $contactIDs = [];
18 * Contribution IDs created for testing.
22 protected $contributionIDs = [];
25 * Contribution IDs created for testing.
29 protected $activityIDs = [];
32 * Contribution IDs created for testing.
36 protected $membershipIDs = [];
39 * Master Address ID created for testing.
43 protected $masterAddressID;
45 protected $locationTypes = [];
48 * Processor generated in test.
50 * @var \CRM_Export_BAO_ExportProcessor
55 * Csv output from export.
57 * @var \League\Csv\Reader
66 public function tearDown() {
67 $this->quickCleanUpFinancialEntities();
72 'civicrm_relationship',
75 'civicrm_case_contact',
76 'civicrm_case_activity',
79 if (!empty($this->locationTypes
)) {
80 $this->callAPISuccess('LocationType', 'delete', ['id' => $this->locationTypes
['Whare Kai']['id']]);
81 $this->callAPISuccess('LocationType', 'create', ['id' => $this->locationTypes
['Main']['id'], 'name' => 'Main']);
83 if ($this->processor
&& $this->processor
->getTemporaryTable()) {
84 // delete the export temp table
85 CRM_Core_DAO
::executeQuery("DROP TABLE IF EXISTS " . $this->processor
->getTemporaryTable());
91 * Basic test to ensure the exportComponents function completes without error.
93 * @throws \CRM_Core_Exception
94 * @throws \League\Csv\Exception
96 public function testExportComponentsNull() {
97 $this->doExportTest([]);
101 * Basic test to ensure the exportComponents function can export selected fields for contribution.
103 * @throws \CRM_Core_Exception
105 public function testExportComponentsContribution() {
106 $this->setUpContributionExportData();
108 ['Individual', 'first_name'],
109 ['Individual', 'last_name'],
110 ['Contribution', 'receive_date'],
111 ['Contribution', 'contribution_source'],
112 ['Individual', 'street_address', 1],
113 ['Individual', 'city', 1],
114 ['Individual', 'country', 1],
115 ['Individual', 'email', 1],
116 ['Contribution', 'trxn_id'],
119 $this->doExportTest([
120 'ids' => $this->contributionIDs
,
121 'order' => 'receive_date desc',
122 'fields' => $selectedFields,
123 'exportMode' => CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
124 'componentClause' => 'civicrm_contribution.id IN ( ' . implode(',', $this->contributionIDs
) . ')',
129 * Basic test to ensure the exportComponents function can export with soft credits enabled.
131 * @throws \CRM_Core_Exception
132 * @throws \League\Csv\Exception
134 public function testExportComponentsContributionSoftCredits() {
135 $this->setUpContributionExportData();
136 $this->callAPISuccess('ContributionSoft', 'create', ['contact_id' => $this->contactIDs
[1], 'contribution_id' => $this->contributionIDs
[0], 'amount' => 5]);
138 ['receive_date_low', '=', '20190101000000', 0, 0],
139 ['receive_date_high', '=', '20191231235959', 0, 0],
140 ['contribution_amount_low', '=', '1', 0, 0],
141 ['contribution_amount_high', '=', '10000000', 0, 0],
142 ['contribution_test', '=', '0', 0, 0],
143 ['contribution_or_softcredits', '=', 'both', 0, 0],
146 $this->startCapturingOutput();
148 CRM_Export_BAO_Export
::exportComponents(
150 $this->contributionIDs
,
155 CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
156 'civicrm_contribution.id IN ( ' . implode(',', $this->contributionIDs
) . ')',
161 'exportOption' => CRM_Export_Form_Select
::CONTACT_EXPORT
,
165 catch (CRM_Core_Exception_PrematureExitException
$e) {
167 $csv = $this->captureOutputToCSV();
168 $this->assertEquals(array_merge($this->getBasicHeaderDefinition(FALSE), $this->getContributeHeaderDefinition()), $csv->getHeader());
170 $rows = $csv->getRecords();
171 foreach ($rows as $row) {
172 if ($rowNumber === 1) {
173 $this->assertEquals(95, $row['Net Amount']);
174 $this->assertEquals('', $row['Soft Credit Amount']);
176 if ($rowNumber === 2) {
177 $this->assertEquals(95, $row['Net Amount']);
178 $this->assertEquals(5, $row['Soft Credit Amount']);
179 $this->assertEquals('Anderson, Anthony', $row['Soft Credit For']);
180 $this->assertEquals($this->contributionIDs
[0], $row['Soft Credit For Contribution ID']);
184 $this->assertEquals(4, $rowNumber);
185 // Ideally we would use a randomised temp table name & use generic temp cleanup for cleanup - but
186 // for now just make sure we don't leave a mess.
187 CRM_Core_DAO
::executeQuery('DROP TABLE IF EXISTS contribution_search_scredit_combined');
192 * Basic test to ensure the exportComponents function can export selected fields for contribution.
194 public function testExportComponentsMembership() {
195 $this->setUpMembershipExportData();
196 list($tableName) = CRM_Export_BAO_Export
::exportComponents(
198 $this->membershipIDs
,
203 CRM_Export_Form_Select
::MEMBER_EXPORT
,
204 'civicrm_membership.id IN ( ' . implode(',', $this->membershipIDs
) . ')',
209 'exportOption' => CRM_Export_Form_Select
::MEMBER_EXPORT
,
210 'suppress_csv_for_testing' => TRUE,
214 $dao = CRM_Core_DAO
::executeQuery('SELECT * from ' . $tableName);
216 $this->assertEquals('100.00', $dao->componentpaymentfield_total_amount
);
217 $this->assertEquals('Completed', $dao->componentpaymentfield_contribution_status
);
218 $this->assertEquals('Credit Card', $dao->componentpaymentfield_payment_instrument
);
219 $this->assertEquals(1, $dao->N
);
221 // delete the export temp table and component table
222 $sql = "DROP TABLE IF EXISTS {$tableName}";
223 CRM_Core_DAO
::executeQuery($sql);
227 * Basic test to ensure the exportComponents function can export selected fields for contribution.
229 public function testExportComponentsActivity() {
230 $this->setUpActivityExportData();
232 ['Individual', 'display_name'],
233 ['Individual', '5_a_b', 'display_name'],
236 list($tableName) = CRM_Export_BAO_Export
::exportComponents(
240 '`activity_date_time` desc',
243 CRM_Export_Form_Select
::ACTIVITY_EXPORT
,
244 'civicrm_activity.id IN ( ' . implode(',', $this->activityIDs
) . ')',
249 'exportOption' => CRM_Export_Form_Select
::ACTIVITY_EXPORT
,
250 'suppress_csv_for_testing' => TRUE,
254 // delete the export temp table and component table
255 $sql = "DROP TABLE IF EXISTS {$tableName}";
256 CRM_Core_DAO
::executeQuery($sql);
260 * Test the function that extracts the arrays used to structure the output.
262 * The keys in the output fields array should by matched by field aliases in the sql query (with
263 * exceptions of course - currently country is one - although maybe a future refactor can change that!).
265 * We are trying to move towards simpler processing in the per row iteration as that may be
266 * repeated 100,000 times and in general we should simply be able to match the query fields to
267 * our expected rows & do a little pseudoconstant mapping.
269 public function testGetExportStructureArrays() {
270 // This is how return properties are formatted internally within the function for passing to the BAO query.
271 $returnProperties = [
275 'contribution_source' => 1,
278 'street_address' => 1,
289 'contribution_id' => 1,
292 $contactRelationshipTypes = CRM_Contact_BAO_Relationship
::getContactRelationshipType(
302 $query = new CRM_Contact_BAO_Query([], $returnProperties, NULL,
303 FALSE, FALSE, CRM_Contact_BAO_Query
::MODE_CONTRIBUTE
,
304 FALSE, TRUE, TRUE, NULL, 'AND'
307 list($select) = $query->query();
308 $pattern = '/as `?([^`,]*)/';
309 $queryFieldAliases = [];
310 preg_match_all($pattern, $select, $queryFieldAliases, PREG_PATTERN_ORDER
);
311 $processor = new CRM_Export_BAO_ExportProcessor(CRM_Contact_BAO_Query
::MODE_CONTRIBUTE
, NULL, 'AND');
312 $processor->setQueryFields($query->_fields
);
314 list($outputFields) = CRM_Export_BAO_Export
::getExportStructureArrays($returnProperties, $processor, $contactRelationshipTypes, '');
315 foreach (array_keys($outputFields) as $fieldAlias) {
316 if ($fieldAlias == 'Home-country') {
317 $this->assertTrue(in_array($fieldAlias . '_id', $queryFieldAliases[1]), 'Country is subject to some funky translate so we make sure country id is present');
320 $this->assertTrue(in_array($fieldAlias, $queryFieldAliases[1]), 'looking for field ' . $fieldAlias . ' in generaly the alias fields need to match the outputfields');
327 * Set up some data for us to do testing on.
329 public function setUpContributionExportData() {
330 $this->setUpContactExportData();
331 $this->contributionIDs
[] = $this->contributionCreate(['contact_id' => $this->contactIDs
[0], 'trxn_id' => 'null', 'invoice_id' => 'null']);
332 $this->contributionIDs
[] = $this->contributionCreate(['contact_id' => $this->contactIDs
[1], 'trxn_id' => 'null', 'invoice_id' => 'null']);
336 * Set up some data for us to do testing on.
338 public function setUpMembershipExportData() {
339 $this->setUpContactExportData();
340 // Create an extra so we don't get false passes due to 1
341 $this->contactMembershipCreate(['contact_id' => $this->contactIDs
[0]]);
342 $this->membershipIDs
[] = $this->contactMembershipCreate(['contact_id' => $this->contactIDs
[0]]);
343 $this->setUpContributionExportData();
344 $this->callAPISuccess('membership_payment', 'create', [
345 'contribution_id' => $this->contributionIDs
[0],
346 'membership_id' => $this->membershipIDs
[0],
348 $this->callAPISuccess('LineItem', 'get', [
349 'entity_table' => 'civicrm_membership',
350 'membership_id' => $this->membershipIDs
[0],
351 'api.LineItem.create' => ['contribution_id' => $this->contributionIDs
[0]],
356 * Set up data to test case export.
358 public function setupCaseExportData() {
359 $contactID1 = $this->individualCreate();
360 $contactID2 = $this->individualCreate([], 1);
362 $case = $this->callAPISuccess('case', 'create', [
365 'contact_id' => $contactID1,
367 $this->callAPISuccess('CaseContact', 'create', [
368 'case_id' => $case['id'],
369 'contact_id' => $contactID2,
374 * Set up some data for us to do testing on.
376 public function setUpActivityExportData() {
377 $this->setUpContactExportData();
378 $this->activityIDs
[] = $this->activityCreate(['contact_id' => $this->contactIDs
[0]])['id'];
382 * Set up some data for us to do testing on.
384 public function setUpContactExportData() {
385 $this->contactIDs
[] = $contactA = $this->individualCreate(['gender_id' => 'Female']);
386 // Create address for contact A.
388 'contact_id' => $contactA,
389 'location_type_id' => 'Home',
390 'street_address' => 'Ambachtstraat 23',
391 'postal_code' => '6971 BN',
392 'country_id' => '1152',
396 $result = $this->callAPISuccess('address', 'create', $params);
397 $addressId = $result['id'];
399 $this->callAPISuccess('email', 'create', [
400 'id' => $this->callAPISuccessGetValue('Email', ['contact_id' => $params['contact_id'], 'return' => 'id']),
401 'location_type_id' => 'Home',
402 'email' => 'home@example.com',
405 $this->callAPISuccess('email', 'create', ['contact_id' => $params['contact_id'], 'location_type_id' => 'Work', 'email' => 'work@example.com', 'is_primary' => 0]);
407 $params['is_primary'] = 0;
408 $params['location_type_id'] = 'Work';
409 $this->callAPISuccess('address', 'create', $params);
410 $this->contactIDs
[] = $contactB = $this->individualCreate();
412 $this->callAPISuccess('address', 'create', [
413 'contact_id' => $contactB,
414 'location_type_id' => "Home",
415 'master_id' => $addressId,
417 $this->masterAddressID
= $addressId;
422 * Test variants of primary address exporting.
424 * @param int $isPrimaryOnly
426 * @dataProvider getBooleanDataProvider
427 * @throws \CRM_Core_Exception
428 * @throws \League\Csv\Exception
430 public function testExportPrimaryAddress($isPrimaryOnly) {
431 \Civi
::settings()->set('searchPrimaryDetailsOnly', $isPrimaryOnly);
432 $this->setUpContactExportData();
434 $selectedFields = [['Individual', 'email', ' '], ['Individual', 'email', '1'], ['Individual', 'email', '2']];
435 $this->doExportTest([
437 'params' => [['email', 'LIKE', 'c', 0, 1]],
438 'fields' => $selectedFields,
439 'componentClause' => "contact_a.id IN ({$this->contactIDs[0]}, {$this->contactIDs[1]})",
443 $row = $this->csv
->fetchOne();
444 $this->assertEquals([
445 'Email' => 'home@example.com',
446 'Home-Email' => 'home@example.com',
447 'Work-Email' => 'work@example.com',
449 $this->assertEquals(2, count($this->csv
));
450 \Civi
::settings()->set('searchPrimaryDetailsOnly', FALSE);
454 * Test that when exporting a pseudoField it is reset for NULL entries.
456 * ie. we have a contact WITH a gender & one without - make sure the latter one
457 * does NOT retain the gender of the former.
459 * @throws \CRM_Core_Exception
461 public function testExportPseudoField() {
462 $this->setUpContactExportData();
463 $selectedFields = [['Individual', 'gender_id']];
464 list($tableName, $sqlColumns) = $this->doExport($selectedFields, $this->contactIDs
);
465 $this->assertEquals('Female,', CRM_Core_DAO
::singleValueQuery("SELECT GROUP_CONCAT(gender_id) FROM {$tableName}"));
469 * Test that when exporting a pseudoField it is reset for NULL entries.
471 * This is specific to the example in CRM-14398
473 public function testExportPseudoFieldCampaign() {
474 $this->setUpContributionExportData();
475 $campaign = $this->callAPISuccess('Campaign', 'create', ['title' => 'Big campaign']);
476 $this->callAPISuccess('Contribution', 'create', ['campaign_id' => 'Big_campaign', 'id' => $this->contributionIDs
[0]]);
477 $selectedFields = [['Individual', 'gender_id'], ['Contribution', 'contribution_campaign_title']];
478 list($tableName, $sqlColumns) = CRM_Export_BAO_Export
::exportComponents(
480 $this->contactIDs
[1],
485 CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
486 "contact_a.id IN (" . implode(",", $this->contactIDs
) . ")",
491 'suppress_csv_for_testing' => TRUE,
494 $this->assertEquals('Big campaign,', CRM_Core_DAO
::singleValueQuery("SELECT GROUP_CONCAT(contribution_campaign_title) FROM {$tableName}"));
498 * Test exporting relationships.
500 * @throws \CRM_Core_Exception
501 * @throws \League\Csv\Exception
503 public function testExportRelationships() {
504 $organization1 = $this->organizationCreate(['organization_name' => 'Org 1', 'legal_name' => 'pretty legal', 'contact_source' => 'friend who took a law paper once']);
505 $organization2 = $this->organizationCreate(['organization_name' => 'Org 2', 'legal_name' => 'well dodgey']);
506 $contact1 = $this->individualCreate(['employer_id' => $organization1, 'first_name' => 'one']);
507 $contact2 = $this->individualCreate(['employer_id' => $organization2, 'first_name' => 'one']);
508 $employerRelationshipTypeID = $this->callAPISuccessGetValue('RelationshipType', ['return' => 'id', 'label_a_b' => 'Employee of']);
510 ['Individual', 'first_name', ''],
511 ['Individual', $employerRelationshipTypeID . '_a_b', 'organization_name', ''],
512 ['Individual', $employerRelationshipTypeID . '_a_b', 'legal_name', ''],
513 ['Individual', $employerRelationshipTypeID . '_a_b', 'contact_source', ''],
515 $this->doExportTest([
516 'ids' => [$contact1, $contact2],
517 'componentClause' => "contact_a.id IN ( $contact1, $contact2 )",
518 'fields' => $selectedFields,
521 $row = $this->csv
->fetchOne();
522 $this->assertEquals('one', $row['First Name']);
523 $this->assertEquals('Org 1', $row['Employee of-Organization Name']);
524 $this->assertEquals('pretty legal', $row['Employee of-Legal Name']);
525 $this->assertEquals('friend who took a law paper once', $row['Employee of-Contact Source']);
527 $row = $this->csv
->fetchOne(1);
528 $this->assertEquals('Org 2', $row['Employee of-Organization Name']);
529 $this->assertEquals('well dodgey', $row['Employee of-Legal Name']);
533 * Test exporting relationships.
535 * This is to ensure that CRM-13995 remains fixed.
537 * @dataProvider getBooleanDataProvider
539 * @param bool $includeHouseHold
541 * @throws \CRM_Core_Exception
543 public function testExportRelationshipsMergeToHousehold($includeHouseHold) {
544 list($householdID, $houseHoldTypeID) = $this->setUpHousehold();
546 if ($includeHouseHold) {
547 $this->contactIDs
[] = $householdID;
550 ['Individual', $houseHoldTypeID . '_a_b', 'state_province', ''],
551 ['Individual', $houseHoldTypeID . '_a_b', 'city', ''],
552 ['Individual', 'city', ''],
553 ['Individual', 'state_province', ''],
554 ['Individual', 'contact_source', ''],
556 list($tableName, $sqlColumns, $headerRows) = CRM_Export_BAO_Export
::exportComponents(
563 CRM_Export_Form_Select
::CONTACT_EXPORT
,
564 "contact_a.id IN (" . implode(",", $this->contactIDs
) . ")",
569 'suppress_csv_for_testing' => TRUE,
572 $dao = CRM_Core_DAO
::executeQuery("SELECT * FROM {$tableName}");
573 while ($dao->fetch()) {
574 $this->assertEquals(1, $dao->N
);
575 $this->assertEquals('Portland', $dao->city
);
576 $this->assertEquals('ME', $dao->state_province
);
577 $this->assertEquals($householdID, $dao->civicrm_primary_id
);
578 $this->assertEquals($householdID, $dao->civicrm_primary_id
);
579 $this->assertEquals('household sauce', $dao->contact_source
);
582 $this->assertEquals([
585 2 => 'Contact Source',
590 'city' => 'city varchar(64)',
591 'state_province' => 'state_province varchar(64)',
592 'civicrm_primary_id' => 'civicrm_primary_id varchar(16)',
593 'contact_source' => 'contact_source varchar(255)',
598 * Test exporting relationships.
600 public function testExportRelationshipsMergeToHouseholdAllFields() {
601 list($householdID) = $this->setUpHousehold();
602 list($tableName) = CRM_Export_BAO_Export
::exportComponents(
609 CRM_Export_Form_Select
::CONTACT_EXPORT
,
610 "contact_a.id IN (" . implode(",", $this->contactIDs
) . ")",
615 'suppress_csv_for_testing' => TRUE,
618 $dao = CRM_Core_DAO
::executeQuery("SELECT * FROM {$tableName}");
619 while ($dao->fetch()) {
620 $this->assertEquals('Unit Test household', $dao->display_name
);
621 $this->assertEquals('Portland', $dao->city
);
622 $this->assertEquals('ME', $dao->state_province
);
623 $this->assertEquals($householdID, $dao->civicrm_primary_id
);
624 $this->assertEquals($householdID, $dao->civicrm_primary_id
);
625 $this->assertEquals('Unit Test household', $dao->addressee
);
626 $this->assertEquals(1, $dao->N
);
631 * Test master_address_id field.
633 public function testExportCustomData() {
634 $this->setUpContactExportData();
636 $customData = $this->entityCustomGroupWithSingleFieldCreate(__FUNCTION__
, 'ContactTest.php');
638 $this->callAPISuccess('Contact', 'create', [
639 'id' => $this->contactIDs
[1],
640 'custom_' . $customData['custom_field_id'] => 'BlahdeBlah',
641 'api.Address.create' => ['location_type_id' => 'Billing', 'city' => 'Waipu'],
644 ['Individual', 'city', CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Address', 'location_type_id', 'Billing')],
645 ['Individual', 'custom_1'],
648 list($tableName, $sqlColumns) = $this->doExport($selectedFields, $this->contactIDs
[1]);
649 $this->assertEquals([
650 'billing_city' => 'billing_city varchar(64)',
651 'custom_1' => 'custom_1 varchar(255)',
654 $dao = CRM_Core_DAO
::executeQuery('SELECT * FROM ' . $tableName);
655 while ($dao->fetch()) {
656 $this->assertEquals('BlahdeBlah', $dao->custom_1
);
657 $this->assertEquals('Waipu', $dao->billing_city
);
662 * Attempt to do a fairly full export of location data.
664 * @throws \CRM_Core_Exception
665 * @throws \League\Csv\Exception
667 public function testExportIMData() {
668 // Use default providers.
669 $providers = ['AIM', 'GTalk', 'Jabber', 'MSN', 'Skype', 'Yahoo'];
670 // Main sure labels are not all anglo chars.
671 $this->diversifyLocationTypes();
673 $locationTypes = ['Billing' => 'Billing', 'Home' => 'Home', 'Main' => 'Méin', 'Other' => 'Other', 'Whare Kai' => 'Whare Kai'];
675 $this->contactIDs
[] = $this->individualCreate();
676 $this->contactIDs
[] = $this->individualCreate();
677 $this->contactIDs
[] = $this->householdCreate();
678 $this->contactIDs
[] = $this->organizationCreate();
679 foreach ($this->contactIDs
as $contactID) {
680 foreach ($providers as $provider) {
681 foreach ($locationTypes as $locationName => $locationLabel) {
682 $this->callAPISuccess('IM', 'create', [
683 'contact_id' => $contactID,
684 'location_type_id' => $locationName,
685 'provider_id' => $provider,
686 'name' => $locationName . $provider . $contactID,
693 $this->contactIDs
[1] => ['label' => 'Spouse of'],
694 $this->contactIDs
[2] => ['label' => 'Household Member of'],
695 $this->contactIDs
[3] => ['label' => 'Employee of'],
698 foreach ($relationships as $contactID => $relationshipType) {
699 $relationshipTypeID = $this->callAPISuccess('RelationshipType', 'getvalue', ['label_a_b' => $relationshipType['label'], 'return' => 'id']);
700 $result = $this->callAPISuccess('Relationship', 'create', [
701 'contact_id_a' => $this->contactIDs
[0],
702 'relationship_type_id' => $relationshipTypeID,
703 'contact_id_b' => $contactID,
705 $relationships[$contactID]['id'] = $result['id'];
706 $relationships[$contactID]['relationship_type_id'] = $relationshipTypeID;
709 $fields = [['Individual', 'contact_id']];
710 // ' ' denotes primary location type.
711 foreach (array_keys(array_merge($locationTypes, [' ' => ['Primary']])) as $locationType) {
715 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'location_type_id', $locationType),
717 foreach ($relationships as $contactID => $relationship) {
720 $relationship['relationship_type_id'] . '_a_b',
722 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'location_type_id', $locationType),
725 foreach ($providers as $provider) {
729 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'location_type_id', $locationType),
730 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'provider_id', $provider),
732 foreach ($relationships as $contactID => $relationship) {
735 $relationship['relationship_type_id'] . '_a_b',
737 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'location_type_id', $locationType),
738 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'provider_id', $provider),
743 $this->doExportTest(['fields' => $fields, 'ids' => [$this->contactIDs
[0]]]);
745 foreach ($this->csv
->getRecords() as $row) {
746 $id = $row['contact_id'];
747 $this->assertEquals('AIM', $row['Billing-IM Provider']);
748 $this->assertEquals('AIM', $row['Whare Kai-IM Provider']);
749 $this->assertEquals('BillingJabber' . $id, $row['Billing-IM Screen Name-Jabber']);
750 $this->assertEquals('Whare KaiJabber' . $id, $row['Whare Kai-IM Screen Name-Jabber']);
751 $this->assertEquals('BillingSkype' . $id, $row['Billing-IM Screen Name-Skype']);
752 foreach ($relationships as $relatedContactID => $relationship) {
753 $this->assertEquals('BillingYahoo' . $relatedContactID, $row[$relationship['label'] . '-Billing-IM Screen Name-Yahoo']);
754 $this->assertEquals('Whare KaiJabber' . $relatedContactID, $row[$relationship['label'] . '-Whare Kai-IM Screen Name-Jabber']);
760 * Test phone data export.
762 * Less over the top complete than the im test.
764 * @throws \CRM_Core_Exception
765 * @throws \League\Csv\Exception
767 public function testExportPhoneData() {
768 $this->contactIDs
[] = $this->individualCreate();
769 $this->contactIDs
[] = $this->individualCreate();
770 $locationTypes = ['Billing' => 'Billing', 'Home' => 'Home'];
771 $phoneTypes = ['Mobile', 'Phone'];
772 foreach ($this->contactIDs
as $contactID) {
773 $this->callAPISuccess('Phone', 'create', [
774 'contact_id' => $contactID,
775 'location_type_id' => 'Billing',
776 'phone_type_id' => 'Mobile',
777 'phone' => 'Billing' . 'Mobile' . $contactID,
780 $this->callAPISuccess('Phone', 'create', [
781 'contact_id' => $contactID,
782 'location_type_id' => 'Home',
783 'phone_type_id' => 'Phone',
784 'phone' => 'Home' . 'Phone' . $contactID,
789 $this->contactIDs
[1] => ['label' => 'Spouse of'],
792 foreach ($relationships as $contactID => $relationshipType) {
793 $relationshipTypeID = $this->callAPISuccess('RelationshipType', 'getvalue', ['label_a_b' => $relationshipType['label'], 'return' => 'id']);
794 $result = $this->callAPISuccess('Relationship', 'create', [
795 'contact_id_a' => $this->contactIDs
[0],
796 'relationship_type_id' => $relationshipTypeID,
797 'contact_id_b' => $contactID,
799 $relationships[$contactID]['id'] = $result['id'];
800 $relationships[$contactID]['relationship_type_id'] = $relationshipTypeID;
803 $fields = [['Individual', 'contact_id']];
804 // ' ' denotes primary location type.
805 foreach (array_keys(array_merge($locationTypes, [' ' => ['Primary']])) as $locationType) {
809 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'location_type_id', $locationType),
814 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'location_type_id', $locationType),
816 foreach ($relationships as $contactID => $relationship) {
819 $relationship['relationship_type_id'] . '_a_b',
821 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'location_type_id', $locationType),
824 foreach ($phoneTypes as $phoneType) {
828 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'location_type_id', $locationType),
829 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'phone_type_id', $phoneType),
831 foreach ($relationships as $contactID => $relationship) {
834 $relationship['relationship_type_id'] . '_a_b',
836 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'location_type_id', $locationType),
837 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Phone', 'phone_type_id', $phoneType),
842 $this->doExportTest(['fields' => $fields, 'ids' => [$this->contactIDs
[0]]]);
843 foreach ($this->csv
->getRecords() as $row) {
844 $this->assertEquals('BillingMobile3', $row['Billing-Phone-Mobile']);
845 $this->assertEquals('', $row['Billing-Phone-Phone']);
846 $this->assertEquals('Phone', $row['Spouse of-Phone Type']);
847 $this->assertEquals('Mobile', $row['Phone Type']);
848 $this->assertEquals('Mobile', $row['Billing-Phone Type']);
853 * Export City against multiple location types.
855 public function testExportAddressData() {
856 $this->diversifyLocationTypes();
858 $locationTypes = ['Billing' => 'Billing', 'Home' => 'Home', 'Main' => 'Méin', 'Other' => 'Other', 'Whare Kai' => 'Whare Kai'];
860 $this->contactIDs
[] = $this->individualCreate();
861 $this->contactIDs
[] = $this->individualCreate();
862 $this->contactIDs
[] = $this->householdCreate();
863 $this->contactIDs
[] = $this->organizationCreate();
864 $fields = [['Individual', 'contact_id']];
865 foreach ($this->contactIDs
as $contactID) {
866 foreach ($locationTypes as $locationName => $locationLabel) {
867 $this->callAPISuccess('Address', 'create', [
868 'contact_id' => $contactID,
869 'location_type_id' => $locationName,
870 'street_address' => $locationLabel . $contactID . 'street_address',
871 'city' => $locationLabel . $contactID . 'city',
872 'postal_code' => $locationLabel . $contactID . 'postal_code',
874 $fields[] = ['Individual', 'city', CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Address', 'location_type_id', $locationName)];
875 $fields[] = ['Individual', 'street_address', CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Address', 'location_type_id', $locationName)];
876 $fields[] = ['Individual', 'postal_code', CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_Address', 'location_type_id', $locationName)];
881 $this->contactIDs
[1] => ['label' => 'Spouse of'],
882 $this->contactIDs
[2] => ['label' => 'Household Member of'],
883 $this->contactIDs
[3] => ['label' => 'Employee of'],
886 foreach ($relationships as $contactID => $relationshipType) {
887 $relationshipTypeID = $this->callAPISuccess('RelationshipType', 'getvalue', ['label_a_b' => $relationshipType['label'], 'return' => 'id']);
888 $result = $this->callAPISuccess('Relationship', 'create', [
889 'contact_id_a' => $this->contactIDs
[0],
890 'relationship_type_id' => $relationshipTypeID,
891 'contact_id_b' => $contactID,
893 $relationships[$contactID]['id'] = $result['id'];
894 $relationships[$contactID]['relationship_type_id'] = $relationshipTypeID;
897 // ' ' denotes primary location type.
898 foreach (array_keys(array_merge($locationTypes, [' ' => ['Primary']])) as $locationType) {
899 foreach ($relationships as $contactID => $relationship) {
902 $relationship['relationship_type_id'] . '_a_b',
904 CRM_Core_PseudoConstant
::getKey('CRM_Core_BAO_IM', 'location_type_id', $locationType),
908 list($tableName, $sqlColumns) = $this->doExport($fields, $this->contactIDs
[0]);
910 $dao = CRM_Core_DAO
::executeQuery('SELECT * FROM ' . $tableName);
911 while ($dao->fetch()) {
912 $id = $dao->contact_id
;
913 $this->assertEquals('Méin' . $id . 'city', $dao->main_city
);
914 $this->assertEquals('Billing' . $id . 'street_address', $dao->billing_street_address
);
915 $this->assertEquals('Whare Kai' . $id . 'postal_code', $dao->whare_kai_postal_code
);
916 foreach ($relationships as $relatedContactID => $relationship) {
917 $relationshipString = $field = $relationship['relationship_type_id'] . '_a_b';
918 $field = $relationshipString . '_main_city';
919 $this->assertEquals('Méin' . $relatedContactID . 'city', $dao->$field);
923 $this->assertEquals([
924 'contact_id' => 'contact_id varchar(255)',
925 'billing_city' => 'billing_city varchar(64)',
926 'billing_street_address' => 'billing_street_address varchar(96)',
927 'billing_postal_code' => 'billing_postal_code varchar(64)',
928 'home_city' => 'home_city varchar(64)',
929 'home_street_address' => 'home_street_address varchar(96)',
930 'home_postal_code' => 'home_postal_code varchar(64)',
931 'main_city' => 'main_city varchar(64)',
932 'main_street_address' => 'main_street_address varchar(96)',
933 'main_postal_code' => 'main_postal_code varchar(64)',
934 'other_city' => 'other_city varchar(64)',
935 'other_street_address' => 'other_street_address varchar(96)',
936 'other_postal_code' => 'other_postal_code varchar(64)',
937 'whare_kai_city' => 'whare_kai_city varchar(64)',
938 'whare_kai_street_address' => 'whare_kai_street_address varchar(96)',
939 'whare_kai_postal_code' => 'whare_kai_postal_code varchar(64)',
940 '2_a_b_billing_city' => '2_a_b_billing_city varchar(64)',
941 '2_a_b_home_city' => '2_a_b_home_city varchar(64)',
942 '2_a_b_main_city' => '2_a_b_main_city varchar(64)',
943 '2_a_b_other_city' => '2_a_b_other_city varchar(64)',
944 '2_a_b_whare_kai_city' => '2_a_b_whare_kai_city varchar(64)',
945 '2_a_b_city' => '2_a_b_city varchar(64)',
946 '8_a_b_billing_city' => '8_a_b_billing_city varchar(64)',
947 '8_a_b_home_city' => '8_a_b_home_city varchar(64)',
948 '8_a_b_main_city' => '8_a_b_main_city varchar(64)',
949 '8_a_b_other_city' => '8_a_b_other_city varchar(64)',
950 '8_a_b_whare_kai_city' => '8_a_b_whare_kai_city varchar(64)',
951 '8_a_b_city' => '8_a_b_city varchar(64)',
952 '5_a_b_billing_city' => '5_a_b_billing_city varchar(64)',
953 '5_a_b_home_city' => '5_a_b_home_city varchar(64)',
954 '5_a_b_main_city' => '5_a_b_main_city varchar(64)',
955 '5_a_b_other_city' => '5_a_b_other_city varchar(64)',
956 '5_a_b_whare_kai_city' => '5_a_b_whare_kai_city varchar(64)',
957 '5_a_b_city' => '5_a_b_city varchar(64)',
962 * Test master_address_id field.
964 public function testExportMasterAddress() {
965 $this->setUpContactExportData();
967 //export the master address for contact B
969 ['Individual', 'master_id', 1],
971 list($tableName, $sqlColumns) = CRM_Export_BAO_Export
::exportComponents(
973 [$this->contactIDs
[1]],
978 CRM_Export_Form_Select
::CONTACT_EXPORT
,
979 "contact_a.id IN ({$this->contactIDs[1]})",
984 'suppress_csv_for_testing' => TRUE,
987 $field = key($sqlColumns);
989 //assert the exported result
990 $masterName = CRM_Core_DAO
::singleValueQuery("SELECT {$field} FROM {$tableName}");
991 $displayName = CRM_Contact_BAO_Contact
::getMasterDisplayName($this->masterAddressID
);
992 $this->assertEquals($displayName, $masterName);
994 // delete the export temp table and component table
995 $sql = "DROP TABLE IF EXISTS {$tableName}";
996 CRM_Core_DAO
::executeQuery($sql);
1000 * Test that deceased and do not mail contacts are removed from contacts before
1002 * @dataProvider getReasonsNotToMail
1004 * @param array $reason
1005 * @param array $addressReason
1007 * @throws \CRM_Core_Exception
1009 public function testExportDeceasedDoNotMail($reason, $addressReason) {
1010 $contactA = $this->callAPISuccess('contact', 'create', [
1011 'first_name' => 'John',
1012 'last_name' => 'Doe',
1013 'contact_type' => 'Individual',
1016 $contactB = $this->callAPISuccess('contact', 'create', array_merge([
1017 'first_name' => 'Jane',
1018 'last_name' => 'Doe',
1019 'contact_type' => 'Individual',
1022 //create address for contact A
1023 $this->callAPISuccess('address', 'create', [
1024 'contact_id' => $contactA['id'],
1025 'location_type_id' => 'Home',
1026 'street_address' => 'ABC 12',
1027 'postal_code' => '123 AB',
1028 'country_id' => '1152',
1033 //create address for contact B
1034 $this->callAPISuccess('address', 'create', array_merge([
1035 'contact_id' => $contactB['id'],
1036 'location_type_id' => 'Home',
1037 'street_address' => 'ABC 12',
1038 'postal_code' => '123 AB',
1039 'country_id' => '1152',
1042 ], $addressReason));
1044 //export and merge contacts with same address
1045 list($tableName, $sqlColumns, $headerRows, $processor) = CRM_Export_BAO_Export
::exportComponents(
1047 [$contactA['id'], $contactB['id']],
1052 CRM_Export_Form_Select
::CONTACT_EXPORT
,
1053 "contact_a.id IN ({$contactA['id']}, {$contactB['id']})",
1058 'mergeOption' => TRUE,
1059 'suppress_csv_for_testing' => TRUE,
1060 'postal_mailing_export' => [
1061 'postal_mailing_export' => TRUE,
1066 $this->assertTrue(!in_array('state_province_id', $processor->getHeaderRows()));
1067 $greeting = CRM_Core_DAO
::singleValueQuery("SELECT email_greeting FROM {$tableName}");
1069 //Assert email_greeting is not merged
1070 $this->assertNotContains(',', (string) $greeting);
1072 // delete the export temp table and component table
1073 $sql = "DROP TABLE IF EXISTS {$tableName}";
1074 CRM_Core_DAO
::executeQuery($sql);
1078 * Get reasons that a contact is not postalable.
1082 public function getReasonsNotToMail() {
1084 [['is_deceased' => 1], []],
1085 [['do_not_mail' => 1], []],
1086 [[], ['street_address' => '']],
1091 * Set up household for tests.
1094 * @throws \Exception
1096 protected function setUpHousehold() {
1097 $this->setUpContactExportData();
1098 $householdID = $this->householdCreate([
1099 'source' => 'household sauce',
1100 'api.Address.create' => [
1101 'city' => 'Portland',
1102 'state_province_id' => 'Maine',
1103 'location_type_id' => 'Home',
1107 $relationshipTypes = $this->callAPISuccess('RelationshipType', 'get', [])['values'];
1108 $houseHoldTypeID = NULL;
1109 foreach ($relationshipTypes as $id => $relationshipType) {
1110 if ($relationshipType['name_a_b'] === 'Household Member of') {
1111 $houseHoldTypeID = $relationshipType['id'];
1114 $this->callAPISuccess('Relationship', 'create', [
1115 'contact_id_a' => $this->contactIDs
[0],
1116 'contact_id_b' => $householdID,
1117 'relationship_type_id' => $houseHoldTypeID,
1119 $this->callAPISuccess('Relationship', 'create', [
1120 'contact_id_a' => $this->contactIDs
[1],
1121 'contact_id_b' => $householdID,
1122 'relationship_type_id' => $houseHoldTypeID,
1124 return [$householdID, $houseHoldTypeID];
1128 * Do a CiviCRM export.
1130 * @param array $selectedFields
1133 * @param int $exportMode
1136 * @throws \CRM_Core_Exception
1138 protected function doExport($selectedFields, $id, $exportMode = CRM_Export_Form_Select
::CONTACT_EXPORT
) {
1140 list($tableName, $sqlColumns) = CRM_Export_BAO_Export
::exportComponents(
1148 "contact_a.id IN (" . implode(',', $ids) . ")",
1153 'suppress_csv_for_testing' => TRUE,
1156 return [$tableName, $sqlColumns];
1160 * Ensure component is enabled.
1162 * @param int $exportMode
1164 public function ensureComponentIsEnabled($exportMode) {
1165 if ($exportMode === CRM_Export_Form_Select
::CASE_EXPORT
) {
1166 CRM_Core_BAO_ConfigSetting
::enableComponent('CiviCase');
1171 * Test our export all field metadata retrieval.
1173 * @dataProvider additionalFieldsDataProvider
1175 * @param int $exportMode
1178 public function testAdditionalReturnProperties($exportMode, $expected) {
1179 $this->ensureComponentIsEnabled($exportMode);
1180 $processor = new CRM_Export_BAO_ExportProcessor($exportMode, NULL, 'AND');
1181 $metadata = $processor->getAdditionalReturnProperties();
1182 $this->assertEquals($expected, $metadata);
1186 * Test our export all field metadata retrieval.
1188 * @dataProvider allFieldsDataProvider
1190 * @param int $exportMode
1193 public function testDefaultReturnProperties($exportMode, $expected) {
1194 $this->ensureComponentIsEnabled($exportMode);
1195 $processor = new CRM_Export_BAO_ExportProcessor($exportMode, NULL, 'AND');
1196 $metadata = $processor->getDefaultReturnProperties();
1197 $this->assertEquals($expected, $metadata);
1201 * Get fields returned from additionalFields function.
1205 public function additionalFieldsDataProvider() {
1208 'anything that will then be defaulting ton contact',
1209 $this->getExtraReturnProperties(),
1212 CRM_Export_Form_Select
::ACTIVITY_EXPORT
,
1213 array_merge($this->getExtraReturnProperties(), $this->getActivityReturnProperties()),
1216 CRM_Export_Form_Select
::CASE_EXPORT
,
1217 array_merge($this->getExtraReturnProperties(), $this->getCaseReturnProperties()),
1220 CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
1221 array_merge($this->getExtraReturnProperties(), $this->getContributionReturnProperties()),
1224 CRM_Export_Form_Select
::EVENT_EXPORT
,
1225 array_merge($this->getExtraReturnProperties(), $this->getEventReturnProperties()),
1228 CRM_Export_Form_Select
::MEMBER_EXPORT
,
1229 array_merge($this->getExtraReturnProperties(), $this->getMembershipReturnProperties()),
1232 CRM_Export_Form_Select
::PLEDGE_EXPORT
,
1233 array_merge($this->getExtraReturnProperties(), $this->getPledgeReturnProperties()),
1240 * get data for testing field metadata by query mode.
1242 public function allFieldsDataProvider() {
1245 'anything that will then be defaulting ton contact',
1246 $this->getBasicReturnProperties(TRUE),
1249 CRM_Export_Form_Select
::ACTIVITY_EXPORT
,
1250 array_merge($this->getBasicReturnProperties(FALSE), $this->getActivityReturnProperties()),
1253 CRM_Export_Form_Select
::CASE_EXPORT
,
1254 array_merge($this->getBasicReturnProperties(FALSE), $this->getCaseReturnProperties()),
1257 CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
1258 array_merge($this->getBasicReturnProperties(FALSE), $this->getContributionReturnProperties()),
1261 CRM_Export_Form_Select
::EVENT_EXPORT
,
1262 array_merge($this->getBasicReturnProperties(FALSE), $this->getEventReturnProperties()),
1265 CRM_Export_Form_Select
::MEMBER_EXPORT
,
1266 array_merge($this->getBasicReturnProperties(FALSE), $this->getMembershipReturnProperties()),
1269 CRM_Export_Form_Select
::PLEDGE_EXPORT
,
1270 array_merge($this->getBasicReturnProperties(FALSE), $this->getPledgeReturnProperties()),
1276 * Get return properties manually added in.
1278 public function getExtraReturnProperties() {
1283 * Get basic return properties.
1285 * @param bool $isContactMode
1286 * Are we in contact mode or not
1290 protected function getBasicReturnProperties($isContactMode) {
1291 $returnProperties = [
1293 'contact_type' => 1,
1294 'contact_sub_type' => 1,
1295 'do_not_email' => 1,
1296 'do_not_phone' => 1,
1299 'do_not_trade' => 1,
1301 'legal_identifier' => 1,
1302 'external_identifier' => 1,
1304 'display_name' => 1,
1308 'preferred_communication_method' => 1,
1309 'preferred_language' => 1,
1310 'preferred_mail_format' => 1,
1312 'contact_source' => 1,
1318 'formal_title' => 1,
1319 'communication_style_id' => 1,
1320 'email_greeting_id' => 1,
1321 'postal_greeting_id' => 1,
1322 'addressee_id' => 1,
1327 'deceased_date' => 1,
1328 'household_name' => 1,
1329 'organization_name' => 1,
1331 'user_unique_id' => 1,
1332 'current_employer_id' => 1,
1333 'contact_is_deleted' => 1,
1334 'created_date' => 1,
1335 'modified_date' => 1,
1337 'email_greeting' => 1,
1338 'postal_greeting' => 1,
1339 'current_employer' => 1,
1340 'location_type' => 1,
1341 'street_address' => 1,
1342 'street_number' => 1,
1343 'street_number_suffix' => 1,
1346 'supplemental_address_1' => 1,
1347 'supplemental_address_2' => 1,
1348 'supplemental_address_3' => 1,
1350 'postal_code_suffix' => 1,
1354 'address_name' => 1,
1357 'state_province' => 1,
1364 'signature_text' => 1,
1365 'signature_html' => 1,
1369 'world_region' => 1,
1374 'phone_type_id' => 1,
1376 if (!$isContactMode) {
1377 unset($returnProperties['groups']);
1378 unset($returnProperties['tags']);
1379 unset($returnProperties['notes']);
1381 return $returnProperties;
1385 * Get return properties for pledges.
1389 public function getPledgeReturnProperties() {
1391 'contact_type' => 1,
1392 'contact_sub_type' => 1,
1394 'display_name' => 1,
1396 'pledge_amount' => 1,
1397 'pledge_total_paid' => 1,
1398 'pledge_create_date' => 1,
1399 'pledge_start_date' => 1,
1400 'pledge_next_pay_date' => 1,
1401 'pledge_next_pay_amount' => 1,
1402 'pledge_status' => 1,
1403 'pledge_is_test' => 1,
1404 'pledge_contribution_page_id' => 1,
1405 'pledge_financial_type' => 1,
1406 'pledge_frequency_interval' => 1,
1407 'pledge_frequency_unit' => 1,
1408 'pledge_currency' => 1,
1409 'pledge_campaign_id' => 1,
1410 'pledge_balance_amount' => 1,
1411 'pledge_payment_id' => 1,
1412 'pledge_payment_scheduled_amount' => 1,
1413 'pledge_payment_scheduled_date' => 1,
1414 'pledge_payment_paid_amount' => 1,
1415 'pledge_payment_paid_date' => 1,
1416 'pledge_payment_reminder_date' => 1,
1417 'pledge_payment_reminder_count' => 1,
1418 'pledge_payment_status' => 1,
1423 * Get membership return properties.
1427 public function getMembershipReturnProperties() {
1429 'contact_type' => 1,
1430 'contact_sub_type' => 1,
1432 'display_name' => 1,
1433 'membership_type' => 1,
1434 'member_is_test' => 1,
1435 'member_is_pay_later' => 1,
1437 'membership_start_date' => 1,
1438 'membership_end_date' => 1,
1439 'membership_source' => 1,
1440 'membership_status' => 1,
1441 'membership_id' => 1,
1442 'owner_membership_id' => 1,
1444 'membership_recur_id' => 1,
1445 'member_campaign_id' => 1,
1446 'member_is_override' => 1,
1447 'member_auto_renew' => 1,
1452 * Get return properties for events.
1456 public function getEventReturnProperties() {
1458 'contact_type' => 1,
1459 'contact_sub_type' => 1,
1461 'display_name' => 1,
1464 'event_start_date' => 1,
1465 'event_end_date' => 1,
1467 'participant_id' => 1,
1468 'participant_status' => 1,
1469 'participant_status_id' => 1,
1470 'participant_role' => 1,
1471 'participant_role_id' => 1,
1472 'participant_note' => 1,
1473 'participant_register_date' => 1,
1474 'participant_source' => 1,
1475 'participant_fee_level' => 1,
1476 'participant_is_test' => 1,
1477 'participant_is_pay_later' => 1,
1478 'participant_fee_amount' => 1,
1479 'participant_discount_name' => 1,
1480 'participant_fee_currency' => 1,
1481 'participant_registered_by_id' => 1,
1482 'participant_campaign_id' => 1,
1487 * Get return properties for activities.
1491 public function getActivityReturnProperties() {
1494 'contact_type' => 1,
1495 'contact_sub_type' => 1,
1497 'display_name' => 1,
1498 'activity_type' => 1,
1499 'activity_type_id' => 1,
1500 'activity_subject' => 1,
1501 'activity_date_time' => 1,
1502 'activity_duration' => 1,
1503 'activity_location' => 1,
1504 'activity_details' => 1,
1505 'activity_status' => 1,
1506 'activity_priority' => 1,
1507 'source_contact' => 1,
1508 'source_record_id' => 1,
1509 'activity_is_test' => 1,
1510 'activity_campaign_id' => 1,
1512 'activity_engagement_level' => 1,
1518 * Get return properties for Case.
1522 public function getCaseReturnProperties() {
1524 'contact_type' => 1,
1525 'contact_sub_type' => 1,
1527 'display_name' => 1,
1529 'case_start_date' => 1,
1530 'case_end_date' => 1,
1531 'case_subject' => 1,
1532 'case_source_contact_id' => 1,
1533 'case_activity_status' => 1,
1534 'case_activity_duration' => 1,
1535 'case_activity_medium_id' => 1,
1536 'case_activity_details' => 1,
1537 'case_activity_is_auto' => 1,
1540 'case_activity_subject' => 1,
1544 'case_deleted' => 1,
1545 'case_recent_activity_date' => 1,
1546 'case_recent_activity_type' => 1,
1547 'case_scheduled_activity_date' => 1,
1552 * Get return properties for contribution.
1556 public function getContributionReturnProperties() {
1558 'contact_type' => 1,
1559 'contact_sub_type' => 1,
1561 'display_name' => 1,
1562 'financial_type' => 1,
1563 'contribution_source' => 1,
1564 'receive_date' => 1,
1565 'thankyou_date' => 1,
1566 'contribution_cancel_date' => 1,
1567 'total_amount' => 1,
1568 'accounting_code' => 1,
1569 'payment_instrument' => 1,
1570 'payment_instrument_id' => 1,
1571 'contribution_check_number' => 1,
1572 'non_deductible_amount' => 1,
1577 'invoice_number' => 1,
1579 'cancel_reason' => 1,
1580 'receipt_date' => 1,
1582 'is_pay_later' => 1,
1583 'contribution_status' => 1,
1584 'contribution_recur_id' => 1,
1585 'amount_level' => 1,
1586 'contribution_note' => 1,
1587 'contribution_batch' => 1,
1588 'contribution_campaign_title' => 1,
1589 'contribution_campaign_id' => 1,
1590 'contribution_soft_credit_name' => 1,
1591 'contribution_soft_credit_amount' => 1,
1592 'contribution_soft_credit_type' => 1,
1593 'contribution_soft_credit_contact_id' => 1,
1594 'contribution_soft_credit_contribution_id' => 1,
1599 * Test the column definition when 'all' fields defined.
1601 * @param int $exportMode
1602 * @param array $expected
1603 * @param array $expectedHeaders
1605 * @throws \CRM_Core_Exception
1606 * @dataProvider getSqlColumnsOutput
1608 public function testGetSQLColumnsAndHeaders($exportMode, $expected, $expectedHeaders) {
1609 $this->ensureComponentIsEnabled($exportMode);
1610 // We need some data so that we can get to the end of the export
1611 // function. Hopefully one day that won't be required to get metadata info out.
1612 // eventually aspire to call $provider->getSQLColumns straight after it
1614 $this->setupBaseExportData($exportMode);
1616 $result = CRM_Export_BAO_Export
::exportComponents(
1629 'suppress_csv_for_testing' => TRUE,
1632 $this->assertEquals($expected, $result[1]);
1633 $this->assertEquals($expectedHeaders, $result[2]);
1637 * Test exported with data entry mis-fire.
1639 * Not fatal error if data incomplete.
1641 * https://lab.civicrm.org/dev/core/issues/819
1643 public function testExportIncompleteSubmission() {
1644 $this->setUpContactExportData();
1645 $this->doExport([['Individual', '']], $this->contactIDs
[1]);
1649 * Test exported with fields to output specified.
1651 * @dataProvider getAllSpecifiableReturnFields
1653 * @param int $exportMode
1654 * @param array $selectedFields
1655 * @param array $expected
1657 public function testExportSpecifyFields($exportMode, $selectedFields, $expected) {
1658 $this->ensureComponentIsEnabled($exportMode);
1659 $this->setUpContributionExportData();
1660 list($tableName, $sqlColumns) = $this->doExport($selectedFields, $this->contactIDs
[1], $exportMode);
1661 $this->assertEquals($expected, $sqlColumns);
1665 * Test export fields when no payment fields to be exported.
1667 public function textExportParticipantSpecifyFieldsNoPayment() {
1668 $selectedFields = $this->getAllSpecifiableParticipantReturnFields();
1669 foreach ($selectedFields as $index => $field) {
1670 if (substr($field[1], 0, 22) === 'componentPaymentField_') {
1671 unset($selectedFields[$index]);
1675 $expected = $this->getAllSpecifiableParticipantReturnFields();
1676 foreach ($expected as $index => $field) {
1677 if (substr($index, 0, 22) === 'componentPaymentField_') {
1678 unset($expected[$index]);
1682 list($tableName, $sqlColumns) = $this->doExport($selectedFields, $this->contactIDs
[1], CRM_Export_Form_Select
::EVENT_EXPORT
);
1683 $this->assertEquals($expected, $sqlColumns);
1687 * Get all return fields (@return array
1689 * @todo - still being built up.
1692 public function getAllSpecifiableReturnFields() {
1695 CRM_Export_Form_Select
::EVENT_EXPORT
,
1696 $this->getAllSpecifiableParticipantReturnFields(),
1697 $this->getAllSpecifiableParticipantReturnColumns(),
1703 * Get expected return column output for participant mode return all columns.
1707 public function getAllSpecifiableParticipantReturnColumns() {
1709 'participant_campaign_id' => 'participant_campaign_id varchar(128)',
1710 'participant_contact_id' => 'participant_contact_id varchar(16)',
1711 'componentpaymentfield_contribution_status' => 'componentpaymentfield_contribution_status text',
1712 'currency' => 'currency varchar(3)',
1713 'componentpaymentfield_received_date' => 'componentpaymentfield_received_date text',
1714 'default_role_id' => 'default_role_id varchar(16)',
1715 'participant_discount_name' => 'participant_discount_name varchar(16)',
1716 'event_id' => 'event_id varchar(16)',
1717 'event_end_date' => 'event_end_date varchar(32)',
1718 'event_start_date' => 'event_start_date varchar(32)',
1719 'template_title' => 'template_title varchar(255)',
1720 'event_title' => 'event_title varchar(255)',
1721 'participant_fee_amount' => 'participant_fee_amount varchar(32)',
1722 'participant_fee_currency' => 'participant_fee_currency varchar(3)',
1723 'fee_label' => 'fee_label varchar(255)',
1724 'participant_fee_level' => 'participant_fee_level longtext',
1725 'participant_is_pay_later' => 'participant_is_pay_later varchar(16)',
1726 'participant_id' => 'participant_id varchar(16)',
1727 'participant_note' => 'participant_note text',
1728 'participant_role_id' => 'participant_role_id varchar(128)',
1729 'participant_role' => 'participant_role varchar(255)',
1730 'participant_source' => 'participant_source varchar(128)',
1731 'participant_status_id' => 'participant_status_id varchar(16)',
1732 'participant_status' => 'participant_status varchar(255)',
1733 'participant_register_date' => 'participant_register_date varchar(32)',
1734 'participant_registered_by_id' => 'participant_registered_by_id varchar(16)',
1735 'participant_is_test' => 'participant_is_test varchar(16)',
1736 'componentpaymentfield_total_amount' => 'componentpaymentfield_total_amount text',
1737 'componentpaymentfield_transaction_id' => 'componentpaymentfield_transaction_id varchar(255)',
1738 'transferred_to_contact_id' => 'transferred_to_contact_id varchar(16)',
1745 public function getAllSpecifiableParticipantReturnFields() {
1755 1 => 'participant_campaign_id',
1760 1 => 'participant_contact_id',
1765 1 => 'componentPaymentField_contribution_status',
1775 1 => 'componentPaymentField_received_date',
1780 1 => 'default_role_id',
1785 1 => 'participant_discount_name',
1795 1 => 'event_end_date',
1800 1 => 'event_start_date',
1805 1 => 'template_title',
1815 1 => 'participant_fee_amount',
1820 1 => 'participant_fee_currency',
1830 1 => 'participant_fee_level',
1835 1 => 'participant_is_pay_later',
1840 1 => 'participant_id',
1845 1 => 'participant_note',
1850 1 => 'participant_role_id',
1855 1 => 'participant_role',
1860 1 => 'participant_source',
1865 1 => 'participant_status_id',
1870 1 => 'participant_status',
1875 1 => 'participant_status',
1880 1 => 'participant_register_date',
1885 1 => 'participant_registered_by_id',
1890 1 => 'participant_is_test',
1895 1 => 'componentPaymentField_total_amount',
1900 1 => 'componentPaymentField_transaction_id',
1905 1 => 'transferred_to_contact_id',
1911 * @param string $exportMode
1913 public function setupBaseExportData($exportMode) {
1914 $this->createLoggedInUser();
1915 if ($exportMode === CRM_Export_Form_Select
::CASE_EXPORT
) {
1916 $this->setupCaseExportData();
1918 if ($exportMode === CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
) {
1919 $this->setUpContributionExportData();
1921 if ($exportMode === CRM_Export_Form_Select
::MEMBER_EXPORT
) {
1922 $this->setUpMembershipExportData();
1924 if ($exportMode === CRM_Export_Form_Select
::ACTIVITY_EXPORT
) {
1925 $this->setUpActivityExportData();
1930 * Get comprehensive sql columns output.
1934 public function getSqlColumnsOutput() {
1937 'anything that will then be defaulting ton contact',
1938 $this->getBasicSqlColumnDefinition(TRUE),
1939 $this->getBasicHeaderDefinition(TRUE),
1942 CRM_Export_Form_Select
::ACTIVITY_EXPORT
,
1943 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getActivitySqlColumns()),
1944 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getActivityHeaderDefinition()),
1947 CRM_Export_Form_Select
::CASE_EXPORT
,
1948 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getCaseSqlColumns()),
1949 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getCaseHeaderDefinition()),
1952 CRM_Export_Form_Select
::CONTRIBUTE_EXPORT
,
1953 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getContributionSqlColumns()),
1954 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getContributeHeaderDefinition()),
1957 CRM_Export_Form_Select
::EVENT_EXPORT
,
1958 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getParticipantSqlColumns()),
1959 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getParticipantHeaderDefinition()),
1962 CRM_Export_Form_Select
::MEMBER_EXPORT
,
1963 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getMembershipSqlColumns()),
1964 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getMemberHeaderDefinition()),
1967 CRM_Export_Form_Select
::PLEDGE_EXPORT
,
1968 array_merge($this->getBasicSqlColumnDefinition(FALSE), $this->getPledgeSqlColumns()),
1969 array_merge($this->getBasicHeaderDefinition(FALSE), $this->getPledgeHeaderDefinition()),
1976 * Get the header definition for exports.
1978 * @param bool $isContactExport
1982 protected function getBasicHeaderDefinition($isContactExport) {
1985 1 => 'Contact Type',
1986 2 => 'Contact Subtype',
1987 3 => 'Do Not Email',
1988 4 => 'Do Not Phone',
1991 7 => 'Do Not Trade',
1992 8 => 'No Bulk Emails (User Opt Out)',
1993 9 => 'Legal Identifier',
1994 10 => 'External Identifier',
1996 12 => 'Display Name',
2000 16 => 'Preferred Communication Method',
2001 17 => 'Preferred Language',
2002 18 => 'Preferred Mail Format',
2003 19 => 'Contact Hash',
2004 20 => 'Contact Source',
2006 22 => 'Middle Name',
2008 24 => 'Individual Prefix',
2009 25 => 'Individual Suffix',
2010 26 => 'Formal Title',
2011 27 => 'Communication Style',
2012 28 => 'Email Greeting ID',
2013 29 => 'Postal Greeting ID',
2014 30 => 'Addressee ID',
2019 35 => 'Deceased Date',
2020 36 => 'Household Name',
2021 37 => 'Organization Name',
2023 39 => 'Unique ID (OpenID)',
2024 40 => 'Current Employer ID',
2025 41 => 'Contact is in Trash',
2026 42 => 'Created Date',
2027 43 => 'Modified Date',
2029 45 => 'Email Greeting',
2030 46 => 'Postal Greeting',
2031 47 => 'Current Employer',
2032 48 => 'Location Type',
2033 49 => 'Street Address',
2034 50 => 'Street Number',
2035 51 => 'Street Number Suffix',
2036 52 => 'Street Name',
2037 53 => 'Street Unit',
2038 54 => 'Supplemental Address 1',
2039 55 => 'Supplemental Address 2',
2040 56 => 'Supplemental Address 3',
2042 58 => 'Postal Code Suffix',
2043 59 => 'Postal Code',
2046 62 => 'Address Name',
2047 63 => 'Master Address Belongs To',
2052 68 => 'Phone Extension',
2056 72 => 'Use for Bulk Mail',
2057 73 => 'Signature Text',
2058 74 => 'Signature Html',
2059 75 => 'IM Provider',
2060 76 => 'IM Screen Name',
2062 78 => 'World Region',
2068 if (!$isContactExport) {
2069 unset($headers[80]);
2070 unset($headers[81]);
2071 unset($headers[82]);
2077 * Get the definition for activity headers.
2081 protected function getActivityHeaderDefinition() {
2083 81 => 'Activity ID',
2084 82 => 'Activity Type',
2085 83 => 'Activity Type ID',
2087 85 => 'Activity Date',
2091 89 => 'Activity Status',
2092 90 => 'Activity Priority',
2093 91 => 'Source Contact',
2094 92 => 'source_record_id',
2096 94 => 'Campaign ID',
2098 96 => 'Engagement Index',
2104 * Get the definition for case headers.
2108 protected function getCaseHeaderDefinition() {
2112 83 => 'case_activity_subject',
2113 84 => 'Case Subject',
2114 85 => 'Case Status',
2116 87 => 'Role in Case',
2117 88 => 'Case is in the Trash',
2118 89 => 'case_recent_activity_date',
2119 90 => 'case_recent_activity_type',
2120 91 => 'case_scheduled_activity_date',
2121 92 => 'Case Start Date',
2122 93 => 'Case End Date',
2123 94 => 'case_source_contact_id',
2124 95 => 'case_activity_status',
2125 96 => 'case_activity_duration',
2126 97 => 'case_activity_medium_id',
2127 98 => 'case_activity_details',
2128 99 => 'case_activity_is_auto',
2133 * Get the definition for contribute headers.
2137 protected function getContributeHeaderDefinition() {
2139 81 => 'Financial Type',
2140 82 => 'Contribution Source',
2141 83 => 'Date Received',
2142 84 => 'Thank-you Date',
2143 85 => 'Cancelled / Refunded Date',
2144 86 => 'Total Amount',
2145 87 => 'Accounting Code',
2146 88 => 'Payment Methods',
2147 89 => 'Payment Method ID',
2148 90 => 'Check Number',
2149 91 => 'Non-deductible Amount',
2152 94 => 'Transaction ID',
2153 95 => 'Invoice Reference',
2154 96 => 'Invoice Number',
2156 98 => 'Cancellation / Refund Reason',
2157 99 => 'Receipt Date',
2159 107 => 'Is Pay Later',
2160 108 => 'Contribution Status',
2161 109 => 'Recurring Contribution ID',
2162 110 => 'Amount Label',
2163 111 => 'Contribution Note',
2164 112 => 'Batch Name',
2165 113 => 'Campaign Title',
2166 114 => 'Campaign ID',
2167 116 => 'Soft Credit For',
2168 117 => 'Soft Credit Amount',
2169 118 => 'Soft Credit Type',
2170 119 => 'Soft Credit For Contact ID',
2171 120 => 'Soft Credit For Contribution ID',
2176 * Get the definition for event headers.
2180 protected function getParticipantHeaderDefinition() {
2183 82 => 'Event Title',
2184 83 => 'Event Start Date',
2185 84 => 'Event End Date',
2187 86 => 'Participant ID',
2188 87 => 'Participant Status',
2189 88 => 'Participant Status Id',
2190 89 => 'Participant Role',
2191 90 => 'Participant Role Id',
2192 91 => 'Participant Note',
2193 92 => 'Register date',
2194 93 => 'Participant Source',
2197 96 => 'Is Pay Later',
2199 98 => 'Discount Name',
2200 99 => 'Fee Currency',
2201 100 => 'Registered By ID',
2202 101 => 'Campaign ID',
2207 * Get the definition for member headers.
2211 protected function getMemberHeaderDefinition() {
2213 81 => 'Membership Type',
2215 83 => 'Is Pay Later',
2216 84 => 'Member Since',
2217 85 => 'Membership Start Date',
2218 86 => 'Membership Expiration Date',
2220 88 => 'Membership Status',
2221 89 => 'Membership ID',
2222 90 => 'Primary Member ID',
2223 91 => 'max_related',
2224 92 => 'membership_recur_id',
2225 93 => 'Campaign ID',
2226 94 => 'member_is_override',
2227 95 => 'member_auto_renew',
2232 * Get the definition for pledge headers.
2236 protected function getPledgeHeaderDefinition() {
2239 82 => 'Total Pledged',
2241 84 => 'Pledge Made',
2242 85 => 'pledge_start_date',
2243 86 => 'Next Payment Date',
2244 87 => 'Next Payment Amount',
2245 88 => 'Pledge Status',
2247 90 => 'Pledge Contribution Page Id',
2248 91 => 'pledge_financial_type',
2249 92 => 'Pledge Frequency Interval',
2250 93 => 'Pledge Frequency Unit',
2251 94 => 'pledge_currency',
2252 95 => 'Campaign ID',
2253 96 => 'Balance Amount',
2255 98 => 'Scheduled Amount',
2256 99 => 'Scheduled Date',
2257 100 => 'Paid Amount',
2259 102 => 'Last Reminder',
2260 103 => 'Reminders Sent',
2261 104 => 'Pledge Payment Status',
2266 * Get the column definition for exports.
2268 * @param bool $isContactExport
2272 protected function getBasicSqlColumnDefinition($isContactExport) {
2274 'civicrm_primary_id' => 'civicrm_primary_id varchar(16)',
2275 'contact_type' => 'contact_type varchar(64)',
2276 'contact_sub_type' => 'contact_sub_type varchar(255)',
2277 'do_not_email' => 'do_not_email varchar(16)',
2278 'do_not_phone' => 'do_not_phone varchar(16)',
2279 'do_not_mail' => 'do_not_mail varchar(16)',
2280 'do_not_sms' => 'do_not_sms varchar(16)',
2281 'do_not_trade' => 'do_not_trade varchar(16)',
2282 'is_opt_out' => 'is_opt_out varchar(16)',
2283 'legal_identifier' => 'legal_identifier varchar(32)',
2284 'external_identifier' => 'external_identifier varchar(64)',
2285 'sort_name' => 'sort_name varchar(128)',
2286 'display_name' => 'display_name varchar(128)',
2287 'nick_name' => 'nick_name varchar(128)',
2288 'legal_name' => 'legal_name varchar(128)',
2289 'image_url' => 'image_url longtext',
2290 'preferred_communication_method' => 'preferred_communication_method varchar(255)',
2291 'preferred_language' => 'preferred_language varchar(5)',
2292 'preferred_mail_format' => 'preferred_mail_format varchar(8)',
2293 'hash' => 'hash varchar(32)',
2294 'contact_source' => 'contact_source varchar(255)',
2295 'first_name' => 'first_name varchar(64)',
2296 'middle_name' => 'middle_name varchar(64)',
2297 'last_name' => 'last_name varchar(64)',
2298 'prefix_id' => 'prefix_id varchar(255)',
2299 'suffix_id' => 'suffix_id varchar(255)',
2300 'formal_title' => 'formal_title varchar(64)',
2301 'communication_style_id' => 'communication_style_id varchar(16)',
2302 'email_greeting_id' => 'email_greeting_id varchar(16)',
2303 'postal_greeting_id' => 'postal_greeting_id varchar(16)',
2304 'addressee_id' => 'addressee_id varchar(16)',
2305 'job_title' => 'job_title varchar(255)',
2306 'gender_id' => 'gender_id varchar(16)',
2307 'birth_date' => 'birth_date varchar(32)',
2308 'is_deceased' => 'is_deceased varchar(16)',
2309 'deceased_date' => 'deceased_date varchar(32)',
2310 'household_name' => 'household_name varchar(128)',
2311 'organization_name' => 'organization_name varchar(128)',
2312 'sic_code' => 'sic_code varchar(8)',
2313 'user_unique_id' => 'user_unique_id varchar(255)',
2314 'current_employer_id' => 'current_employer_id varchar(16)',
2315 'contact_is_deleted' => 'contact_is_deleted varchar(16)',
2316 'created_date' => 'created_date varchar(32)',
2317 'modified_date' => 'modified_date varchar(32)',
2318 'addressee' => 'addressee varchar(255)',
2319 'email_greeting' => 'email_greeting varchar(255)',
2320 'postal_greeting' => 'postal_greeting varchar(255)',
2321 'current_employer' => 'current_employer varchar(128)',
2322 'location_type' => 'location_type text',
2323 'street_address' => 'street_address varchar(96)',
2324 'street_number' => 'street_number varchar(16)',
2325 'street_number_suffix' => 'street_number_suffix varchar(8)',
2326 'street_name' => 'street_name varchar(64)',
2327 'street_unit' => 'street_unit varchar(16)',
2328 'supplemental_address_1' => 'supplemental_address_1 varchar(96)',
2329 'supplemental_address_2' => 'supplemental_address_2 varchar(96)',
2330 'supplemental_address_3' => 'supplemental_address_3 varchar(96)',
2331 'city' => 'city varchar(64)',
2332 'postal_code_suffix' => 'postal_code_suffix varchar(12)',
2333 'postal_code' => 'postal_code varchar(64)',
2334 'geo_code_1' => 'geo_code_1 varchar(32)',
2335 'geo_code_2' => 'geo_code_2 varchar(32)',
2336 'address_name' => 'address_name varchar(255)',
2337 'master_id' => 'master_id varchar(128)',
2338 'county' => 'county varchar(64)',
2339 'state_province' => 'state_province varchar(64)',
2340 'country' => 'country varchar(64)',
2341 'phone' => 'phone varchar(32)',
2342 'phone_ext' => 'phone_ext varchar(16)',
2343 'phone_type_id' => 'phone_type_id varchar(16)',
2344 'email' => 'email varchar(254)',
2345 'on_hold' => 'on_hold varchar(16)',
2346 'is_bulkmail' => 'is_bulkmail varchar(16)',
2347 'signature_text' => 'signature_text longtext',
2348 'signature_html' => 'signature_html longtext',
2349 'im_provider' => 'im_provider text',
2350 'im_screen_name' => 'im_screen_name varchar(64)',
2351 'openid' => 'openid varchar(255)',
2352 'world_region' => 'world_region varchar(128)',
2353 'url' => 'url varchar(128)',
2354 'groups' => 'groups text',
2355 'tags' => 'tags text',
2356 'notes' => 'notes text',
2358 if (!$isContactExport) {
2359 unset($columns['groups']);
2360 unset($columns['tags']);
2361 unset($columns['notes']);
2367 * Get Case SQL columns.
2371 protected function getCaseSqlColumns() {
2373 'case_start_date' => 'case_start_date varchar(32)',
2374 'case_end_date' => 'case_end_date varchar(32)',
2375 'case_subject' => 'case_subject varchar(128)',
2376 'case_source_contact_id' => 'case_source_contact_id varchar(255)',
2377 'case_activity_status' => 'case_activity_status text',
2378 'case_activity_duration' => 'case_activity_duration text',
2379 'case_activity_medium_id' => 'case_activity_medium_id varchar(255)',
2380 'case_activity_details' => 'case_activity_details text',
2381 'case_activity_is_auto' => 'case_activity_is_auto text',
2382 'contact_id' => 'contact_id varchar(255)',
2383 'case_id' => 'case_id varchar(16)',
2384 'case_activity_subject' => 'case_activity_subject text',
2385 'case_status' => 'case_status text',
2386 'case_type' => 'case_type text',
2387 'case_role' => 'case_role text',
2388 'case_deleted' => 'case_deleted varchar(16)',
2389 'case_recent_activity_date' => 'case_recent_activity_date text',
2390 'case_recent_activity_type' => 'case_recent_activity_type text',
2391 'case_scheduled_activity_date' => 'case_scheduled_activity_date text',
2396 * Get activity sql columns.
2400 protected function getActivitySqlColumns() {
2402 'activity_id' => 'activity_id varchar(16)',
2403 'activity_type' => 'activity_type varchar(255)',
2404 'activity_type_id' => 'activity_type_id varchar(16)',
2405 'activity_subject' => 'activity_subject varchar(255)',
2406 'activity_date_time' => 'activity_date_time varchar(32)',
2407 'activity_duration' => 'activity_duration varchar(16)',
2408 'activity_location' => 'activity_location varchar(255)',
2409 'activity_details' => 'activity_details longtext',
2410 'activity_status' => 'activity_status varchar(255)',
2411 'activity_priority' => 'activity_priority varchar(255)',
2412 'source_contact' => 'source_contact varchar(255)',
2413 'source_record_id' => 'source_record_id varchar(255)',
2414 'activity_is_test' => 'activity_is_test varchar(16)',
2415 'activity_campaign_id' => 'activity_campaign_id varchar(128)',
2416 'result' => 'result text',
2417 'activity_engagement_level' => 'activity_engagement_level varchar(16)',
2418 'parent_id' => 'parent_id varchar(255)',
2423 * Get participant sql columns.
2427 protected function getParticipantSqlColumns() {
2429 'event_id' => 'event_id varchar(16)',
2430 'event_title' => 'event_title varchar(255)',
2431 'event_start_date' => 'event_start_date varchar(32)',
2432 'event_end_date' => 'event_end_date varchar(32)',
2433 'event_type' => 'event_type varchar(255)',
2434 'participant_id' => 'participant_id varchar(16)',
2435 'participant_status' => 'participant_status varchar(255)',
2436 'participant_status_id' => 'participant_status_id varchar(16)',
2437 'participant_role' => 'participant_role varchar(255)',
2438 'participant_role_id' => 'participant_role_id varchar(128)',
2439 'participant_note' => 'participant_note text',
2440 'participant_register_date' => 'participant_register_date varchar(32)',
2441 'participant_source' => 'participant_source varchar(128)',
2442 'participant_fee_level' => 'participant_fee_level longtext',
2443 'participant_is_test' => 'participant_is_test varchar(16)',
2444 'participant_is_pay_later' => 'participant_is_pay_later varchar(16)',
2445 'participant_fee_amount' => 'participant_fee_amount varchar(32)',
2446 'participant_discount_name' => 'participant_discount_name varchar(16)',
2447 'participant_fee_currency' => 'participant_fee_currency varchar(3)',
2448 'participant_registered_by_id' => 'participant_registered_by_id varchar(16)',
2449 'participant_campaign_id' => 'participant_campaign_id varchar(128)',
2454 * Get contribution sql columns.
2458 public function getContributionSqlColumns() {
2460 'civicrm_primary_id' => 'civicrm_primary_id varchar(16)',
2461 'contact_type' => 'contact_type varchar(64)',
2462 'contact_sub_type' => 'contact_sub_type varchar(255)',
2463 'do_not_email' => 'do_not_email varchar(16)',
2464 'do_not_phone' => 'do_not_phone varchar(16)',
2465 'do_not_mail' => 'do_not_mail varchar(16)',
2466 'do_not_sms' => 'do_not_sms varchar(16)',
2467 'do_not_trade' => 'do_not_trade varchar(16)',
2468 'is_opt_out' => 'is_opt_out varchar(16)',
2469 'legal_identifier' => 'legal_identifier varchar(32)',
2470 'external_identifier' => 'external_identifier varchar(64)',
2471 'sort_name' => 'sort_name varchar(128)',
2472 'display_name' => 'display_name varchar(128)',
2473 'nick_name' => 'nick_name varchar(128)',
2474 'legal_name' => 'legal_name varchar(128)',
2475 'image_url' => 'image_url longtext',
2476 'preferred_communication_method' => 'preferred_communication_method varchar(255)',
2477 'preferred_language' => 'preferred_language varchar(5)',
2478 'preferred_mail_format' => 'preferred_mail_format varchar(8)',
2479 'hash' => 'hash varchar(32)',
2480 'contact_source' => 'contact_source varchar(255)',
2481 'first_name' => 'first_name varchar(64)',
2482 'middle_name' => 'middle_name varchar(64)',
2483 'last_name' => 'last_name varchar(64)',
2484 'prefix_id' => 'prefix_id varchar(255)',
2485 'suffix_id' => 'suffix_id varchar(255)',
2486 'formal_title' => 'formal_title varchar(64)',
2487 'communication_style_id' => 'communication_style_id varchar(16)',
2488 'email_greeting_id' => 'email_greeting_id varchar(16)',
2489 'postal_greeting_id' => 'postal_greeting_id varchar(16)',
2490 'addressee_id' => 'addressee_id varchar(16)',
2491 'job_title' => 'job_title varchar(255)',
2492 'gender_id' => 'gender_id varchar(16)',
2493 'birth_date' => 'birth_date varchar(32)',
2494 'is_deceased' => 'is_deceased varchar(16)',
2495 'deceased_date' => 'deceased_date varchar(32)',
2496 'household_name' => 'household_name varchar(128)',
2497 'organization_name' => 'organization_name varchar(128)',
2498 'sic_code' => 'sic_code varchar(8)',
2499 'user_unique_id' => 'user_unique_id varchar(255)',
2500 'current_employer_id' => 'current_employer_id varchar(16)',
2501 'contact_is_deleted' => 'contact_is_deleted varchar(16)',
2502 'created_date' => 'created_date varchar(32)',
2503 'modified_date' => 'modified_date varchar(32)',
2504 'addressee' => 'addressee varchar(255)',
2505 'email_greeting' => 'email_greeting varchar(255)',
2506 'postal_greeting' => 'postal_greeting varchar(255)',
2507 'current_employer' => 'current_employer varchar(128)',
2508 'location_type' => 'location_type text',
2509 'street_address' => 'street_address varchar(96)',
2510 'street_number' => 'street_number varchar(16)',
2511 'street_number_suffix' => 'street_number_suffix varchar(8)',
2512 'street_name' => 'street_name varchar(64)',
2513 'street_unit' => 'street_unit varchar(16)',
2514 'supplemental_address_1' => 'supplemental_address_1 varchar(96)',
2515 'supplemental_address_2' => 'supplemental_address_2 varchar(96)',
2516 'supplemental_address_3' => 'supplemental_address_3 varchar(96)',
2517 'city' => 'city varchar(64)',
2518 'postal_code_suffix' => 'postal_code_suffix varchar(12)',
2519 'postal_code' => 'postal_code varchar(64)',
2520 'geo_code_1' => 'geo_code_1 varchar(32)',
2521 'geo_code_2' => 'geo_code_2 varchar(32)',
2522 'address_name' => 'address_name varchar(255)',
2523 'master_id' => 'master_id varchar(128)',
2524 'county' => 'county varchar(64)',
2525 'state_province' => 'state_province varchar(64)',
2526 'country' => 'country varchar(64)',
2527 'phone' => 'phone varchar(32)',
2528 'phone_ext' => 'phone_ext varchar(16)',
2529 'email' => 'email varchar(254)',
2530 'on_hold' => 'on_hold varchar(16)',
2531 'is_bulkmail' => 'is_bulkmail varchar(16)',
2532 'signature_text' => 'signature_text longtext',
2533 'signature_html' => 'signature_html longtext',
2534 'im_provider' => 'im_provider text',
2535 'im_screen_name' => 'im_screen_name varchar(64)',
2536 'openid' => 'openid varchar(255)',
2537 'world_region' => 'world_region varchar(128)',
2538 'url' => 'url varchar(128)',
2539 'phone_type_id' => 'phone_type_id varchar(16)',
2540 'financial_type' => 'financial_type varchar(255)',
2541 'contribution_source' => 'contribution_source varchar(255)',
2542 'receive_date' => 'receive_date varchar(32)',
2543 'thankyou_date' => 'thankyou_date varchar(32)',
2544 'contribution_cancel_date' => 'contribution_cancel_date varchar(32)',
2545 'total_amount' => 'total_amount varchar(32)',
2546 'accounting_code' => 'accounting_code varchar(64)',
2547 'payment_instrument' => 'payment_instrument varchar(255)',
2548 'payment_instrument_id' => 'payment_instrument_id varchar(16)',
2549 'contribution_check_number' => 'contribution_check_number varchar(255)',
2550 'non_deductible_amount' => 'non_deductible_amount varchar(32)',
2551 'fee_amount' => 'fee_amount varchar(32)',
2552 'net_amount' => 'net_amount varchar(32)',
2553 'trxn_id' => 'trxn_id varchar(255)',
2554 'invoice_id' => 'invoice_id varchar(255)',
2555 'invoice_number' => 'invoice_number varchar(255)',
2556 'currency' => 'currency varchar(3)',
2557 'cancel_reason' => 'cancel_reason longtext',
2558 'receipt_date' => 'receipt_date varchar(32)',
2559 'is_test' => 'is_test varchar(16)',
2560 'is_pay_later' => 'is_pay_later varchar(16)',
2561 'contribution_status' => 'contribution_status varchar(255)',
2562 'contribution_recur_id' => 'contribution_recur_id varchar(16)',
2563 'amount_level' => 'amount_level longtext',
2564 'contribution_note' => 'contribution_note text',
2565 'contribution_batch' => 'contribution_batch text',
2566 'contribution_campaign_title' => 'contribution_campaign_title varchar(255)',
2567 'contribution_campaign_id' => 'contribution_campaign_id varchar(128)',
2568 'contribution_soft_credit_name' => 'contribution_soft_credit_name varchar(255)',
2569 'contribution_soft_credit_amount' => 'contribution_soft_credit_amount varchar(255)',
2570 'contribution_soft_credit_type' => 'contribution_soft_credit_type varchar(255)',
2571 'contribution_soft_credit_contact_id' => 'contribution_soft_credit_contact_id varchar(255)',
2572 'contribution_soft_credit_contribution_id' => 'contribution_soft_credit_contribution_id varchar(255)',
2577 * Get pledge sql columns.
2581 public function getPledgeSqlColumns() {
2583 'pledge_id' => 'pledge_id varchar(16)',
2584 'pledge_amount' => 'pledge_amount varchar(32)',
2585 'pledge_total_paid' => 'pledge_total_paid text',
2586 'pledge_create_date' => 'pledge_create_date varchar(32)',
2587 'pledge_start_date' => 'pledge_start_date text',
2588 'pledge_next_pay_date' => 'pledge_next_pay_date text',
2589 'pledge_next_pay_amount' => 'pledge_next_pay_amount text',
2590 'pledge_status' => 'pledge_status varchar(255)',
2591 'pledge_is_test' => 'pledge_is_test varchar(16)',
2592 'pledge_contribution_page_id' => 'pledge_contribution_page_id varchar(255)',
2593 'pledge_financial_type' => 'pledge_financial_type text',
2594 'pledge_frequency_interval' => 'pledge_frequency_interval varchar(255)',
2595 'pledge_frequency_unit' => 'pledge_frequency_unit varchar(255)',
2596 'pledge_currency' => 'pledge_currency text',
2597 'pledge_campaign_id' => 'pledge_campaign_id varchar(128)',
2598 'pledge_balance_amount' => 'pledge_balance_amount text',
2599 'pledge_payment_id' => 'pledge_payment_id varchar(16)',
2600 'pledge_payment_scheduled_amount' => 'pledge_payment_scheduled_amount varchar(32)',
2601 'pledge_payment_scheduled_date' => 'pledge_payment_scheduled_date varchar(32)',
2602 'pledge_payment_paid_amount' => 'pledge_payment_paid_amount text',
2603 'pledge_payment_paid_date' => 'pledge_payment_paid_date text',
2604 'pledge_payment_reminder_date' => 'pledge_payment_reminder_date varchar(32)',
2605 'pledge_payment_reminder_count' => 'pledge_payment_reminder_count varchar(16)',
2606 'pledge_payment_status' => 'pledge_payment_status varchar(255)',
2611 * Get membership sql columns.
2615 public function getMembershipSqlColumns() {
2617 'membership_type' => 'membership_type varchar(128)',
2618 'member_is_test' => 'member_is_test varchar(16)',
2619 'member_is_pay_later' => 'member_is_pay_later varchar(16)',
2620 'join_date' => 'join_date varchar(32)',
2621 'membership_start_date' => 'membership_start_date varchar(32)',
2622 'membership_end_date' => 'membership_end_date varchar(32)',
2623 'membership_source' => 'membership_source varchar(128)',
2624 'membership_status' => 'membership_status varchar(255)',
2625 'membership_id' => 'membership_id varchar(16)',
2626 'owner_membership_id' => 'owner_membership_id varchar(16)',
2627 'max_related' => 'max_related text',
2628 'membership_recur_id' => 'membership_recur_id varchar(255)',
2629 'member_campaign_id' => 'member_campaign_id varchar(128)',
2630 'member_is_override' => 'member_is_override text',
2631 'member_auto_renew' => 'member_auto_renew text',
2636 * Change our location types so we have some edge cases in the mix.
2638 * - a space in the name
2639 * - name differs from label
2640 * - non-anglo char in the label (not valid in the name).
2642 protected function diversifyLocationTypes() {
2643 $this->locationTypes
['Main'] = $this->callAPISuccess('Location_type', 'get', [
2646 'api.LocationType.Create' => ['display_name' => 'Méin'],
2648 $this->locationTypes
['Whare Kai'] = $this->callAPISuccess('Location_type', 'create', [
2649 'name' => 'Whare Kai',
2650 'display_name' => 'Whare Kai',
2655 * Test export components.
2657 * Tests the exportComponents function with the provided parameters.
2659 * This exportComponents will export a csv but it will also throw a prematureExitException
2660 * which we catch & grab the processor from.
2662 * $this->processor is set to the export processor.
2666 * @throws \CRM_Core_Exception
2667 * @throws \League\Csv\Exception
2669 protected function doExportTest($params) {
2670 $this->startCapturingOutput();
2672 $defaultClause = (empty($params['ids']) ?
NULL : "contact_a.id IN (" . implode(',', $params['ids']) . ")");
2673 CRM_Export_BAO_Export
::exportComponents(
2674 CRM_Utils_Array
::value('selectAll', $params, (empty($params['fields']))),
2675 CRM_Utils_Array
::value('ids', $params, []),
2676 CRM_Utils_Array
::value('params', $params, []),
2677 CRM_Utils_Array
::value('order', $params),
2678 CRM_Utils_Array
::value('fields', $params),
2679 CRM_Utils_Array
::value('moreReturnProperties', $params),
2680 CRM_Utils_Array
::value('exportMode', $params, CRM_Export_Form_Select
::CONTACT_EXPORT
),
2681 CRM_Utils_Array
::value('componentClause', $params, $defaultClause),
2682 CRM_Utils_Array
::value('componentTable', $params),
2683 CRM_Utils_Array
::value('mergeSameAddress', $params, FALSE),
2684 CRM_Utils_Array
::value('mergeSameHousehold', $params, FALSE)
2687 catch (CRM_Core_Exception_PrematureExitException
$e) {
2688 $this->processor
= $e->errorData
['processor'];
2689 $this->csv
= $this->captureOutputToCSV();
2692 $this->fail('We expected a premature exit exception');