Merge pull request #5301 from totten/master-abtest-perm
[civicrm-core.git] / CRM / Contribute / Selector / Search.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035 5 +--------------------------------------------------------------------+
06b69b18 6 | Copyright CiviCRM LLC (c) 2004-2014 |
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
06b69b18 31 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
32 * $Id$
33 *
34 */
35
36/**
37 * This class is used to retrieve and display a range of
38 * contacts that match the given criteria (specifically for
39 * results of advanced search options.
40 *
41 */
42class CRM_Contribute_Selector_Search extends CRM_Core_Selector_Base implements CRM_Core_Selector_API {
43
44 /**
45 * This defines two actions- View and Edit.
46 *
47 * @var array
6a488035
TO
48 */
49 static $_links = NULL;
50
51 /**
100fef9d 52 * We use desc to remind us what that column is, name is used in the tpl
6a488035
TO
53 *
54 * @var array
6a488035
TO
55 */
56 static $_columnHeaders;
57
58 /**
59 * Properties of contact we're interested in displaying
60 * @var array
6a488035
TO
61 */
62 static $_properties = array(
63 'contact_id',
64 'contribution_id',
65 'contact_type',
66 'sort_name',
67 'amount_level',
68 'total_amount',
e777c2b6 69 'financial_type',
6a488035
TO
70 'contribution_source',
71 'receive_date',
72 'thankyou_date',
73 'contribution_status_id',
74 'contribution_status',
75 'cancel_date',
76 'product_name',
77 'is_test',
78 'contribution_recur_id',
79 'receipt_date',
80 'membership_id',
81 'currency',
82 'contribution_campaign_id',
36bf52ef 83 'contribution_soft_credit_name',
d4e2b978 84 'contribution_soft_credit_contact_id',
36bf52ef
DS
85 'contribution_soft_credit_amount',
86 'contribution_soft_credit_type',
6a488035
TO
87 );
88
89 /**
100fef9d 90 * Are we restricting ourselves to a single contact
6a488035 91 *
6a488035
TO
92 * @var boolean
93 */
94 protected $_single = FALSE;
95
96 /**
100fef9d 97 * Are we restricting ourselves to a single contact
6a488035 98 *
6a488035
TO
99 * @var boolean
100 */
101 protected $_limit = NULL;
102
103 /**
100fef9d 104 * What context are we being invoked from
6a488035 105 *
6a488035
TO
106 * @var string
107 */
108 protected $_context = NULL;
109
110 /**
100fef9d 111 * What component context are we being invoked from
6a488035 112 *
6a488035
TO
113 * @var string
114 */
115 protected $_compContext = NULL;
116
117 /**
100fef9d 118 * QueryParams is the array returned by exportValues called on
6a488035
TO
119 * the HTML_QuickForm_Controller for that page.
120 *
121 * @var array
6a488035
TO
122 */
123 public $_queryParams;
124
125 /**
100fef9d 126 * Represent the type of selector
6a488035
TO
127 *
128 * @var int
6a488035
TO
129 */
130 protected $_action;
131
132 /**
133 * The additional clause that we restrict the search with
134 *
135 * @var string
136 */
137 protected $_contributionClause = NULL;
138
139 /**
140 * The query object
141 *
142 * @var string
143 */
144 protected $_query;
145
36bf52ef
DS
146 protected $_includeSoftCredits = FALSE;
147
6a488035 148 /**
fe482240 149 * Class constructor.
6a488035 150 *
014c4014
TO
151 * @param array $queryParams
152 * Array of parameters for query.
da6b46f4 153 * @param \const|int $action - action of search basic or advanced.
014c4014
TO
154 * @param string $contributionClause
155 * If the caller wants to further restrict the search (used in contributions).
156 * @param bool $single
157 * Are we dealing only with one contact?.
158 * @param int $limit
159 * How many contributions do we want returned.
6a488035 160 *
da6b46f4
EM
161 * @param string $context
162 * @param null $compContext
163 *
164 * @return \CRM_Contribute_Selector_Search
6a488035 165 */
8d7a9d07 166 public function __construct(
a13f3d8c 167 &$queryParams,
874c9be7 168 $action = CRM_Core_Action::NONE,
6a488035 169 $contributionClause = NULL,
874c9be7
TO
170 $single = FALSE,
171 $limit = NULL,
172 $context = 'search',
173 $compContext = NULL
6a488035
TO
174 ) {
175
176 // submitted form values
177 $this->_queryParams = &$queryParams;
178
353ffa53
TO
179 $this->_single = $single;
180 $this->_limit = $limit;
181 $this->_context = $context;
6a488035
TO
182 $this->_compContext = $compContext;
183
184 $this->_contributionClause = $contributionClause;
185
186 // type of selector
187 $this->_action = $action;
188
d4e2b978 189 $this->_includeSoftCredits = CRM_Contribute_BAO_Query::isSoftCreditOptionEnabled($this->_queryParams);
36bf52ef
DS
190 $this->_query = new CRM_Contact_BAO_Query(
191 $this->_queryParams,
192 CRM_Contribute_BAO_Query::defaultReturnProperties(
193 CRM_Contact_BAO_Query::MODE_CONTRIBUTE,
f654cacf 194 FALSE
6a488035
TO
195 ),
196 NULL, FALSE, FALSE,
197 CRM_Contact_BAO_Query::MODE_CONTRIBUTE
198 );
3dbf477c
DS
199 if ($this->_includeSoftCredits) {
200 $this->_query->_rowCountClause = " count(civicrm_contribution.id)";
ed81a415 201 $this->_query->_groupByComponentClause = " GROUP BY contribution_search_scredit_combined.id, contribution_search_scredit_combined.contact_id, contribution_search_scredit_combined.scredit_id ";
0db6c3e1
TO
202 }
203 else {
3dbf477c
DS
204 $this->_query->_distinctComponentClause = " civicrm_contribution.id";
205 $this->_query->_groupByComponentClause = " GROUP BY civicrm_contribution.id ";
206 }
6a488035 207 }
6a488035
TO
208
209 /**
210 * This method returns the links that are given for each search row.
211 * currently the links added for each row are
212 *
213 * - View
214 * - Edit
215 *
100fef9d 216 * @param int $componentId
fd31fa4c
EM
217 * @param null $componentAction
218 * @param null $key
219 * @param null $compContext
220 *
6a488035 221 * @return array
6a488035 222 */
00be9182 223 public static function &links($componentId = NULL, $componentAction = NULL, $key = NULL, $compContext = NULL) {
6a488035
TO
224 $extraParams = NULL;
225 if ($componentId) {
226 $extraParams = "&compId={$componentId}&compAction={$componentAction}";
227 }
228 if ($compContext) {
229 $extraParams .= "&compContext={$compContext}";
230 }
231 if ($key) {
232 $extraParams .= "&key={$key}";
233 }
234
235 if (!(self::$_links)) {
236 self::$_links = array(
237 CRM_Core_Action::VIEW => array(
238 'name' => ts('View'),
239 'url' => 'civicrm/contact/view/contribution',
240 'qs' => "reset=1&id=%%id%%&cid=%%cid%%&action=view&context=%%cxt%%&selectedChild=contribute{$extraParams}",
241 'title' => ts('View Contribution'),
242 ),
243 CRM_Core_Action::UPDATE => array(
244 'name' => ts('Edit'),
245 'url' => 'civicrm/contact/view/contribution',
246 'qs' => "reset=1&action=update&id=%%id%%&cid=%%cid%%&context=%%cxt%%{$extraParams}",
247 'title' => ts('Edit Contribution'),
248 ),
249 CRM_Core_Action::DELETE => array(
250 'name' => ts('Delete'),
251 'url' => 'civicrm/contact/view/contribution',
252 'qs' => "reset=1&action=delete&id=%%id%%&cid=%%cid%%&context=%%cxt%%{$extraParams}",
253 'title' => ts('Delete Contribution'),
254 ),
255 );
256 }
257 return self::$_links;
258 }
6a488035
TO
259
260 /**
100fef9d 261 * Getter for array of the parameters required for creating pager.
6a488035 262 *
da6b46f4 263 * @param $action
c490a46a 264 * @param array $params
6a488035 265 */
00be9182 266 public function getPagerParams($action, &$params) {
6a488035
TO
267 $params['status'] = ts('Contribution') . ' %%StatusMessage%%';
268 $params['csvString'] = NULL;
269 if ($this->_limit) {
270 $params['rowCount'] = $this->_limit;
271 }
272 else {
273 $params['rowCount'] = CRM_Utils_Pager::ROWCOUNT;
274 }
275
276 $params['buttonTop'] = 'PagerTopButton';
277 $params['buttonBottom'] = 'PagerBottomButton';
278 }
6a488035
TO
279
280 /**
281 * Returns total number of rows for the query.
282 *
7fe37828 283 * @param string $action
6a488035 284 *
a6c01b45
CW
285 * @return int
286 * Total number of rows
6a488035 287 */
00be9182 288 public function getTotalCount($action) {
6a488035
TO
289 return $this->_query->searchQuery(0, 0, NULL,
290 TRUE, FALSE,
291 FALSE, FALSE,
292 FALSE,
293 $this->_contributionClause
294 );
295 }
296
297 /**
fe482240 298 * Returns all the rows in the given offset and rowCount.
6a488035 299 *
3f8d2862 300 * @param string $action
014c4014
TO
301 * The action being performed.
302 * @param int $offset
303 * The row number to start from.
304 * @param int $rowCount
305 * The number of rows to return.
306 * @param string $sort
307 * The sql string that describes the sort order.
3f8d2862 308 * @param string $output
014c4014 309 * What should the result set include (web/email/csv).
6a488035 310 *
a6c01b45
CW
311 * @return int
312 * the total number of rows for this action
6a488035 313 */
00be9182 314 public function &getRows($action, $offset, $rowCount, $sort, $output = NULL) {
4f3846df
DS
315 if ($this->_includeSoftCredits) {
316 // especial sort order when rows include soft credits
317 $sort = "civicrm_contribution.receive_date DESC, civicrm_contribution.id, civicrm_contribution_soft.id";
318 }
6a488035
TO
319 $result = $this->_query->searchQuery($offset, $rowCount, $sort,
320 FALSE, FALSE,
321 FALSE, FALSE,
322 FALSE,
323 $this->_contributionClause
324 );
325 // process the result of the query
326 $rows = array();
327
328 //CRM-4418 check for view/edit/delete
329 $permissions = array(CRM_Core_Permission::VIEW);
330 if (CRM_Core_Permission::check('edit contributions')) {
331 $permissions[] = CRM_Core_Permission::EDIT;
332 }
333 if (CRM_Core_Permission::check('delete in CiviContribute')) {
334 $permissions[] = CRM_Core_Permission::DELETE;
335 }
336 $mask = CRM_Core_Action::mask($permissions);
337
338 $qfKey = $this->_key;
339 $componentId = $componentContext = NULL;
340 if ($this->_context != 'contribute') {
353ffa53
TO
341 $qfKey = CRM_Utils_Request::retrieve('key', 'String', CRM_Core_DAO::$_nullObject);
342 $componentId = CRM_Utils_Request::retrieve('id', 'Positive', CRM_Core_DAO::$_nullObject);
343 $componentAction = CRM_Utils_Request::retrieve('action', 'String', CRM_Core_DAO::$_nullObject);
6a488035
TO
344 $componentContext = CRM_Utils_Request::retrieve('compContext', 'String', CRM_Core_DAO::$_nullObject);
345
346 if (!$componentContext &&
347 $this->_compContext
348 ) {
349 $componentContext = $this->_compContext;
350 $qfKey = CRM_Utils_Request::retrieve('qfKey', 'String', CRM_Core_DAO::$_nullObject, NULL, FALSE, 'REQUEST');
351 }
352 }
353
354 // get all contribution status
355 $contributionStatuses = CRM_Core_OptionGroup::values('contribution_status',
356 FALSE, FALSE, FALSE, NULL, 'name', FALSE
357 );
358
359 //get all campaigns.
360 $allCampaigns = CRM_Campaign_BAO_Campaign::getCampaigns(NULL, NULL, FALSE, FALSE, FALSE, TRUE);
361
874c9be7 362 while ($result->fetch()) {
6a488035
TO
363 $row = array();
364 // the columns we are interested in
365 foreach (self::$_properties as $property) {
366 if (property_exists($result, $property)) {
367 $row[$property] = $result->$property;
368 }
369 }
370
371 //carry campaign on selectors.
372 $row['campaign'] = CRM_Utils_Array::value($result->contribution_campaign_id, $allCampaigns);
373 $row['campaign_id'] = $result->contribution_campaign_id;
374
375 // add contribution status name
376 $row['contribution_status_name'] = CRM_Utils_Array::value($row['contribution_status_id'],
377 $contributionStatuses
378 );
379
380 if ($result->is_pay_later && CRM_Utils_Array::value('contribution_status_name', $row) == 'Pending') {
381 $row['contribution_status'] .= ' (' . ts('Pay Later') . ')';
382 }
383 elseif (CRM_Utils_Array::value('contribution_status_name', $row) == 'Pending') {
384 $row['contribution_status'] .= ' (' . ts('Incomplete Transaction') . ')';
385 }
386
387 if ($row['is_test']) {
e777c2b6 388 $row['financial_type'] = $row['financial_type'] . ' (' . ts('test') . ')';
6a488035
TO
389 }
390
391 $row['checkbox'] = CRM_Core_Form::CB_PREFIX . $result->contribution_id;
392
6a488035
TO
393 $actions = array(
394 'id' => $result->contribution_id,
395 'cid' => $result->contact_id,
396 'cxt' => $this->_context,
397 );
398
e777c2b6
KJ
399 $row['action'] = CRM_Core_Action::formLink(
400 self::links($componentId,
401 $componentAction,
402 $qfKey,
403 $componentContext
404 ),
87dab4a4
AH
405 $mask, $actions,
406 ts('more'),
407 FALSE,
408 'contribution.selector.row',
409 'Contribution',
410 $result->contribution_id
6a488035
TO
411 );
412
874c9be7 413 $row['contact_type'] = CRM_Contact_BAO_Contact_Utils::getImage($result->contact_sub_type ? $result->contact_sub_type : $result->contact_type, FALSE, $result->contact_id
6a488035
TO
414 );
415
a7488080 416 if (!empty($row['amount_level'])) {
6a488035
TO
417 CRM_Event_BAO_Participant::fixEventLevel($row['amount_level']);
418 }
419
420 $rows[] = $row;
421 }
422
423 return $rows;
424 }
425
426 /**
1054415f 427 * @inheritDoc
6a488035 428 */
6a488035
TO
429 public function getQILL() {
430 return $this->_query->qill();
431 }
432
433 /**
100fef9d 434 * Returns the column headers as an array of tuples:
6a488035
TO
435 * (name, sortName (key to the sort array))
436 *
014c4014
TO
437 * @param string $action
438 * The action being performed.
3f8d2862 439 * @param string $output
014c4014 440 * What should the result set include (web/email/csv).
6a488035 441 *
a6c01b45
CW
442 * @return array
443 * the column headers that need to be displayed
6a488035
TO
444 */
445 public function &getColumnHeaders($action = NULL, $output = NULL) {
36bf52ef
DS
446 self::$_columnHeaders = array(
447 array(
4f3846df 448 'name' => $this->_includeSoftCredits ? ts('Contribution Amount') : ts('Amount'),
36bf52ef
DS
449 'sort' => 'total_amount',
450 'direction' => CRM_Utils_Sort::DONTCARE,
451 ),
36bf52ef 452 );
4f3846df 453 if ($this->_includeSoftCredits) {
8d7a9d07
CB
454 self::$_columnHeaders
455 = array_merge(
fd31fa4c 456 self::$_columnHeaders,
4f3846df
DS
457 array(
458 array(
459 'name' => ts('Soft Credit Amount'),
460 'sort' => 'contribution_soft_credit_amount',
461 'direction' => CRM_Utils_Sort::DONTCARE,
21dfd5f5 462 ),
4f3846df
DS
463 )
464 );
465 }
8d7a9d07
CB
466 self::$_columnHeaders
467 = array_merge(
fd31fa4c 468 self::$_columnHeaders,
4f3846df
DS
469 array(
470 array(
471 'name' => ts('Type'),
353ffa53 472 'sort' => 'financial_type',
4f3846df
DS
473 'direction' => CRM_Utils_Sort::DONTCARE,
474 ),
475 array(
476 'name' => ts('Source'),
477 'sort' => 'contribution_source',
478 'direction' => CRM_Utils_Sort::DONTCARE,
479 ),
480 array(
481 'name' => ts('Received'),
482 'sort' => 'receive_date',
483 'direction' => CRM_Utils_Sort::DESCENDING,
484 ),
485 array(
486 'name' => ts('Thank-you Sent'),
487 'sort' => 'thankyou_date',
488 'direction' => CRM_Utils_Sort::DONTCARE,
489 ),
490 array(
491 'name' => ts('Status'),
33a5a53d 492 'sort' => 'contribution_status',
4f3846df
DS
493 'direction' => CRM_Utils_Sort::DONTCARE,
494 ),
495 array(
496 'name' => ts('Premium'),
497 'sort' => 'product_name',
498 'direction' => CRM_Utils_Sort::DONTCARE,
499 ),
500 )
501 );
36bf52ef
DS
502 if (!$this->_single) {
503 $pre = array(
504 array('desc' => ts('Contact Type')),
6a488035 505 array(
36bf52ef
DS
506 'name' => ts('Name'),
507 'sort' => 'sort_name',
6a488035
TO
508 'direction' => CRM_Utils_Sort::DONTCARE,
509 ),
6a488035 510 );
36bf52ef
DS
511 self::$_columnHeaders = array_merge($pre, self::$_columnHeaders);
512 }
513 if ($this->_includeSoftCredits) {
006389de 514 self::$_columnHeaders = array_merge(
8d7a9d07
CB
515 self::$_columnHeaders,
516 array(
6a488035 517 array(
8d7a9d07
CB
518 'name' => ts('Soft Credit For'),
519 'sort' => 'contribution_soft_credit_name',
520 'direction' => CRM_Utils_Sort::DONTCARE,
521 ),
522 array(
523 'name' => ts('Soft Credit Type'),
524 'sort' => 'contribution_soft_credit_type',
525 'direction' => CRM_Utils_Sort::ASCENDING,
526 ),
527 )
528 );
6a488035 529 }
8d7a9d07
CB
530 self::$_columnHeaders
531 = array_merge(
4f3846df 532 self::$_columnHeaders, array(
21dfd5f5 533 array('desc' => ts('Actions')),
4f3846df
DS
534 )
535 );
6a488035
TO
536 return self::$_columnHeaders;
537 }
538
186c9c17
EM
539 /**
540 * @return mixed
541 */
00be9182 542 public function alphabetQuery() {
6a488035
TO
543 return $this->_query->searchQuery(NULL, NULL, NULL, FALSE, FALSE, TRUE);
544 }
545
186c9c17
EM
546 /**
547 * @return string
548 */
00be9182 549 public function &getQuery() {
6a488035
TO
550 return $this->_query;
551 }
552
553 /**
100fef9d 554 * Name of export file.
6a488035 555 *
014c4014
TO
556 * @param string $output
557 * Type of output.
6a488035 558 *
a6c01b45
CW
559 * @return string
560 * name of the file
6a488035 561 */
00be9182 562 public function getExportFileName($output = 'csv') {
6a488035
TO
563 return ts('CiviCRM Contribution Search');
564 }
565
186c9c17
EM
566 /**
567 * @return mixed
568 */
00be9182 569 public function getSummary() {
6a488035
TO
570 return $this->_query->summaryContribution($this->_context);
571 }
96025800 572
6a488035 573}