Merge pull request #11921 from civicrm/5.0
[civicrm-core.git] / CRM / Report / Form / Member / Detail.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
7e9e8871 4 | CiviCRM version 4.7 |
6a488035 5 +--------------------------------------------------------------------+
8c9251b3 6 | Copyright CiviCRM LLC (c) 2004-2018 |
6a488035
TO
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
d25dd0ee 26 */
6a488035
TO
27
28/**
29 *
30 * @package CRM
8c9251b3 31 * @copyright CiviCRM LLC (c) 2004-2018
6a488035
TO
32 */
33class CRM_Report_Form_Member_Detail extends CRM_Report_Form {
34
6a488035
TO
35 protected $_summary = NULL;
36
804f9330
DJ
37 protected $_customGroupExtends = array(
38 'Membership',
39 'Contribution',
40 'Contact',
41 'Individual',
42 'Household',
43 'Organization',
44 );
45
f813f78e 46 protected $_customGroupGroupBy = FALSE;
47
1728e9a0 48 /**
49 * This report has not been optimised for group filtering.
50 *
51 * The functionality for group filtering has been improved but not
52 * all reports have been adjusted to take care of it. This report has not
53 * and will run an inefficient query until fixed.
54 *
55 * CRM-19170
56 *
57 * @var bool
58 */
eae0f0d9 59 protected $groupFilterNotOptimised = FALSE;
1728e9a0 60
74cf4551 61 /**
e5575773 62 * Class constructor.
74cf4551 63 */
00be9182 64 public function __construct() {
f813f78e 65
66 // Check if CiviCampaign is a) enabled and b) has active campaigns
244200e1 67 $config = CRM_Core_Config::singleton();
0211a554
DL
68 $campaignEnabled = in_array("CiviCampaign", $config->enableComponents);
69 if ($campaignEnabled) {
70 $getCampaigns = CRM_Campaign_BAO_Campaign::getPermissionedCampaigns(NULL, NULL, TRUE, FALSE, TRUE);
71 $this->activeCampaigns = $getCampaigns['campaigns'];
72 asort($this->activeCampaigns);
73 }
f813f78e 74
6a488035 75 $this->_columns = array(
1e887757
EM
76 'civicrm_contact' => array(
77 'dao' => 'CRM_Contact_DAO_Contact',
e5575773 78 'fields' => $this->getBasicContactFields(),
1e887757
EM
79 'filters' => array(
80 'sort_name' => array(
81 'title' => ts('Contact Name'),
82 'operator' => 'like',
83 ),
bc390081
JP
84 'is_deleted' => array(
85 'title' => ts('Is Deleted'),
86 'default' => 0,
87 'type' => CRM_Utils_Type::T_BOOLEAN,
88 ),
1e887757
EM
89 'id' => array('no_display' => TRUE),
90 ),
91 'order_bys' => array(
92 'sort_name' => array(
93 'title' => ts('Last Name, First Name'),
94 'default' => '1',
95 'default_weight' => '0',
21dfd5f5 96 'default_order' => 'ASC',
8cab7c88 97 ),
6a488035 98 ),
1e887757
EM
99 'grouping' => 'contact-fields',
100 ),
8cab7c88
EM
101 'civicrm_membership' => array(
102 'dao' => 'CRM_Member_DAO_Membership',
103 'fields' => array(
104 'membership_type_id' => array(
ccc29f8e 105 'title' => ts('Membership Type'),
8cab7c88
EM
106 'required' => TRUE,
107 'no_repeat' => TRUE,
108 ),
109 'membership_start_date' => array(
110 'title' => ts('Start Date'),
111 'default' => TRUE,
112 ),
113 'membership_end_date' => array(
114 'title' => ts('End Date'),
115 'default' => TRUE,
116 ),
117 'join_date' => array(
118 'title' => ts('Join Date'),
119 'default' => TRUE,
120 ),
ccc29f8e 121 'source' => array('title' => ts('Source')),
244200e1 122 ),
8cab7c88
EM
123 'filters' => array(
124 'join_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
125 'membership_start_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
126 'membership_end_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
127 'owner_membership_id' => array(
128 'title' => ts('Membership Owner ID'),
129 'operatorType' => CRM_Report_Form::OP_INT,
130 ),
131 'tid' => array(
132 'name' => 'membership_type_id',
133 'title' => ts('Membership Types'),
134 'type' => CRM_Utils_Type::T_INT,
135 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
136 'options' => CRM_Member_PseudoConstant::membershipType(),
137 ),
6a488035 138 ),
8d44b023
J
139 'order_bys' => array(
140 'membership_type_id' => array(
141 'title' => ts('Membership Type'),
142 'default' => '0',
143 'default_weight' => '1',
144 'default_order' => 'ASC',
145 ),
146 ),
8cab7c88 147 'grouping' => 'member-fields',
490a6f02 148 'group_bys' => array(
149 'id' => array(
150 'title' => ts('Membership'),
151 'default' => TRUE,
152 ),
153 ),
8cab7c88
EM
154 ),
155 'civicrm_membership_status' => array(
156 'dao' => 'CRM_Member_DAO_MembershipStatus',
157 'alias' => 'mem_status',
158 'fields' => array(
159 'name' => array(
160 'title' => ts('Status'),
161 'default' => TRUE,
162 ),
163 ),
164 'filters' => array(
165 'sid' => array(
166 'name' => 'id',
167 'title' => ts('Status'),
168 'type' => CRM_Utils_Type::T_INT,
169 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
170 'options' => CRM_Member_PseudoConstant::membershipStatus(NULL, NULL, 'label'),
171 ),
172 ),
173 'grouping' => 'member-fields',
174 ),
8cab7c88
EM
175 'civicrm_email' => array(
176 'dao' => 'CRM_Core_DAO_Email',
177 'fields' => array('email' => NULL),
178 'grouping' => 'contact-fields',
179 ),
180 'civicrm_phone' => array(
181 'dao' => 'CRM_Core_DAO_Phone',
182 'fields' => array('phone' => NULL),
183 'grouping' => 'contact-fields',
184 ),
185 'civicrm_contribution' => array(
186 'dao' => 'CRM_Contribute_DAO_Contribution',
187 'fields' => array(
188 'contribution_id' => array(
189 'name' => 'id',
190 'no_display' => TRUE,
191 'required' => TRUE,
192 ),
193 'financial_type_id' => array('title' => ts('Financial Type')),
194 'contribution_status_id' => array('title' => ts('Contribution Status')),
195 'payment_instrument_id' => array('title' => ts('Payment Type')),
196 'currency' => array(
197 'required' => TRUE,
198 'no_display' => TRUE,
199 ),
200 'trxn_id' => NULL,
201 'receive_date' => NULL,
202 'receipt_date' => NULL,
203 'fee_amount' => NULL,
204 'net_amount' => NULL,
205 'total_amount' => array(
206 'title' => ts('Payment Amount (most recent)'),
207 'statistics' => array('sum' => ts('Amount')),
208 ),
6a488035 209 ),
8cab7c88
EM
210 'filters' => array(
211 'receive_date' => array('operatorType' => CRM_Report_Form::OP_DATE),
212 'financial_type_id' => array(
213 'title' => ts('Financial Type'),
214 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
215 'options' => CRM_Contribute_PseudoConstant::financialType(),
216 'type' => CRM_Utils_Type::T_INT,
217 ),
218 'payment_instrument_id' => array(
219 'title' => ts('Payment Type'),
220 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
221 'options' => CRM_Contribute_PseudoConstant::paymentInstrument(),
222 'type' => CRM_Utils_Type::T_INT,
223 ),
224 'currency' => array(
ccc29f8e 225 'title' => ts('Currency'),
8cab7c88
EM
226 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
227 'options' => CRM_Core_OptionGroup::values('currencies_enabled'),
228 'default' => NULL,
229 'type' => CRM_Utils_Type::T_STRING,
230 ),
231 'contribution_status_id' => array(
232 'title' => ts('Contribution Status'),
233 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
234 'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
235 'type' => CRM_Utils_Type::T_INT,
236 ),
237 'total_amount' => array('title' => ts('Contribution Amount')),
238 ),
8d44b023
J
239 'order_bys' => array(
240 'receive_date' => array(
7bc6b5bb 241 'title' => ts('Date Received'),
8d44b023
J
242 'default_weight' => '2',
243 'default_order' => 'DESC',
244 ),
245 ),
8cab7c88
EM
246 'grouping' => 'contri-fields',
247 ),
e5575773 248 ) + $this->getAddressColumns(array(
249 // These options are only excluded because they were not previously present.
250 'order_by' => FALSE,
251 'group_by' => FALSE,
252 ));
6a488035
TO
253 $this->_groupFilter = TRUE;
254 $this->_tagFilter = TRUE;
fdb63ad1 255
244200e1 256 // If we have active campaigns add those elements to both the fields and filters
0211a554 257 if ($campaignEnabled && !empty($this->activeCampaigns)) {
e3dfdfc3 258 $this->_columns['civicrm_membership']['fields']['campaign_id'] = array(
0211a554
DL
259 'title' => ts('Campaign'),
260 'default' => 'false',
261 );
244200e1
EM
262 $this->_columns['civicrm_membership']['filters']['campaign_id'] = array(
263 'title' => ts('Campaign'),
0211a554
DL
264 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
265 'options' => $this->activeCampaigns,
942b1d01 266 'type' => CRM_Utils_Type::T_INT,
0211a554 267 );
e3dfdfc3 268 $this->_columns['civicrm_membership']['order_bys']['campaign_id'] = array('title' => ts('Campaign'));
5752b04f 269
0211a554
DL
270 }
271
fdb63ad1 272 $this->_currencyColumn = 'civicrm_contribution_currency';
6a488035
TO
273 parent::__construct();
274 }
275
00be9182 276 public function preProcess() {
6a488035
TO
277 $this->assign('reportTitle', ts('Membership Detail Report'));
278 parent::preProcess();
279 }
280
00be9182 281 public function from() {
eae0f0d9 282 $this->setFromBase('civicrm_contact');
283 $this->_from .= "
284 {$this->_aclFrom}
f813f78e 285 INNER JOIN civicrm_membership {$this->_aliases['civicrm_membership']}
286 ON {$this->_aliases['civicrm_contact']}.id =
6a488035
TO
287 {$this->_aliases['civicrm_membership']}.contact_id AND {$this->_aliases['civicrm_membership']}.is_test = 0
288 LEFT JOIN civicrm_membership_status {$this->_aliases['civicrm_membership_status']}
f813f78e 289 ON {$this->_aliases['civicrm_membership_status']}.id =
6a488035
TO
290 {$this->_aliases['civicrm_membership']}.status_id ";
291
183af103 292 $this->joinAddressFromContact();
293 $this->joinPhoneFromContact();
294 $this->joinEmailFromContact();
e5575773 295
4b885f84 296 //used when contribution field is selected.
297 if ($this->isTableSelected('civicrm_contribution')) {
6a488035 298 $this->_from .= "
06d4bf4d
TO
299 LEFT JOIN civicrm_membership_payment cmp
300 ON {$this->_aliases['civicrm_membership']}.id = cmp.membership_id
fb7829f2 301 LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
06d4bf4d 302 ON cmp.contribution_id={$this->_aliases['civicrm_contribution']}.id\n";
6a488035
TO
303 }
304 }
305
00be9182 306 public function postProcess() {
6a488035
TO
307
308 $this->beginPostProcess();
309
310 // get the acl clauses built before we assemble the query
311 $this->buildACLClause($this->_aliases['civicrm_contact']);
312 $sql = $this->buildQuery(TRUE);
313
314 $rows = array();
315 $this->buildRows($sql, $rows);
316
317 $this->formatDisplay($rows);
318 $this->doTemplateAssignment($rows);
319 $this->endPostProcess($rows);
320 }
321
74cf4551 322 /**
ced9bfed
EM
323 * Alter display of rows.
324 *
325 * Iterate through the rows retrieved via SQL and make changes for display purposes,
326 * such as rendering contacts as links.
327 *
328 * @param array $rows
329 * Rows generated by SQL, with an array for each row.
74cf4551 330 */
00be9182 331 public function alterDisplay(&$rows) {
6a488035
TO
332 $entryFound = FALSE;
333 $checkList = array();
f813f78e 334
244200e1 335 $contributionTypes = CRM_Contribute_PseudoConstant::financialType();
6a488035
TO
336 $contributionStatus = CRM_Contribute_PseudoConstant::contributionStatus();
337 $paymentInstruments = CRM_Contribute_PseudoConstant::paymentInstrument();
f813f78e 338
2ac6b1ce 339 $repeatFound = FALSE;
6a488035 340 foreach ($rows as $rowNum => $row) {
2ac6b1ce
J
341 if ($repeatFound == FALSE ||
342 $repeatFound < $rowNum - 1
343 ) {
344 unset($checkList);
345 $checkList = array();
346 }
6a488035
TO
347 if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
348 // not repeat contact display names if it matches with the one
349 // in previous row
6a488035 350 foreach ($row as $colName => $colVal) {
a5658df0
J
351 if (in_array($colName, $this->_noRepeats) &&
352 $rowNum > 0
6a488035 353 ) {
a5658df0
J
354 if ($rows[$rowNum][$colName] == $rows[$rowNum - 1][$colName] ||
355 (!empty($checkList[$colName]) &&
356 in_array($colVal, $checkList[$colName]))
357 ) {
358 $rows[$rowNum][$colName] = "";
359 // CRM-15917: Don't blank the name if it's a different contact
64e8aa73 360 if ($colName == 'civicrm_contact_exposed_id') {
a5658df0
J
361 $rows[$rowNum]['civicrm_contact_sort_name'] = "";
362 }
2ac6b1ce 363 $repeatFound = $rowNum;
5ac295e6 364 }
6a488035
TO
365 }
366 if (in_array($colName, $this->_noRepeats)) {
367 $checkList[$colName][] = $colVal;
368 }
369 }
370 }
371
372 if (array_key_exists('civicrm_membership_membership_type_id', $row)) {
373 if ($value = $row['civicrm_membership_membership_type_id']) {
374 $rows[$rowNum]['civicrm_membership_membership_type_id'] = CRM_Member_PseudoConstant::membershipType($value, FALSE);
375 }
376 $entryFound = TRUE;
377 }
378
379 if (array_key_exists('civicrm_address_state_province_id', $row)) {
380 if ($value = $row['civicrm_address_state_province_id']) {
381 $rows[$rowNum]['civicrm_address_state_province_id'] = CRM_Core_PseudoConstant::stateProvince($value, FALSE);
382 }
383 $entryFound = TRUE;
384 }
385
386 if (array_key_exists('civicrm_address_country_id', $row)) {
387 if ($value = $row['civicrm_address_country_id']) {
388 $rows[$rowNum]['civicrm_address_country_id'] = CRM_Core_PseudoConstant::country($value, FALSE);
389 }
390 $entryFound = TRUE;
391 }
392
393 if (array_key_exists('civicrm_contact_sort_name', $row) &&
394 $rows[$rowNum]['civicrm_contact_sort_name'] &&
395 array_key_exists('civicrm_contact_id', $row)
396 ) {
397 $url = CRM_Utils_System::url("civicrm/contact/view",
398 'reset=1&cid=' . $row['civicrm_contact_id'],
399 $this->_absoluteUrl
400 );
401 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
402 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
403 $entryFound = TRUE;
404 }
f813f78e 405
6a488035
TO
406 if ($value = CRM_Utils_Array::value('civicrm_contribution_financial_type_id', $row)) {
407 $rows[$rowNum]['civicrm_contribution_financial_type_id'] = $contributionTypes[$value];
408 $entryFound = TRUE;
409 }
410 if ($value = CRM_Utils_Array::value('civicrm_contribution_contribution_status_id', $row)) {
411 $rows[$rowNum]['civicrm_contribution_contribution_status_id'] = $contributionStatus[$value];
412 $entryFound = TRUE;
413 }
414 if ($value = CRM_Utils_Array::value('civicrm_contribution_payment_instrument_id', $row)) {
415 $rows[$rowNum]['civicrm_contribution_payment_instrument_id'] = $paymentInstruments[$value];
416 $entryFound = TRUE;
417 }
418
0211a554 419 // Convert campaign_id to campaign title
229c2785
CD
420 if (array_key_exists('civicrm_membership_campaign_id', $row)) {
421 if ($value = $row['civicrm_membership_campaign_id']) {
422 $rows[$rowNum]['civicrm_membership_campaign_id'] = $this->activeCampaigns[$value];
0211a554
DL
423 $entryFound = TRUE;
424 }
425 }
e5575773 426 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'member/detail', 'List all memberships(s) for this ') ? TRUE : $entryFound;
7a4192f7 427 $entryFound = $this->alterDisplayContactFields($row, $rows, $rowNum, 'member/detail', 'List all memberships(s) for this ') ? TRUE : $entryFound;
0211a554 428
6a488035
TO
429 if (!$entryFound) {
430 break;
431 }
432 }
433 }
96025800 434
6a488035 435}