From f6493dcdbaf62babb3e5e6a83f0f761ccbd714a2 Mon Sep 17 00:00:00 2001 From: Seamus Lee Date: Thu, 1 Aug 2019 15:49:07 +1000 Subject: [PATCH] Allow extensions to join address, email and phone tables without limiting to primary fields --- CRM/Report/Form.php | 42 +++++++++++++++---- .../CRM/Report/Form/ContactSummaryTest.php | 20 ++++++++- 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/CRM/Report/Form.php b/CRM/Report/Form.php index 73c4f561f16a..248bc64a278d 100644 --- a/CRM/Report/Form.php +++ b/CRM/Report/Form.php @@ -4711,6 +4711,8 @@ public function addPhoneFromClause() { * Not currently used in core but may be used in override extensions. */ protected function joinAddressFromContact($prefix = '', $extra = []) { + $defaults = ['primary_only' => TRUE]; + $params = array_merge($defaults, $extra); $addressTables = ['civicrm_address', 'civicrm_country', 'civicrm_worldregion', 'civicrm_state_province']; $isJoinRequired = $this->_addressField; foreach ($addressTables as $addressTable) { @@ -4719,11 +4721,15 @@ protected function joinAddressFromContact($prefix = '', $extra = []) { } } if ($isJoinRequired) { - $this->_from .= " + $fromJoin = " LEFT JOIN civicrm_address {$this->_aliases[$prefix . 'civicrm_address']} ON ({$this->_aliases[$prefix . 'civicrm_contact']}.id = - {$this->_aliases[$prefix . 'civicrm_address']}.contact_id) AND + {$this->_aliases[$prefix . 'civicrm_address']}.contact_id)"; + if ($params['primary_only']) { + $fromJoin .= " AND {$this->_aliases[$prefix . 'civicrm_address']}.is_primary = 1\n"; + } + $this->_from .= $fromJoin; } } @@ -4738,15 +4744,21 @@ protected function joinAddressFromContact($prefix = '', $extra = []) { * Not currently used in core but may be used in override extensions. */ protected function joinCountryFromAddress($prefix = '', $extra = []) { + $defaults = ['primary_only' => TRUE]; + $params = array_merge($defaults, $extra); // include country field if country column is to be included if ($this->isTableSelected($prefix . 'civicrm_country') || $this->isTableSelected($prefix . 'civicrm_worldregion')) { if (empty($this->_aliases[$prefix . 'civicrm_country'])) { $this->_aliases[$prefix . 'civicrm_country'] = $prefix . '_report_country'; } - $this->_from .= " + $fromJoin = " LEFT JOIN civicrm_country {$this->_aliases[$prefix . 'civicrm_country']} - ON {$this->_aliases[$prefix . 'civicrm_address']}.country_id = {$this->_aliases[$prefix . 'civicrm_country']}.id AND + ON {$this->_aliases[$prefix . 'civicrm_address']}.country_id = {$this->_aliases[$prefix . 'civicrm_country']}.id"; + if ($params['primary_only']) { + $fromJoin .= " AND {$this->_aliases[$prefix . 'civicrm_address']}.is_primary = 1 "; + } + $this->_from .= $fromJoin; } } @@ -4761,12 +4773,18 @@ protected function joinCountryFromAddress($prefix = '', $extra = []) { * Not currently used in core but may be used in override extensions. */ protected function joinPhoneFromContact($prefix = '', $extra = []) { + $defaults = ['primary_only' => TRUE]; + $params = array_merge($defaults, $extra); // include phone field if phone column is to be included if ($this->isTableSelected($prefix . 'civicrm_phone')) { - $this->_from .= " + $fromJoin = " LEFT JOIN civicrm_phone {$this->_aliases[$prefix . 'civicrm_phone']} - ON {$this->_aliases[$prefix . 'civicrm_contact']}.id = {$this->_aliases[$prefix . 'civicrm_phone']}.contact_id AND + ON {$this->_aliases[$prefix . 'civicrm_contact']}.id = {$this->_aliases[$prefix . 'civicrm_phone']}.contact_id"; + if ($params['primary_only']) { + $fromJoin .= " AND {$this->_aliases[$prefix . 'civicrm_phone']}.is_primary = 1\n"; + } + $this->_from .= $fromJoin; } } @@ -4781,12 +4799,18 @@ protected function joinPhoneFromContact($prefix = '', $extra = []) { * Not currently used in core but may be used in override extensions. */ protected function joinEmailFromContact($prefix = '', $extra = []) { + $defaults = ['primary_only' => TRUE]; + $params = array_merge($defaults, $extra); // include email field if email column is to be included if ($this->isTableSelected($prefix . 'civicrm_email')) { - $this->_from .= " + $fromJoin = " LEFT JOIN civicrm_email {$this->_aliases[$prefix . 'civicrm_email']} - ON ({$this->_aliases[$prefix . 'civicrm_contact']}.id = {$this->_aliases[$prefix . 'civicrm_email']}.contact_id AND - {$this->_aliases[$prefix . 'civicrm_email']}.is_primary = 1) "; + ON {$this->_aliases[$prefix . 'civicrm_contact']}.id = {$this->_aliases[$prefix . 'civicrm_email']}.contact_id"; + if ($params['primary_only']) { + $fromJoin .= " AND + {$this->_aliases[$prefix . 'civicrm_email']}.is_primary = 1 "; + } + $this->_from .= $fromJoin; } } diff --git a/tests/phpunit/CRM/Report/Form/ContactSummaryTest.php b/tests/phpunit/CRM/Report/Form/ContactSummaryTest.php index b173d4d462db..9a05133235ae 100644 --- a/tests/phpunit/CRM/Report/Form/ContactSummaryTest.php +++ b/tests/phpunit/CRM/Report/Form/ContactSummaryTest.php @@ -51,6 +51,11 @@ public function tearDown() { * Ensure the new Odd/Event street number sort column works correctly */ public function testOddEvenStreetNumber() { + $customLocationType = $this->callAPISuccess('LocationType', 'create', [ + 'name' => 'Custom Location Type', + 'display_name' => 'CiviTest Custom Location Type', + 'is_active' => 1, + ]); // Create 5 contacts where: // Contact A - Odd Street number - 3 // Contact B - Odd Street number - 5 @@ -88,7 +93,13 @@ public function testOddEvenStreetNumber() { ]), 'no_street_number' => $this->individualCreate(), ]; - + // Create a non primary address to check that we are only outputting primary contact details. + $this->callAPISuccess('Address', 'create', [ + 'contact_id' => $contactIDs['even_street_number_2'], + 'location_type_id' => $customLocationType['id'], + 'is_primary' => 0, + 'street_number' => 6, + ]); $input = [ 'fields' => [ 'address_street_number', @@ -193,7 +204,14 @@ public function testOddEvenStreetNumber() { $this->assertEquals($case['expected_contact_ids'], CRM_Utils_Array::collect('civicrm_contact_id', $rows)); // check the order clause $this->assertEquals(TRUE, !empty(strstr($sql, $case['expected_orderby_clause']))); + // Ensure that we are only fetching primary fields. + foreach ($rows as $row) { + if ($row['civicrm_contact_id'] == $contactIDs['even_street_number_2']) { + $this->assertEquals(4, $row['civicrm_address_address_street_number']); + } + } } + $this->callAPISuccess('LocationType', 'Delete', ['id' => $customLocationType['id']]); } }