Merge pull request #22316 from braders/core-3003-preserve-tab-between-pageloads
[civicrm-core.git] / CRM / Report / Form / Contribute / PCP.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
bc77d7c0 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
bc77d7c0
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035 9 +--------------------------------------------------------------------+
d25dd0ee 10 */
6a488035
TO
11
12/**
13 *
14 * @package CRM
ca5cec67 15 * @copyright CiviCRM LLC https://civicrm.org/licensing
6a488035
TO
16 */
17class CRM_Report_Form_Contribute_PCP extends CRM_Report_Form {
73b448bf 18
74cf4551 19 /**
73b448bf 20 * Class constructor.
74cf4551 21 */
00be9182 22 public function __construct() {
be2fb01f
CW
23 $this->_columns = [
24 'civicrm_contact' => [
6a488035 25 'dao' => 'CRM_Contact_DAO_Contact',
be2fb01f
CW
26 'fields' => [
27 'sort_name' => [
9d72cede 28 'title' => ts('Supporter'),
6a488035
TO
29 'required' => TRUE,
30 'default' => TRUE,
be2fb01f
CW
31 ],
32 'id' => [
6a488035
TO
33 'required' => TRUE,
34 'no_display' => TRUE,
be2fb01f
CW
35 ],
36 'contact_type' => [
30f85891 37 'title' => ts('Supporter Contact Type'),
be2fb01f
CW
38 ],
39 'contact_sub_type' => [
b8f96eb8 40 'title' => ts('Supporter Contact Subtype'),
be2fb01f
CW
41 ],
42 ],
43 'filters' => [
44 'sort_name' => [
9d72cede 45 'title' => ts('Supporter Name'),
6a488035
TO
46 'type' => CRM_Utils_Type::T_STRING,
47 'operator' => 'like',
be2fb01f
CW
48 ],
49 'id' => [
9d72cede 50 'title' => ts('Contact ID'),
6a488035 51 'no_display' => TRUE,
be2fb01f
CW
52 ],
53 ],
6a488035 54 'grouping' => 'pcp-fields',
be2fb01f
CW
55 ],
56 'civicrm_contribution_page' => [
6a488035 57 'dao' => 'CRM_Contribute_DAO_ContributionPage',
39bad6a6 58 'alias' => 'cp',
be2fb01f
CW
59 'fields' => [
60 'page_title' => [
39bad6a6 61 'title' => ts('Page Title'),
6a488035 62 'name' => 'title',
39bad6a6 63 'dbAlias' => 'coalesce(cp_civireport.title, e_civireport.title)',
6a488035 64 'default' => TRUE,
be2fb01f
CW
65 ],
66 ],
67 'filters' => [
68 'page_title' => [
9d72cede 69 'title' => ts('Contribution Page Title'),
6a488035
TO
70 'name' => 'title',
71 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
72 ],
73 ],
6a488035 74 'grouping' => 'pcp-fields',
be2fb01f
CW
75 ],
76 'civicrm_event' => [
39bad6a6 77 'alias' => 'e',
be2fb01f
CW
78 'filters' => [
79 'event_title' => [
39bad6a6
AS
80 'title' => ts('Event Title'),
81 'name' => 'title',
82 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
83 ],
84 ],
39bad6a6 85 'grouping' => 'pcp-fields',
be2fb01f
CW
86 ],
87 'civicrm_pcp' => [
6a488035 88 'dao' => 'CRM_PCP_DAO_PCP',
be2fb01f
CW
89 'fields' => [
90 'title' => [
9d72cede 91 'title' => ts('Personal Campaign Title'),
6a488035 92 'default' => TRUE,
be2fb01f
CW
93 ],
94 'page_type' => [
39bad6a6
AS
95 'title' => ts('Page Type'),
96 'default' => FALSE,
be2fb01f
CW
97 ],
98 'goal_amount' => [
9d72cede 99 'title' => ts('Goal Amount'),
6a488035
TO
100 'type' => CRM_Utils_Type::T_MONEY,
101 'default' => TRUE,
be2fb01f
CW
102 ],
103 ],
104 'filters' => [
105 'title' => [
9d72cede 106 'title' => ts('Personal Campaign Title'),
6a488035 107 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
108 ],
109 ],
110 'group_bys' => [
111 'pcp_id' => [
e40ce31e
JM
112 'name' => 'id',
113 'required' => TRUE,
114 'default' => TRUE,
115 'title' => ts('Personal Campaign Page'),
be2fb01f
CW
116 ],
117 ],
6a488035 118 'grouping' => 'pcp-fields',
be2fb01f
CW
119 ],
120 'civicrm_contribution_soft' => [
6a488035 121 'dao' => 'CRM_Contribute_DAO_ContributionSoft',
be2fb01f
CW
122 'fields' => [
123 'amount_1' => [
9d72cede 124 'title' => ts('Committed Amount'),
6a488035
TO
125 'name' => 'amount',
126 'type' => CRM_Utils_Type::T_MONEY,
127 'default' => TRUE,
be2fb01f 128 'statistics' => [
9d72cede 129 'sum' => ts('Committed Amount'),
be2fb01f
CW
130 ],
131 ],
132 'amount_2' => [
9d72cede 133 'title' => ts('Amount Received'),
6a488035
TO
134 'name' => 'amount',
135 'type' => CRM_Utils_Type::T_MONEY,
136 'default' => TRUE,
137 // nice trick with dbAlias
138 'dbAlias' => 'SUM(IF( contribution_civireport.contribution_status_id > 1, 0, contribution_soft_civireport.amount))',
be2fb01f
CW
139 ],
140 'soft_id' => [
9d72cede 141 'title' => ts('Number of Donors'),
6a488035
TO
142 'name' => 'id',
143 'default' => TRUE,
be2fb01f 144 'statistics' => [
9d72cede 145 'count' => ts('Number of Donors'),
be2fb01f
CW
146 ],
147 ],
148 ],
149 'filters' => [
150 'amount_2' => [
9d72cede 151 'title' => ts('Amount Received'),
6a488035
TO
152 'type' => CRM_Utils_Type::T_MONEY,
153 'dbAlias' => 'SUM(IF( contribution_civireport.contribution_status_id > 1, 0, contribution_soft_civireport.amount))',
be2fb01f
CW
154 ],
155 ],
6a488035 156 'grouping' => 'pcp-fields',
be2fb01f
CW
157 ],
158 'civicrm_contribution' => [
6a488035 159 'dao' => 'CRM_Contribute_DAO_Contribution',
be2fb01f
CW
160 'fields' => [
161 'contribution_id' => [
6a488035
TO
162 'name' => 'id',
163 'no_display' => TRUE,
164 'required' => TRUE,
be2fb01f
CW
165 ],
166 'receive_date' => [
9d72cede 167 'title' => ts('Most Recent Contribution'),
6a488035 168 'default' => TRUE,
be2fb01f 169 'statistics' => [
9d72cede 170 'max' => ts('Most Recent Contribution'),
be2fb01f
CW
171 ],
172 ],
cfd9f6cf
JM
173 ],
174 'filters' => [
175 'contribution_status_id' => [
176 'title' => ts('Contribution Status'),
177 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
178 'options' => CRM_Contribute_PseudoConstant::contributionStatus(),
179 'default' => [1],
180 ],
be2fb01f 181 ],
6a488035 182 'grouping' => 'pcp-fields',
be2fb01f
CW
183 ],
184 'civicrm_financial_trxn' => [
d2a1da52 185 'dao' => 'CRM_Financial_DAO_FinancialTrxn',
be2fb01f
CW
186 'fields' => [
187 'card_type_id' => [
d72b084a 188 'title' => ts('Credit Card Type'),
5e0343e8 189 'dbAlias' => 'GROUP_CONCAT(financial_trxn_civireport.card_type_id SEPARATOR ",")',
be2fb01f
CW
190 ],
191 ],
192 'filters' => [
193 'card_type_id' => [
d72b084a 194 'title' => ts('Credit Card Type'),
d2a1da52 195 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
5e0343e8 196 'options' => CRM_Financial_DAO_FinancialTrxn::buildOptions('card_type_id'),
d2a1da52
ERL
197 'default' => NULL,
198 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
199 ],
200 ],
201 ],
202 ];
6a488035
TO
203
204 parent::__construct();
e40ce31e 205 $this->optimisedForOnlyFullGroupBy = FALSE;
6a488035
TO
206 }
207
00be9182 208 public function from() {
6a488035
TO
209 $this->_from = "
210FROM civicrm_pcp {$this->_aliases['civicrm_pcp']}
211
2f4c2f5d 212LEFT JOIN civicrm_contribution_soft {$this->_aliases['civicrm_contribution_soft']}
213 ON {$this->_aliases['civicrm_pcp']}.id =
6a488035
TO
214 {$this->_aliases['civicrm_contribution_soft']}.pcp_id
215
2f4c2f5d 216LEFT JOIN civicrm_contribution {$this->_aliases['civicrm_contribution']}
217 ON {$this->_aliases['civicrm_contribution_soft']}.contribution_id =
6a488035
TO
218 {$this->_aliases['civicrm_contribution']}.id
219
2f4c2f5d 220LEFT JOIN civicrm_contact {$this->_aliases['civicrm_contact']}
221 ON {$this->_aliases['civicrm_pcp']}.contact_id =
222 {$this->_aliases['civicrm_contact']}.id
6a488035
TO
223
224LEFT JOIN civicrm_contribution_page {$this->_aliases['civicrm_contribution_page']}
2f4c2f5d 225 ON {$this->_aliases['civicrm_pcp']}.page_id =
39bad6a6
AS
226 {$this->_aliases['civicrm_contribution_page']}.id
227 AND {$this->_aliases['civicrm_pcp']}.page_type = 'contribute'
228
229LEFT JOIN civicrm_event {$this->_aliases['civicrm_event']}
230 ON {$this->_aliases['civicrm_pcp']}.page_id =
231 {$this->_aliases['civicrm_event']}.id
232 AND {$this->_aliases['civicrm_pcp']}.page_type = 'event'";
d2a1da52
ERL
233
234 // for credit card type
235 $this->addFinancialTrxnFromClause();
6a488035
TO
236 }
237
00be9182 238 public function orderBy() {
6a488035
TO
239 $this->_orderBy = " ORDER BY {$this->_aliases['civicrm_contact']}.sort_name ";
240 }
241
00be9182 242 public function where() {
be2fb01f 243 $whereClauses = $havingClauses = [];
6a488035
TO
244
245 foreach ($this->_columns as $tableName => $table) {
246 if (array_key_exists('filters', $table)) {
247 foreach ($table['filters'] as $fieldName => $field) {
248 $clause = NULL;
249
250 if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
9c1bc317
CW
251 $relative = $this->_params["{$fieldName}_relative"] ?? NULL;
252 $from = $this->_params["{$fieldName}_from"] ?? NULL;
253 $to = $this->_params["{$fieldName}_to"] ?? NULL;
9d72cede 254 $clause = $this->dateClause($field['name'], $relative, $from, $to, $field['type']);
6a488035
TO
255 }
256 else {
9c1bc317 257 $op = $this->_params["{$fieldName}_op"] ?? NULL;
6a488035
TO
258
259 if ($op) {
260 $clause = $this->whereClause($field,
261 $op,
262 CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
263 CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
264 CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
265 );
266 }
267 }
268
269 if (!empty($clause)) {
270 if ($tableName == 'civicrm_contribution_soft' &&
271 $fieldName == 'amount_2'
272 ) {
273 $havingClauses[] = $clause;
274 }
275 else {
276 $whereClauses[] = $clause;
277 }
278 }
279 }
280 }
281 }
282 if (empty($whereClauses)) {
283 $this->_where = "WHERE ( 1 ) ";
284 }
285 else {
286 $this->_where = "WHERE " . implode(' AND ', $whereClauses);
287 }
288 if ($this->_aclWhere) {
289 $this->_where .= " AND {$this->_aclWhere} ";
290 }
291 $this->_having = "";
292 if (!empty($havingClauses)) {
293 // use this clause to construct group by clause.
294 $this->_having = "HAVING " . implode(' AND ', $havingClauses);
295 }
296 }
297
74cf4551 298 /**
71d8f758 299 * @param array $rows
74cf4551
EM
300 *
301 * @return array
302 */
00be9182 303 public function statistics(&$rows) {
ecd4d80f
JM
304 $statistics = parent::statistics($rows);
305
ea9ec579 306 // Calculate totals from the civicrm_contribution_soft table.
17dea6fa
JM
307 $select = "SELECT SUM({$this->_aliases['civicrm_contribution_soft']}.amount) "
308 . "as committed_total, COUNT({$this->_aliases['civicrm_contribution_soft']}.id) "
309 . "as donors_total, SUM(IF( contribution_civireport.contribution_status_id > 1, 0, "
310 . "contribution_soft_civireport.amount)) AS received_total ";
ecd4d80f
JM
311 $sql = "{$select} {$this->_from} {$this->_where}";
312 $dao = CRM_Core_DAO::executeQuery($sql);
313 $dao->fetch();
ea9ec579
JM
314 $committed_total = $dao->committed_total;
315 $received_total = $dao->received_total;
7a99327d 316 $donors_total = $dao->donors_total;
ea9ec579
JM
317
318 // Calculate goal total goal from the PCP table (we only want one result per
319 // PCP page - the query above produces one result per contribution made).
17dea6fa
JM
320 $sql = "SELECT SUM(goal_amount) as goal_total FROM civicrm_pcp WHERE "
321 . "goal_amount IS NOT NULL AND id IN ("
322 . "SELECT DISTINCT {$this->_aliases['civicrm_pcp']}.id {$this->_from} "
323 . "{$this->_where}"
324 . ")";
ea9ec579
JM
325 $dao = CRM_Core_DAO::executeQuery($sql);
326 $dao->fetch();
327 $goal_total = $dao->goal_total;
328
be2fb01f 329 $statistics['counts']['goal_total'] = [
ecd4d80f 330 'title' => ts('Goal Total'),
ea9ec579 331 'value' => $goal_total,
21dfd5f5 332 'type' => CRM_Utils_Type::T_MONEY,
be2fb01f
CW
333 ];
334 $statistics['counts']['committed_total'] = [
ecd4d80f 335 'title' => ts('Total Committed'),
ea9ec579 336 'value' => $committed_total,
21dfd5f5 337 'type' => CRM_Utils_Type::T_MONEY,
be2fb01f
CW
338 ];
339 $statistics['counts']['received_total'] = [
ecd4d80f 340 'title' => ts('Total Received'),
ea9ec579 341 'value' => $received_total,
21dfd5f5 342 'type' => CRM_Utils_Type::T_MONEY,
be2fb01f
CW
343 ];
344 $statistics['counts']['donors_total'] = [
ecd4d80f 345 'title' => ts('Total Donors'),
ea9ec579 346 'value' => $donors_total,
21dfd5f5 347 'type' => CRM_Utils_Type::T_INT,
be2fb01f 348 ];
ecd4d80f
JM
349 return $statistics;
350 }
74cf4551
EM
351
352 /**
ced9bfed
EM
353 * Alter display of rows.
354 *
355 * Iterate through the rows retrieved via SQL and make changes for display purposes,
356 * such as rendering contacts as links.
357 *
358 * @param array $rows
359 * Rows generated by SQL, with an array for each row.
74cf4551 360 */
00be9182 361 public function alterDisplay(&$rows) {
6a488035 362 $entryFound = FALSE;
be2fb01f 363 $checkList = [];
6a488035
TO
364 foreach ($rows as $rowNum => $row) {
365 if (!empty($this->_noRepeats) && $this->_outputMode != 'csv') {
366 // not repeat contact sort names if it matches with the one
367 // in previous row
368 $repeatFound = FALSE;
369
370 foreach ($row as $colName => $colVal) {
a7488080 371 if (!empty($checkList[$colName]) &&
6a488035
TO
372 is_array($checkList[$colName]) &&
373 in_array($colVal, $checkList[$colName])
374 ) {
375 $rows[$rowNum][$colName] = "";
376 $repeatFound = TRUE;
377 }
378 if (in_array($colName, $this->_noRepeats)) {
379 $checkList[$colName][] = $colVal;
380 }
381 }
382 }
383
384 if (array_key_exists('civicrm_contact_sort_name', $row) &&
385 $rows[$rowNum]['civicrm_contact_sort_name'] &&
386 array_key_exists('civicrm_contact_id', $row)
387 ) {
388 $url = CRM_Utils_System::url("civicrm/contact/view",
389 'reset=1&cid=' . $row['civicrm_contact_id'],
390 $this->_absoluteUrl
391 );
392 $rows[$rowNum]['civicrm_contact_sort_name_link'] = $url;
393 $rows[$rowNum]['civicrm_contact_sort_name_hover'] = ts("View Contact Summary for this Contact.");
394 $entryFound = TRUE;
395 }
396
5e0343e8 397 if (!empty($row['civicrm_financial_trxn_card_type_id'])) {
398 $rows[$rowNum]['civicrm_financial_trxn_card_type_id'] = $this->getLabels($row['civicrm_financial_trxn_card_type_id'], 'CRM_Financial_DAO_FinancialTrxn', 'card_type_id');
d2a1da52
ERL
399 $entryFound = TRUE;
400 }
401
39bad6a6
AS
402 if (!empty($row['civicrm_pcp_page_type'])) {
403 $rows[$rowNum]['civicrm_pcp_page_type'] = ucfirst($rows[$rowNum]['civicrm_pcp_page_type']);
404 $entryFound = TRUE;
405 }
406
6a488035
TO
407 if (!$entryFound) {
408 break;
409 }
410 }
411 }
96025800 412
6a488035 413}