NFC - Fix @return annotation in CRM_Utils_Check_Component_*
[civicrm-core.git] / CRM / Report / Form / Activity.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_Activity extends CRM_Report_Form {
be2fb01f 18 protected $_selectAliasesTotal = [];
6a488035 19
f0100b85 20 protected $_customGroupExtends = ['Activity'];
430ae6dd 21
be2fb01f 22 protected $_nonDisplayFields = [];
09febbae 23
1728e9a0 24 /**
25 * This report has not been optimised for group filtering.
26 *
27 * The functionality for group filtering has been improved but not
28 * all reports have been adjusted to take care of it. This report has not
29 * and will run an inefficient query until fixed.
30 *
31 * CRM-19170
32 *
33 * @var bool
34 */
35 protected $groupFilterNotOptimised = TRUE;
36
74cf4551 37 /**
ab432335 38 * Class constructor.
f0100b85 39 *
40 * @throws \CRM_Core_Exception
74cf4551 41 */
00be9182 42 public function __construct() {
7116d719 43 // There could be multiple contacts. We not clear on which contact id to display.
83e74860
DS
44 // Lets hide it for now.
45 $this->_exposeContactID = FALSE;
8f621a01 46 // if navigated from count link of activity summary reports.
a3d827a7 47 $this->_resetDateFilter = CRM_Utils_Request::retrieve('resetDateFilter', 'Boolean');
83e74860 48
1023b3bc 49 $components = CRM_Core_Component::getEnabledComponents();
f0100b85 50 $campaignEnabled = !empty($components['CiviCampaign']);
51 $caseEnabled = !empty($components['CiviCase']);
52
1023b3bc 53 foreach ($components as $componentName => $componentInfo) {
d3e6c71f 54 // CRM-19201: Add support for reporting CiviCampaign activities
44d17ec8
BS
55 // For CiviCase, "access all cases and activities" is required here
56 // rather than "access my cases and activities" to prevent those with
57 // only the later permission from seeing a list of all cases which might
58 // present a privacy issue.
59 if (CRM_Core_Permission::access($componentName, TRUE, TRUE)) {
1023b3bc 60 $accessAllowed[] = $componentInfo->componentID;
61 }
62 }
63
64 $include = '';
65 if (!empty($accessAllowed)) {
66 $include = 'OR v.component_id IN (' . implode(', ', $accessAllowed) . ')';
67 }
68 $condition = " AND ( v.component_id IS NULL {$include} )";
69 $this->activityTypes = CRM_Core_OptionGroup::values('activity_type', FALSE, FALSE, FALSE, $condition);
70 asort($this->activityTypes);
d47468d0 71
72 // @todo split the 3 different contact tables into their own array items.
73 // this will massively simplify the needs of this report.
be2fb01f
CW
74 $this->_columns = [
75 'civicrm_contact' => [
af9b09df 76 'dao' => 'CRM_Contact_DAO_Contact',
be2fb01f
CW
77 'fields' => [
78 'contact_source' => [
af9b09df 79 'name' => 'sort_name',
8c0ff2a6 80 'title' => ts('Source Name'),
af9b09df
TO
81 'alias' => 'civicrm_contact_source',
82 'no_repeat' => TRUE,
be2fb01f
CW
83 ],
84 'contact_assignee' => [
af9b09df 85 'name' => 'sort_name',
8c0ff2a6 86 'title' => ts('Assignee Name'),
af9b09df
TO
87 'alias' => 'civicrm_contact_assignee',
88 'dbAlias' => "civicrm_contact_assignee.sort_name",
89 'default' => TRUE,
be2fb01f
CW
90 ],
91 'contact_target' => [
af9b09df 92 'name' => 'sort_name',
8c0ff2a6 93 'title' => ts('Target Name'),
af9b09df
TO
94 'alias' => 'civicrm_contact_target',
95 'dbAlias' => "civicrm_contact_target.sort_name",
96 'default' => TRUE,
be2fb01f
CW
97 ],
98 'contact_source_id' => [
af9b09df
TO
99 'name' => 'id',
100 'alias' => 'civicrm_contact_source',
101 'dbAlias' => "civicrm_contact_source.id",
102 'no_display' => TRUE,
103 'default' => TRUE,
104 'required' => TRUE,
be2fb01f
CW
105 ],
106 'contact_assignee_id' => [
af9b09df
TO
107 'name' => 'id',
108 'alias' => 'civicrm_contact_assignee',
109 'dbAlias' => "civicrm_contact_assignee.id",
110 'no_display' => TRUE,
111 'default' => TRUE,
112 'required' => TRUE,
be2fb01f
CW
113 ],
114 'contact_target_id' => [
af9b09df
TO
115 'name' => 'id',
116 'alias' => 'civicrm_contact_target',
117 'dbAlias' => "civicrm_contact_target.id",
118 'no_display' => TRUE,
119 'default' => TRUE,
120 'required' => TRUE,
be2fb01f
CW
121 ],
122 ],
123 'filters' => [
124 'contact_source' => [
af9b09df
TO
125 'name' => 'sort_name',
126 'alias' => 'civicrm_contact_source',
8c0ff2a6 127 'title' => ts('Source Name'),
af9b09df
TO
128 'operator' => 'like',
129 'type' => CRM_Report_Form::OP_STRING,
be2fb01f
CW
130 ],
131 'contact_assignee' => [
af9b09df
TO
132 'name' => 'sort_name',
133 'alias' => 'civicrm_contact_assignee',
8c0ff2a6 134 'title' => ts('Assignee Name'),
af9b09df
TO
135 'operator' => 'like',
136 'type' => CRM_Report_Form::OP_STRING,
be2fb01f
CW
137 ],
138 'contact_target' => [
af9b09df
TO
139 'name' => 'sort_name',
140 'alias' => 'civicrm_contact_target',
8c0ff2a6 141 'title' => ts('Target Name'),
af9b09df
TO
142 'operator' => 'like',
143 'type' => CRM_Report_Form::OP_STRING,
be2fb01f
CW
144 ],
145 'current_user' => [
af9b09df
TO
146 'name' => 'current_user',
147 'title' => ts('Limit To Current User'),
148 'type' => CRM_Utils_Type::T_INT,
149 'operatorType' => CRM_Report_Form::OP_SELECT,
be2fb01f
CW
150 'options' => ['0' => ts('No'), '1' => ts('Yes')],
151 ],
152 ],
af9b09df 153 'grouping' => 'contact-fields',
be2fb01f
CW
154 ],
155 'civicrm_email' => [
af9b09df 156 'dao' => 'CRM_Core_DAO_Email',
be2fb01f
CW
157 'fields' => [
158 'contact_source_email' => [
af9b09df 159 'name' => 'email',
8c0ff2a6 160 'title' => ts('Source Email'),
af9b09df 161 'alias' => 'civicrm_email_source',
be2fb01f
CW
162 ],
163 'contact_assignee_email' => [
af9b09df 164 'name' => 'email',
8c0ff2a6 165 'title' => ts('Assignee Email'),
af9b09df 166 'alias' => 'civicrm_email_assignee',
be2fb01f
CW
167 ],
168 'contact_target_email' => [
af9b09df 169 'name' => 'email',
8c0ff2a6 170 'title' => ts('Target Email'),
af9b09df 171 'alias' => 'civicrm_email_target',
be2fb01f
CW
172 ],
173 ],
174 'order_bys' => [
175 'source_contact_email' => [
af9b09df 176 'name' => 'email',
8c0ff2a6 177 'title' => ts('Source Email'),
af9b09df 178 'dbAlias' => 'civicrm_email_contact_source_email',
be2fb01f
CW
179 ],
180 ],
181 ],
182 'civicrm_phone' => [
8c0ff2a6 183 'dao' => 'CRM_Core_DAO_Phone',
be2fb01f
CW
184 'fields' => [
185 'contact_source_phone' => [
8c0ff2a6 186 'name' => 'phone',
187 'title' => ts('Source Phone'),
188 'alias' => 'civicrm_phone_source',
be2fb01f
CW
189 ],
190 'contact_assignee_phone' => [
8c0ff2a6 191 'name' => 'phone',
192 'title' => ts('Assignee Phone'),
193 'alias' => 'civicrm_phone_assignee',
be2fb01f
CW
194 ],
195 'contact_target_phone' => [
8c0ff2a6 196 'name' => 'phone',
2afe8e0c 197 'title' => ts('Target Phone'),
8c0ff2a6 198 'alias' => 'civicrm_phone_target',
be2fb01f
CW
199 ],
200 ],
201 ],
202 'civicrm_activity' => [
af9b09df 203 'dao' => 'CRM_Activity_DAO_Activity',
be2fb01f
CW
204 'fields' => [
205 'id' => [
af9b09df
TO
206 'no_display' => TRUE,
207 'title' => ts('Activity ID'),
208 'required' => TRUE,
be2fb01f
CW
209 ],
210 'source_record_id' => [
af9b09df
TO
211 'no_display' => TRUE,
212 'required' => TRUE,
be2fb01f
CW
213 ],
214 'activity_type_id' => [
af9b09df
TO
215 'title' => ts('Activity Type'),
216 'required' => TRUE,
217 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
218 ],
219 'activity_subject' => [
af9b09df
TO
220 'title' => ts('Subject'),
221 'default' => TRUE,
be2fb01f
CW
222 ],
223 'activity_date_time' => [
af9b09df
TO
224 'title' => ts('Activity Date'),
225 'required' => TRUE,
be2fb01f
CW
226 ],
227 'status_id' => [
af9b09df
TO
228 'title' => ts('Activity Status'),
229 'default' => TRUE,
230 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
231 ],
232 'duration' => [
af9b09df
TO
233 'title' => ts('Duration'),
234 'type' => CRM_Utils_Type::T_INT,
be2fb01f
CW
235 ],
236 'location' => [
c02f870b
JM
237 'title' => ts('Location'),
238 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
239 ],
240 'details' => [
1efec7ff 241 'title' => ts('Activity Details'),
be2fb01f
CW
242 ],
243 'priority_id' => [
da236f9a 244 'title' => ts('Priority'),
245 'default' => TRUE,
246 'type' => CRM_Utils_Type::T_STRING,
be2fb01f
CW
247 ],
248 ],
249 'filters' => [
250 'activity_date_time' => [
1a6c8513 251 'default' => 'this.month',
6a488035 252 'operatorType' => CRM_Report_Form::OP_DATE,
be2fb01f
CW
253 ],
254 'activity_subject' => ['title' => ts('Activity Subject')],
255 'activity_type_id' => [
af9b09df
TO
256 'title' => ts('Activity Type'),
257 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
258 'options' => $this->activityTypes,
be2fb01f
CW
259 ],
260 'status_id' => [
af9b09df 261 'title' => ts('Activity Status'),
8ee006e7 262 'type' => CRM_Utils_Type::T_STRING,
af9b09df
TO
263 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
264 'options' => CRM_Core_PseudoConstant::activityStatus(),
be2fb01f
CW
265 ],
266 'location' => [
c02f870b
JM
267 'title' => ts('Location'),
268 'type' => CRM_Utils_Type::T_TEXT,
be2fb01f
CW
269 ],
270 'details' => [
1efec7ff
DG
271 'title' => ts('Activity Details'),
272 'type' => CRM_Utils_Type::T_TEXT,
be2fb01f
CW
273 ],
274 'priority_id' => [
71c30391 275 'title' => ts('Activity Priority'),
410e8105 276 'type' => CRM_Utils_Type::T_STRING,
71c30391 277 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
278 'options' => CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id'),
be2fb01f
CW
279 ],
280 ],
281 'order_bys' => [
282 'activity_date_time' => [
af9b09df
TO
283 'title' => ts('Activity Date'),
284 'default_weight' => '1',
285 'dbAlias' => 'civicrm_activity_activity_date_time',
be2fb01f
CW
286 ],
287 'activity_type_id' => [
af9b09df
TO
288 'title' => ts('Activity Type'),
289 'default_weight' => '2',
56bbb442 290 'dbAlias' => 'field(civicrm_activity_activity_type_id, ' . implode(', ', array_keys($this->activityTypes)) . ')',
be2fb01f
CW
291 ],
292 ],
af9b09df
TO
293 'grouping' => 'activity-fields',
294 'alias' => 'activity',
be2fb01f 295 ],
56bbb442 296 // Hack to get $this->_alias populated for the table.
be2fb01f 297 'civicrm_activity_contact' => [
af9b09df 298 'dao' => 'CRM_Activity_DAO_ActivityContact',
be2fb01f
CW
299 'fields' => [],
300 ],
301 ] + $this->addressFields(TRUE);
6a488035 302
d6c3d40f 303 if ($caseEnabled && CRM_Core_Permission::check('access all cases and activities')) {
be2fb01f 304 $this->_columns['civicrm_activity']['filters']['include_case_activities'] = [
d6c3d40f 305 'name' => 'include_case_activities',
306 'title' => ts('Include Case Activities'),
307 'type' => CRM_Utils_Type::T_INT,
308 'operatorType' => CRM_Report_Form::OP_SELECT,
be2fb01f
CW
309 'options' => ['0' => ts('No'), '1' => ts('Yes')],
310 ];
07d4be20
SL
311 $this->_columns['civicrm_case_activity'] = [
312 'dao' => 'CRM_Case_DAO_CaseActivity',
313 'fields' => [],
314 ];
d6c3d40f 315 }
316
6a488035
TO
317 if ($campaignEnabled) {
318 // Add display column and filter for Survey Results, Campaign and Engagement Index if CiviCampaign is enabled
319
be2fb01f 320 $this->_columns['civicrm_activity']['fields']['result'] = [
fd6a6828 321 'title' => ts('Survey Result'),
6a488035 322 'default' => 'false',
be2fb01f
CW
323 ];
324 $this->_columns['civicrm_activity']['filters']['result'] = [
9d72cede 325 'title' => ts('Survey Result'),
6a488035
TO
326 'operator' => 'like',
327 'type' => CRM_Utils_Type::T_STRING,
be2fb01f 328 ];
254ca428
SL
329 // If we have campaigns enabled, add those elements to both the fields, filters.
330 $this->addCampaignFields('civicrm_activity');
f0100b85 331 $this->engagementLevels = $campaignEnabled ? CRM_Campaign_PseudoConstant::engagementLevel() : [];
6a488035 332 if (!empty($this->engagementLevels)) {
be2fb01f 333 $this->_columns['civicrm_activity']['fields']['engagement_level'] = [
fd6a6828 334 'title' => ts('Engagement Index'),
6a488035 335 'default' => 'false',
be2fb01f
CW
336 ];
337 $this->_columns['civicrm_activity']['filters']['engagement_level'] = [
9d72cede 338 'title' => ts('Engagement Index'),
09b5cdcf 339 'type' => CRM_Utils_Type::T_INT,
6a488035
TO
340 'operatorType' => CRM_Report_Form::OP_MULTISELECT,
341 'options' => $this->engagementLevels,
be2fb01f 342 ];
6a488035
TO
343 }
344 }
345 $this->_groupFilter = TRUE;
346 $this->_tagFilter = TRUE;
ed795723 347 $this->_tagFilterTable = 'civicrm_activity';
b811ac0b 348
6a488035
TO
349 parent::__construct();
350 }
351
07d4be20
SL
352 protected static function addCaseActivityColumns($columns) {
353 $columns['civicrm_case_activity']['fields'] = [
354 'case_id' => [
355 'title' => ts('Case ID'),
356 'required' => TRUE,
357 'dbAlias' => $columns['civicrm_case_activity']['alias'] . '.case_id',
358 'type' => CRM_Utils_Type::T_INT,
359 ],
360 ];
361 return $columns;
b811ac0b
MWMC
362 }
363
be2e0c6a
TO
364 /**
365 * Adding address fields with dbAlias for order clause.
ab432335
EM
366 *
367 * @param bool $orderBy
368 *
a6c01b45 369 * @return array
ab432335 370 * Address fields
667abe3a 371 */
00be9182 372 public function addressFields($orderBy = FALSE) {
667abe3a 373 $address = parent::addAddressFields(FALSE, TRUE);
374 if ($orderBy) {
375 foreach ($address['civicrm_address']['order_bys'] as $fieldName => $field) {
376 $address['civicrm_address']['order_bys'][$fieldName]['dbAlias'] = "civicrm_address_{$fieldName}";
377 }
378 }
379 return $address;
380 }
381
74cf4551 382 /**
a0375fa3 383 * Build select clause.
384 *
d47468d0 385 * @todo get rid of $recordType param. It's only because 3 separate contact tables
386 * are mis-declared as one that we need it.
387 *
388 * @param null $recordType deprecated
389 * Parameter to hack around the bad decision made in construct to misrepresent
390 * different tables as the same table.
74cf4551 391 */
3ede1c56 392 public function select($recordType = 'target') {
9d72cede
EM
393 if (!array_key_exists("contact_{$recordType}", $this->_params['fields']) &&
394 $recordType != 'final'
395 ) {
09febbae 396 $this->_nonDisplayFields[] = "civicrm_contact_contact_{$recordType}";
09febbae 397 }
1f220d30 398 parent::select();
1f220d30 399
09febbae 400 if ($recordType == 'final' && !empty($this->_nonDisplayFields)) {
401 foreach ($this->_nonDisplayFields as $fieldName) {
402 unset($this->_columnHeaders[$fieldName]);
403 }
404 }
405
1f220d30
DS
406 if (empty($this->_selectAliasesTotal)) {
407 $this->_selectAliasesTotal = $this->_selectAliases;
408 }
409
be2fb01f 410 $removeKeys = [];
1f220d30 411 if ($recordType == 'target') {
d47468d0 412 // @todo - fix up the way the tables are declared in construct & remove this.
1f220d30 413 foreach ($this->_selectClauses as $key => $clause) {
7116d719 414 if (strstr($clause, 'civicrm_contact_assignee.') ||
1f220d30
DS
415 strstr($clause, 'civicrm_contact_source.') ||
416 strstr($clause, 'civicrm_email_assignee.') ||
8c0ff2a6 417 strstr($clause, 'civicrm_email_source.') ||
418 strstr($clause, 'civicrm_phone_assignee.') ||
419 strstr($clause, 'civicrm_phone_source.')
1f220d30
DS
420 ) {
421 $removeKeys[] = $key;
422 unset($this->_selectClauses[$key]);
423 }
424 }
9d72cede 425 }
4c9b6178 426 elseif ($recordType == 'assignee') {
d47468d0 427 // @todo - fix up the way the tables are declared in construct & remove this.
1f220d30 428 foreach ($this->_selectClauses as $key => $clause) {
7116d719 429 if (strstr($clause, 'civicrm_contact_target.') ||
1f220d30
DS
430 strstr($clause, 'civicrm_contact_source.') ||
431 strstr($clause, 'civicrm_email_target.') ||
8c0ff2a6 432 strstr($clause, 'civicrm_email_source.') ||
433 strstr($clause, 'civicrm_phone_target.') ||
c00963a1 434 strstr($clause, 'civicrm_phone_source.') ||
435 strstr($clause, 'civicrm_address_')
1f220d30
DS
436 ) {
437 $removeKeys[] = $key;
438 unset($this->_selectClauses[$key]);
439 }
440 }
9d72cede 441 }
4c9b6178 442 elseif ($recordType == 'source') {
d47468d0 443 // @todo - fix up the way the tables are declared in construct & remove this.
1f220d30 444 foreach ($this->_selectClauses as $key => $clause) {
7116d719 445 if (strstr($clause, 'civicrm_contact_target.') ||
1f220d30
DS
446 strstr($clause, 'civicrm_contact_assignee.') ||
447 strstr($clause, 'civicrm_email_target.') ||
8c0ff2a6 448 strstr($clause, 'civicrm_email_assignee.') ||
449 strstr($clause, 'civicrm_phone_target.') ||
c00963a1 450 strstr($clause, 'civicrm_phone_assignee.') ||
451 strstr($clause, 'civicrm_address_')
1f220d30
DS
452 ) {
453 $removeKeys[] = $key;
454 unset($this->_selectClauses[$key]);
455 }
456 }
9d72cede 457 }
4c9b6178 458 elseif ($recordType == 'final') {
1f220d30
DS
459 $this->_selectClauses = $this->_selectAliasesTotal;
460 foreach ($this->_selectClauses as $key => $clause) {
d47468d0 461 // @todo - fix up the way the tables are declared in construct & remove this.
7116d719 462 if (strstr($clause, 'civicrm_contact_contact_target') ||
1f220d30 463 strstr($clause, 'civicrm_contact_contact_assignee') ||
8c0ff2a6 464 strstr($clause, 'civicrm_contact_contact_source') ||
465 strstr($clause, 'civicrm_phone_contact_source_phone') ||
466 strstr($clause, 'civicrm_phone_contact_assignee_phone') ||
467 strstr($clause, 'civicrm_email_contact_source_email') ||
468 strstr($clause, 'civicrm_email_contact_assignee_email') ||
469 strstr($clause, 'civicrm_email_contact_target_email') ||
66ad82d6 470 strstr($clause, 'civicrm_phone_contact_target_phone') ||
471 strstr($clause, 'civicrm_address_')
9d72cede 472 ) {
66ad82d6 473 $this->_selectClauses[$key] = "GROUP_CONCAT(DISTINCT $clause SEPARATOR ';') as $clause";
6a488035
TO
474 }
475 }
476 }
477
1f220d30
DS
478 if ($recordType) {
479 foreach ($removeKeys as $key) {
480 unset($this->_selectAliases[$key]);
481 }
482
c00963a1 483 if ($recordType == 'target') {
667abe3a 484 foreach ($this->_columns['civicrm_address']['order_bys'] as $fieldName => $field) {
485 $orderByFld = $this->_columns['civicrm_address']['order_bys'][$fieldName];
486 $fldInfo = $this->_columns['civicrm_address']['fields'][$fieldName];
487 $this->_selectAliases[] = $orderByFld['dbAlias'];
488 $this->_selectClauses[] = "{$fldInfo['dbAlias']} as {$orderByFld['dbAlias']}";
489 }
667abe3a 490 $this->_selectAliases = array_unique($this->_selectAliases);
491 $this->_selectClauses = array_unique($this->_selectClauses);
492 }
1f220d30 493 $this->_select = "SELECT " . implode(', ', $this->_selectClauses) . " ";
1f220d30 494 }
6a488035
TO
495 }
496
74cf4551 497 /**
a0375fa3 498 * Build from clause.
d47468d0 499 * @todo remove this function & declare the 3 contact tables separately
74cf4551 500 */
d47468d0 501 public function from() {
b811ac0b 502 $this->buildFrom('target');
6a488035
TO
503 }
504
74cf4551 505 /**
a0375fa3 506 * Build where clause.
507 *
d47468d0 508 * @todo get rid of $recordType param. It's only because 3 separate contact tables
509 * are mis-declared as one that we need it.
510 *
a0375fa3 511 * @param string $recordType
74cf4551 512 */
00be9182 513 public function where($recordType = NULL) {
2f4b4d54 514 $this->_where = " WHERE {$this->_aliases['civicrm_activity']}.is_test = 0 AND
6a488035
TO
515 {$this->_aliases['civicrm_activity']}.is_deleted = 0 AND
516 {$this->_aliases['civicrm_activity']}.is_current_revision = 1";
517
be2fb01f 518 $clauses = [];
6a488035
TO
519 foreach ($this->_columns as $tableName => $table) {
520 if (array_key_exists('filters', $table)) {
521
522 foreach ($table['filters'] as $fieldName => $field) {
523 $clause = NULL;
7116d719 524 if ($fieldName != 'contact_' . $recordType &&
525 (strstr($fieldName, '_target') ||
526 strstr($fieldName, '_assignee') ||
527 strstr($fieldName, '_source')
528 )
529 ) {
7116d719 530 continue;
531 }
6a488035 532 if (CRM_Utils_Array::value('type', $field) & CRM_Utils_Type::T_DATE) {
9c1bc317
CW
533 $relative = $this->_params["{$fieldName}_relative"] ?? NULL;
534 $from = $this->_params["{$fieldName}_from"] ?? NULL;
535 $to = $this->_params["{$fieldName}_to"] ?? NULL;
6a488035 536
c44cb2b8 537 $clause = $this->dateClause($field['dbAlias'], $relative, $from, $to, $field['type']);
6a488035
TO
538 }
539 else {
9c1bc317 540 $op = $this->_params["{$fieldName}_op"] ?? NULL;
54df7b0b 541 if ($op && !($fieldName === "contact_{$recordType}" && ($op === 'nnll' || $op === 'nll'))) {
6a488035
TO
542 $clause = $this->whereClause($field,
543 $op,
544 CRM_Utils_Array::value("{$fieldName}_value", $this->_params),
545 CRM_Utils_Array::value("{$fieldName}_min", $this->_params),
546 CRM_Utils_Array::value("{$fieldName}_max", $this->_params)
547 );
d6c3d40f 548 if ($field['name'] == 'include_case_activities') {
549 $clause = NULL;
550 }
9d72cede
EM
551 if ($fieldName == 'activity_type_id' &&
552 empty($this->_params['activity_type_id_value'])
553 ) {
355b8a20 554 if (empty($this->_params['include_case_activities_value'])) {
555 $this->activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, FALSE, FALSE, 'label', TRUE);
556 }
1023b3bc 557 $actTypes = array_flip($this->activityTypes);
6c552737 558 $clause = "( {$this->_aliases['civicrm_activity']}.activity_type_id IN (" .
9d72cede 559 implode(',', $actTypes) . ") )";
42b3be07 560 }
6a488035
TO
561 }
562 }
563
564 if ($field['name'] == 'current_user') {
9d72cede
EM
565 if (CRM_Utils_Array::value("{$fieldName}_value", $this->_params) ==
566 1
567 ) {
6a488035 568 // get current user
f0c3f9bc 569 if ($contactID = CRM_Core_Session::getLoggedInContactID()) {
389cfee7 570 $clause = "{$this->_aliases['civicrm_activity_contact']}.activity_id IN
571 (SELECT activity_id FROM civicrm_activity_contact WHERE contact_id = {$contactID})";
6a488035
TO
572 }
573 else {
574 $clause = NULL;
575 }
576 }
577 else {
578 $clause = NULL;
579 }
580 }
581 if (!empty($clause)) {
582 $clauses[] = $clause;
583 }
584 }
585 }
586 }
587
588 if (empty($clauses)) {
b6cab294 589 $this->_where .= " ";
6a488035
TO
590 }
591 else {
b6cab294 592 $this->_where .= " AND " . implode(' AND ', $clauses);
6a488035
TO
593 }
594
595 if ($this->_aclWhere) {
596 $this->_where .= " AND {$this->_aclWhere} ";
597 }
598 }
599
a0375fa3 600 /**
601 * Override group by function.
602 */
00be9182 603 public function groupBy() {
b708c08d 604 $this->_groupBy = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, "{$this->_aliases['civicrm_activity']}.id");
6a488035
TO
605 }
606
74cf4551 607 /**
a0375fa3 608 * Build ACL clause.
609 *
74cf4551 610 * @param string $tableAlias
f0c3f9bc 611 *
612 * @throws \CRM_Core_Exception
74cf4551 613 */
00be9182 614 public function buildACLClause($tableAlias = 'contact_a') {
2a3c101f 615 //override for ACL( Since Contact may be source
6a488035
TO
616 //contact/assignee or target also it may be null )
617
618 if (CRM_Core_Permission::check('view all contacts')) {
619 $this->_aclFrom = $this->_aclWhere = NULL;
620 return;
621 }
622
f0c3f9bc 623 $contactID = CRM_Core_Session::getLoggedInContactID();
6a488035
TO
624 if (!$contactID) {
625 $contactID = 0;
626 }
627 $contactID = CRM_Utils_Type::escape($contactID, 'Integer');
628
629 CRM_Contact_BAO_Contact_Permission::cache($contactID);
be2fb01f 630 $clauses = [];
6a488035
TO
631 foreach ($tableAlias as $k => $alias) {
632 $clauses[] = " INNER JOIN civicrm_acl_contact_cache aclContactCache_{$k} ON ( {$alias}.id = aclContactCache_{$k}.contact_id OR {$alias}.id IS NULL ) AND aclContactCache_{$k}.user_id = $contactID ";
633 }
634
635 $this->_aclFrom = implode(" ", $clauses);
636 $this->_aclWhere = NULL;
637 }
638
74cf4551 639 /**
100fef9d 640 * @param int $groupID
74cf4551
EM
641 *
642 * @throws Exception
643 */
00be9182 644 public function add2group($groupID) {
9a2f601e 645 if (CRM_Utils_Array::value("contact_target_op", $this->_params) == 'nll') {
7980012b 646 CRM_Core_Error::statusBounce(ts('Current filter criteria didn\'t have any target contact to add to group'));
9a2f601e 647 }
648
7f6464a0
JM
649 $new_select = 'AS addtogroup_contact_id';
650 $select = str_ireplace('AS civicrm_contact_contact_target_id', $new_select, $this->_select);
651 $new_having = ' addtogroup_contact_id';
652 $having = str_ireplace(' civicrm_contact_contact_target_id', $new_having, $this->_having);
653 $query = "$select
a8b58e72 654FROM {$this->temporaryTables['activity_temp_table']['name']} tar
7f6464a0 655GROUP BY civicrm_activity_id $having {$this->_orderBy}";
9a2f601e 656 $select = 'AS addtogroup_contact_id';
657 $query = str_ireplace('AS civicrm_contact_contact_target_id', $select, $query);
dfb264b2 658 CRM_Core_DAO::disableFullGroupByMode();
f38e3c19 659 $dao = $this->executeReportQuery($query);
dfb264b2 660 CRM_Core_DAO::reenableFullGroupByMode();
9a2f601e 661
be2fb01f 662 $contactIDs = [];
9a2f601e 663 // Add resulting contacts to group
664 while ($dao->fetch()) {
665 if ($dao->addtogroup_contact_id) {
666 $contact_id = explode(';', $dao->addtogroup_contact_id);
667 if ($contact_id[0]) {
7bb16323 668 $contactIDs[$contact_id[0]] = $contact_id[0];
9a2f601e 669 }
670 }
671 }
672
9d72cede 673 if (!empty($contactIDs)) {
9a2f601e 674 CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs, $groupID);
675 CRM_Core_Session::setStatus(ts("Listed contact(s) have been added to the selected group."), ts('Contacts Added'), 'success');
676 }
677 else {
678 CRM_Core_Session::setStatus(ts("The listed records(s) cannot be added to the group."));
679 }
680 }
681
d6c3d40f 682 /**
683 * @param $fields
684 * @param $files
685 * @param $self
686 *
687 * @return array
688 */
689 public static function formRule($fields, $files, $self) {
be2fb01f 690 $errors = [];
355b8a20 691 $config = CRM_Core_Config::singleton();
692 if (in_array("CiviCase", $config->enableComponents)) {
693 $componentId = CRM_Core_Component::getComponentID('CiviCase');
694 $caseActivityTypes = CRM_Core_OptionGroup::values('activity_type', TRUE, FALSE, FALSE, " AND v.component_id={$componentId}");
695 if (!empty($fields['activity_type_id_value']) && is_array($fields['activity_type_id_value']) && empty($fields['include_case_activities_value'])) {
696 foreach ($fields['activity_type_id_value'] as $activityTypeId) {
697 if (in_array($activityTypeId, $caseActivityTypes)) {
698 $errors['fields'] = ts("Please enable 'Include Case Activities' to filter with Case Activity types.");
699 }
d6c3d40f 700 }
701 }
702 }
703 return $errors;
704 }
705
a1bf1058
ML
706 /**
707 * @param $applyLimit
708 *
709 * @return string
710 */
711 public function buildQuery($applyLimit = TRUE) {
44f817d4 712 $activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
52272965 713 $sourceID = CRM_Utils_Array::key('Activity Source', $activityContacts);
2f4b4d54 714
389cfee7 715 //Assign those recordtype to array which have filter operator as 'Is not empty' or 'Is empty'
be2fb01f
CW
716 $nullFilters = [];
717 foreach (['target', 'source', 'assignee'] as $type) {
9d72cede
EM
718 if (CRM_Utils_Array::value("contact_{$type}_op", $this->_params) ==
719 'nnll' || !empty($this->_params["contact_{$type}_value"])
720 ) {
3ae89fd7 721 $nullFilters[] = " civicrm_contact_contact_{$type}_id IS NOT NULL ";
389cfee7 722 }
4c9b6178 723 elseif (CRM_Utils_Array::value("contact_{$type}_op", $this->_params) ==
9d72cede
EM
724 'nll'
725 ) {
3ae89fd7 726 $nullFilters[] = " civicrm_contact_contact_{$type}_id IS NULL ";
b6cab294 727 }
728 }
729
07d4be20
SL
730 if (!empty($this->_params['include_case_activities_value'])) {
731 $this->_columns = self::addCaseActivityColumns($this->_columns);
732 }
733
d47468d0 734 // @todo - all this temp table stuff is here because pre 4.4 the activity contact
735 // form did not exist.
736 // Fixing the way the construct method declares them will make all this redundant.
9d72cede 737 // 1. fill temp table with target results
be2fb01f 738 $this->buildACLClause(['civicrm_contact_target']);
1f220d30 739 $this->select('target');
d47468d0 740 $this->from();
5b1ba2b8 741 $this->customDataFrom();
389cfee7 742 $this->where('target');
5a14305b 743 $tempTableName = $this->createTemporaryTable('activity_temp_table', "{$this->_select} {$this->_from} {$this->_where}");
2f4b4d54 744
1f220d30
DS
745 // 2. add new columns to hold assignee and source results
746 // fixme: add when required
747 $tempQuery = "
5a14305b 748 ALTER TABLE $tempTableName
e7b3275b 749 MODIFY COLUMN civicrm_contact_contact_target_id VARCHAR(128),
1f220d30
DS
750 ADD COLUMN civicrm_contact_contact_assignee VARCHAR(128),
751 ADD COLUMN civicrm_contact_contact_source VARCHAR(128),
7116d719 752 ADD COLUMN civicrm_contact_contact_assignee_id VARCHAR(128),
482691e1 753 ADD COLUMN civicrm_contact_contact_source_id VARCHAR(128),
8c0ff2a6 754 ADD COLUMN civicrm_phone_contact_assignee_phone VARCHAR(128),
755 ADD COLUMN civicrm_phone_contact_source_phone VARCHAR(128),
1f220d30
DS
756 ADD COLUMN civicrm_email_contact_assignee_email VARCHAR(128),
757 ADD COLUMN civicrm_email_contact_source_email VARCHAR(128)";
f38e3c19 758 $this->executeReportQuery($tempQuery);
1f220d30
DS
759
760 // 3. fill temp table with assignee results
be2fb01f 761 $this->buildACLClause(['civicrm_contact_assignee']);
389cfee7 762 $this->select('assignee');
d47468d0 763 $this->buildAssigneeFrom();
764
389cfee7 765 $this->customDataFrom();
766 $this->where('assignee');
767 $insertCols = implode(',', $this->_selectAliases);
5a14305b 768 $tempQuery = "INSERT INTO $tempTableName ({$insertCols})
1f220d30 769{$this->_select}
83e74860 770{$this->_from} {$this->_where}";
f38e3c19 771 $this->executeReportQuery($tempQuery);
2f4b4d54 772
1f220d30 773 // 4. fill temp table with source results
be2fb01f 774 $this->buildACLClause(['civicrm_contact_source']);
389cfee7 775 $this->select('source');
d47468d0 776 $this->buildSourceFrom();
389cfee7 777 $this->customDataFrom();
778 $this->where('source');
779 $insertCols = implode(',', $this->_selectAliases);
5a14305b 780 $tempQuery = "INSERT INTO $tempTableName ({$insertCols})
1f220d30 781{$this->_select}
83e74860 782{$this->_from} {$this->_where}";
f38e3c19 783 $this->executeReportQuery($tempQuery);
2f4b4d54 784
1f220d30 785 // 5. show final result set from temp table
be2fb01f 786 $rows = [];
1f220d30 787 $this->select('final');
389cfee7 788 $this->_having = "";
789 if (!empty($nullFilters)) {
790 $this->_having = "HAVING " . implode(' AND ', $nullFilters);
791 }
83e74860 792 $this->orderBy();
ecf1e543 793 foreach ($this->_sections as $alias => $section) {
794 if (!empty($section) && $section['name'] == 'activity_date_time') {
5a14305b 795 $this->alterSectionHeaderForDateTime($tempTableName, $section['tplField']);
ecf1e543 796 }
e06df9af 797 }
a1bf1058
ML
798
799 if ($applyLimit) {
800 $this->limit();
801 }
802
d1641c51 803 $groupByFromSelect = CRM_Contact_BAO_Query::getGroupByFromSelectColumns($this->_selectClauses, 'civicrm_activity_id');
52272965 804
cbbc16ec 805 $this->_where = " WHERE (1)";
52272965 806 $this->buildPermissionClause();
cbbc16ec
TS
807 if ($this->_aclWhere) {
808 $this->_where .= " AND {$this->_aclWhere} ";
809 }
52272965 810
b811ac0b
MWMC
811 $caseJoin = '';
812 if (!empty($this->_params['include_case_activities_value'])) {
813 $caseJoin = "LEFT JOIN civicrm_case_activity {$this->_aliases['civicrm_case_activity']} ON {$this->_aliases['civicrm_activity']}.id = {$this->_aliases['civicrm_case_activity']}.activity_id";
814 }
815
7116d719 816 $sql = "{$this->_select}
5a14305b 817 FROM $tempTableName tar
52272965
E
818 INNER JOIN civicrm_activity {$this->_aliases['civicrm_activity']} ON {$this->_aliases['civicrm_activity']}.id = tar.civicrm_activity_id
819 INNER JOIN civicrm_activity_contact {$this->_aliases['civicrm_activity_contact']} ON {$this->_aliases['civicrm_activity_contact']}.activity_id = {$this->_aliases['civicrm_activity']}.id
820 AND {$this->_aliases['civicrm_activity_contact']}.record_type_id = {$sourceID}
cbbc16ec 821 LEFT JOIN civicrm_contact contact_civireport ON contact_civireport.id = {$this->_aliases['civicrm_activity_contact']}.contact_id
b811ac0b 822 {$caseJoin}
cbbc16ec 823 {$this->_where} {$groupByFromSelect} {$this->_having} {$this->_orderBy} {$this->_limit}";
52272965 824
a1bf1058 825 CRM_Utils_Hook::alterReportVar('sql', $this, $this);
cbbc16ec 826 $this->addToDeveloperTab($sql);
a1bf1058
ML
827
828 return $sql;
829 }
830
c6f4d60c 831 /**
832 * Override parent to reset value of activity_date.
833 */
834 public function beginPostProcessCommon() {
a1bf1058 835 if (!empty($this->_resetDateFilter)) {
c6f4d60c 836 $this->_formValues['activity_date_time_relative'] = NULL;
a1bf1058 837 }
6a488035
TO
838 }
839
74cf4551 840 /**
4b62bc4f
EM
841 * Alter display of rows.
842 *
843 * Iterate through the rows retrieved via SQL and make changes for display purposes,
844 * such as rendering contacts as links.
845 *
846 * @param array $rows
847 * Rows generated by SQL, with an array for each row.
c6f4d60c 848 *
849 * @throws \CRM_Core_Exception
74cf4551 850 */
00be9182 851 public function alterDisplay(&$rows) {
9d72cede
EM
852 $entryFound = FALSE;
853 $activityType = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE);
6a488035 854 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
410e8105 855 $priority = CRM_Core_PseudoConstant::get('CRM_Activity_DAO_Activity', 'priority_id');
9d72cede 856 $viewLinks = FALSE;
f2e37338 857
d47468d0 858 // Would we ever want to retrieve from the form controller??
859 $form = $this->noController ? NULL : $this;
860 $context = CRM_Utils_Request::retrieve('context', 'Alphanumeric', $form, FALSE, 'report');
9d72cede 861 $actUrl = '';
6a488035
TO
862
863 if (CRM_Core_Permission::check('access CiviCRM')) {
9d72cede
EM
864 $viewLinks = TRUE;
865 $onHover = ts('View Contact Summary for this Contact');
6a488035
TO
866 $onHoverAct = ts('View Activity Record');
867 }
38ba593b 868 foreach ($rows as $rowNum => $row) {
1efec7ff 869 // if we have an activity type, format the View Activity link for use in various columns
9d72cede
EM
870 if ($viewLinks &&
871 array_key_exists('civicrm_activity_activity_type_id', $row)
872 ) {
1efec7ff
DG
873 // Check for target contact id(s) and use the first contact id in that list for view activity link if found,
874 // else use source contact id
875 if (!empty($rows[$rowNum]['civicrm_contact_contact_target_id'])) {
876 $targets = explode(';', $rows[$rowNum]['civicrm_contact_contact_target_id']);
877 $cid = $targets[0];
878 }
879 else {
880 $cid = $rows[$rowNum]['civicrm_contact_contact_source_id'];
881 }
882
b811ac0b
MWMC
883 if (empty($this->_params['include_case_activities_value']) || empty($rows[$rowNum]['civicrm_case_activity_case_id'])) {
884 // Generate a "view activity" link
885 $actActionLinks = CRM_Activity_Selector_Activity::actionLinks($row['civicrm_activity_activity_type_id'],
886 CRM_Utils_Array::value('civicrm_activity_source_record_id', $rows[$rowNum]),
887 FALSE,
888 $rows[$rowNum]['civicrm_activity_id']
889 );
890
891 $actLinkValues = [
892 'id' => $rows[$rowNum]['civicrm_activity_id'],
893 'cid' => $cid,
894 'cxt' => $context,
895 ];
896 $actUrl = CRM_Utils_System::url($actActionLinks[CRM_Core_Action::VIEW]['url'],
897 CRM_Core_Action::replace($actActionLinks[CRM_Core_Action::VIEW]['qs'], $actLinkValues), TRUE
898 );
899 }
900 else {
901 // Generate a "view case activity" link
902 $caseActionLinks = CRM_Case_Selector_Search::actionLinks();
903 $caseLinkValues = [
904 'aid' => $rows[$rowNum]['civicrm_activity_id'],
905 'caseid' => $rows[$rowNum]['civicrm_case_activity_case_id'],
906 'cid' => $cid,
907 'cxt' => $context,
908 ];
909 $actUrl = CRM_Utils_System::url($caseActionLinks[CRM_Core_Action::VIEW]['url'],
910 CRM_Core_Action::replace($caseActionLinks[CRM_Core_Action::VIEW]['qs'], $caseLinkValues), TRUE
911 );
912 }
1efec7ff
DG
913 }
914
482691e1
RN
915 if (array_key_exists('civicrm_contact_contact_source', $row)) {
916 if ($value = $row['civicrm_contact_contact_source_id']) {
917 if ($viewLinks) {
918 $url = CRM_Utils_System::url("civicrm/contact/view",
919 'reset=1&cid=' . $value,
920 $this->_absoluteUrl
921 );
922 $rows[$rowNum]['civicrm_contact_contact_source_link'] = $url;
923 $rows[$rowNum]['civicrm_contact_contact_source_hover'] = $onHover;
924 }
925 $entryFound = TRUE;
926 }
927 }
928
929 if (array_key_exists('civicrm_contact_contact_assignee', $row)) {
930 $assigneeNames = explode(';', $row['civicrm_contact_contact_assignee']);
931 if ($value = $row['civicrm_contact_contact_assignee_id']) {
932 $assigneeContactIds = explode(';', $value);
be2fb01f 933 $link = [];
482691e1
RN
934 if ($viewLinks) {
935 foreach ($assigneeContactIds as $id => $value) {
936 if (isset($value) && isset($assigneeNames[$id])) {
937 $url = CRM_Utils_System::url("civicrm/contact/view",
938 'reset=1&cid=' . $value,
939 $this->_absoluteUrl
940 );
9d72cede
EM
941 $link[] = "<a title='" . $onHover . "' href='" . $url .
942 "'>{$assigneeNames[$id]}</a>";
482691e1
RN
943 }
944 }
945 $rows[$rowNum]['civicrm_contact_contact_assignee'] = implode('; ', $link);
946 }
947 $entryFound = TRUE;
948 }
949 }
950
951 if (array_key_exists('civicrm_contact_contact_target', $row)) {
952 $targetNames = explode(';', $row['civicrm_contact_contact_target']);
953 if ($value = $row['civicrm_contact_contact_target_id']) {
954 $targetContactIds = explode(';', $value);
be2fb01f 955 $link = [];
482691e1
RN
956 if ($viewLinks) {
957 foreach ($targetContactIds as $id => $value) {
958 if (isset($value) && isset($targetNames[$id])) {
959 $url = CRM_Utils_System::url("civicrm/contact/view",
960 'reset=1&cid=' . $value,
961 $this->_absoluteUrl
962 );
9d72cede
EM
963 $link[] = "<a title='" . $onHover . "' href='" . $url .
964 "'>{$targetNames[$id]}</a>";
482691e1
RN
965 }
966 }
967 $rows[$rowNum]['civicrm_contact_contact_target'] = implode('; ', $link);
968 }
969 $entryFound = TRUE;
970 }
971 }
972
6a488035
TO
973 if (array_key_exists('civicrm_activity_activity_type_id', $row)) {
974 if ($value = $row['civicrm_activity_activity_type_id']) {
975 $rows[$rowNum]['civicrm_activity_activity_type_id'] = $activityType[$value];
482691e1 976 if ($viewLinks) {
1efec7ff 977 $rows[$rowNum]['civicrm_activity_activity_type_id_link'] = $actUrl;
482691e1
RN
978 $rows[$rowNum]['civicrm_activity_activity_type_id_hover'] = $onHoverAct;
979 }
6a488035
TO
980 $entryFound = TRUE;
981 }
982 }
983
984 if (array_key_exists('civicrm_activity_status_id', $row)) {
985 if ($value = $row['civicrm_activity_status_id']) {
986 $rows[$rowNum]['civicrm_activity_status_id'] = $activityStatus[$value];
987 $entryFound = TRUE;
988 }
989 }
990
410e8105 991 if (array_key_exists('civicrm_activity_priority_id', $row)) {
992 if ($value = $row['civicrm_activity_priority_id']) {
993 $rows[$rowNum]['civicrm_activity_priority_id'] = $priority[$value];
994 $entryFound = TRUE;
995 }
996 }
997
34e0bdb6 998 if (array_key_exists('civicrm_activity_details', $row) && $this->_outputMode == 'html') {
1efec7ff
DG
999 if ($value = $row['civicrm_activity_details']) {
1000 $fullDetails = $rows[$rowNum]['civicrm_activity_details'];
1001 $rows[$rowNum]['civicrm_activity_details'] = substr($fullDetails, 0, strrpos(substr($fullDetails, 0, 80), ' '));
1002 if ($actUrl) {
6e5e50a9 1003 $rows[$rowNum]['civicrm_activity_details'] .= " <a href='{$actUrl}' title='{$onHoverAct}'>(more)</a>";
1efec7ff
DG
1004 }
1005 $entryFound = TRUE;
1006 }
1007 }
1008
6a488035
TO
1009 if (array_key_exists('civicrm_activity_campaign_id', $row)) {
1010 if ($value = $row['civicrm_activity_campaign_id']) {
254ca428 1011 $rows[$rowNum]['civicrm_activity_campaign_id'] = $this->campaigns[$value];
6a488035
TO
1012 $entryFound = TRUE;
1013 }
1014 }
1015
1016 if (array_key_exists('civicrm_activity_engagement_level', $row)) {
1017 if ($value = $row['civicrm_activity_engagement_level']) {
1018 $rows[$rowNum]['civicrm_activity_engagement_level'] = $this->engagementLevels[$value];
1019 $entryFound = TRUE;
1020 }
1021 }
1022
9d72cede
EM
1023 if (array_key_exists('civicrm_activity_activity_date_time', $row) &&
1024 array_key_exists('civicrm_activity_status_id', $row)
1025 ) {
6a488035
TO
1026 if (CRM_Utils_Date::overdue($rows[$rowNum]['civicrm_activity_activity_date_time']) &&
1027 $activityStatus[$row['civicrm_activity_status_id']] != 'Completed'
1028 ) {
1029 $rows[$rowNum]['class'] = "status-overdue";
1030 $entryFound = TRUE;
1031 }
1032 }
1033
66ad82d6 1034 $entryFound = $this->alterDisplayAddressFields($row, $rows, $rowNum, 'activity', 'List all activities for this', ';') ? TRUE : $entryFound;
482691e1 1035
6a488035
TO
1036 if (!$entryFound) {
1037 break;
1038 }
1039 }
1040 }
667abe3a 1041
00be9182 1042 public function sectionTotals() {
667abe3a 1043 // Reports using order_bys with sections must populate $this->_selectAliases in select() method.
1044 if (empty($this->_selectAliases)) {
1045 return;
1046 }
1047
1048 if (!empty($this->_sections)) {
1049 // pull section aliases out of $this->_sections
1050 $sectionAliases = array_keys($this->_sections);
1051
be2fb01f 1052 $ifnulls = [];
667abe3a 1053 foreach (array_merge($sectionAliases, $this->_selectAliases) as $alias) {
1054 $ifnulls[] = "ifnull($alias, '') as $alias";
1055 }
b708c08d 1056 $this->_select = "SELECT " . implode(", ", $ifnulls);
36d2f4d5 1057 $this->_select = CRM_Contact_BAO_Query::appendAnyValueToSelect($ifnulls, $sectionAliases);
667abe3a 1058
b708c08d 1059 $query = $this->_select .
ab663ec4 1060 ", count(DISTINCT civicrm_activity_id) as ct from {$this->temporaryTables['activity_temp_table']['name']} group by " .
667abe3a 1061 implode(", ", $sectionAliases);
1062
1063 // initialize array of total counts
be2fb01f 1064 $totals = [];
f38e3c19 1065 $dao = $this->executeReportQuery($query);
667abe3a 1066 while ($dao->fetch()) {
1067 // let $this->_alterDisplay translate any integer ids to human-readable values.
1068 $rows[0] = $dao->toArray();
1069 $this->alterDisplay($rows);
1070 $row = $rows[0];
1071
1072 // add totals for all permutations of section values
be2fb01f 1073 $values = [];
667abe3a 1074 $i = 1;
1075 $aliasCount = count($sectionAliases);
1076 foreach ($sectionAliases as $alias) {
1077 $values[] = $row[$alias];
1078 $key = implode(CRM_Core_DAO::VALUE_SEPARATOR, $values);
1079 if ($i == $aliasCount) {
1080 // the last alias is the lowest-level section header; use count as-is
1081 $totals[$key] = $dao->ct;
1082 }
1083 else {
1084 // other aliases are higher level; roll count into their total
1085 $totals[$key] += $dao->ct;
1086 }
1087 }
1088 }
1089 $this->assign('sectionTotals', $totals);
1090 }
1091 }
96025800 1092
d47468d0 1093 /**
1094 * @todo remove this function & declare the 3 contact tables separately
1095 *
1096 * (Currently the construct method incorrectly melds them - this is an interim
1097 * refactor in order to get this under ReportTemplateTests)
1098 */
1099 protected function buildAssigneeFrom() {
b811ac0b 1100 $this->buildFrom('assignee');
d47468d0 1101 }
1102
1103 /**
1104 * @todo remove this function & declare the 3 contact tables separately
1105 *
1106 * (Currently the construct method incorrectly melds them - this is an interim
1107 * refactor in order to get this under ReportTemplateTests)
1108 */
1109 protected function buildSourceFrom() {
b811ac0b
MWMC
1110 $this->buildFrom('source');
1111 }
1112
1113 /**
1114 * Shared function to build the from clause
1115 *
1116 * @param string $recordType (one of 'source', 'activity', 'target')
1117 */
1118 protected function buildFrom($recordType) {
d47468d0 1119 $activityContacts = CRM_Activity_BAO_ActivityContact::buildOptions('record_type_id', 'validate');
b811ac0b
MWMC
1120 switch ($recordType) {
1121 case 'target':
1122 $recordTypeID = CRM_Utils_Array::key('Activity Targets', $activityContacts);
1123 break;
1124
1125 case 'source':
1126 $recordTypeID = CRM_Utils_Array::key('Activity Source', $activityContacts);
1127 break;
1128
1129 case 'assignee':
1130 $recordTypeID = CRM_Utils_Array::key('Activity Assignees', $activityContacts);
1131 break;
1132
1133 }
1134
d47468d0 1135 $this->_from = "
b811ac0b
MWMC
1136 FROM civicrm_activity {$this->_aliases['civicrm_activity']}
1137 INNER JOIN civicrm_activity_contact {$this->_aliases['civicrm_activity_contact']}
1138 ON {$this->_aliases['civicrm_activity']}.id = {$this->_aliases['civicrm_activity_contact']}.activity_id AND
1139 {$this->_aliases['civicrm_activity_contact']}.record_type_id = {$recordTypeID}
1140 INNER JOIN civicrm_contact civicrm_contact_{$recordType}
1141 ON {$this->_aliases['civicrm_activity_contact']}.contact_id = civicrm_contact_{$recordType}.id
1142 {$this->_aclFrom}";
1143 if (!empty($this->_params['include_case_activities_value'])) {
1144 $this->_from .= "
1145 LEFT JOIN civicrm_case_activity {$this->_aliases['civicrm_case_activity']}
1146 ON {$this->_aliases['civicrm_case_activity']}.activity_id = {$this->_aliases['civicrm_activity']}.id";
1147 }
d47468d0 1148
1149 if ($this->isTableSelected('civicrm_email')) {
1150 $this->_from .= "
b811ac0b
MWMC
1151 LEFT JOIN civicrm_email civicrm_email_{$recordType}
1152 ON {$this->_aliases['civicrm_activity_contact']}.contact_id = civicrm_email_{$recordType}.contact_id AND
1153 civicrm_email_{$recordType}.is_primary = 1";
d47468d0 1154 }
b811ac0b 1155
d47468d0 1156 if ($this->isTableSelected('civicrm_phone')) {
1157 $this->_from .= "
b811ac0b
MWMC
1158 LEFT JOIN civicrm_phone civicrm_phone_{$recordType}
1159 ON {$this->_aliases['civicrm_activity_contact']}.contact_id = civicrm_phone_{$recordType}.contact_id AND
1160 civicrm_phone_{$recordType}.is_primary = 1 ";
d47468d0 1161 }
b811ac0b
MWMC
1162 $this->_aliases['civicrm_contact'] = "civicrm_contact_{$recordType}";
1163
d47468d0 1164 $this->joinAddressFromContact();
1165 }
1166
6a488035 1167}