Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | // $Id$ | |
3 | ||
4 | /* | |
5 | +--------------------------------------------------------------------+ | |
39de6fd5 | 6 | | CiviCRM version 4.6 | |
6a488035 | 7 | +--------------------------------------------------------------------+ |
731a0992 | 8 | | Copyright CiviCRM LLC (c) 2004-2014 | |
6a488035 TO |
9 | +--------------------------------------------------------------------+ |
10 | | This file is a part of CiviCRM. | | |
11 | | | | |
12 | | CiviCRM is free software; you can copy, modify, and distribute it | | |
13 | | under the terms of the GNU Affero General Public License | | |
14 | | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. | | |
15 | | | | |
16 | | CiviCRM is distributed in the hope that it will be useful, but | | |
17 | | WITHOUT ANY WARRANTY; without even the implied warranty of | | |
18 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | | |
19 | | See the GNU Affero General Public License for more details. | | |
20 | | | | |
21 | | You should have received a copy of the GNU Affero General Public | | |
22 | | License and the CiviCRM Licensing Exception along | | |
23 | | with this program; if not, contact CiviCRM LLC | | |
24 | | at info[AT]civicrm[DOT]org. If you have questions about the | | |
25 | | GNU Affero General Public License or the licensing of CiviCRM, | | |
26 | | see the CiviCRM license FAQ at http://civicrm.org/licensing | | |
27 | +--------------------------------------------------------------------+ | |
28 | */ | |
29 | ||
30 | /** | |
31 | * File for the CiviCRM APIv3 activity functions | |
32 | * | |
33 | * @package CiviCRM_APIv3 | |
34 | * @subpackage API_Activity | |
731a0992 | 35 | * @copyright CiviCRM LLC (c) 2004-2014 |
6a488035 TO |
36 | * @version $Id: Activity.php 30486 2010-11-02 16:12:09Z shot $ |
37 | * | |
38 | */ | |
39 | ||
40 | ||
41 | /** | |
42 | * Creates or updates an Activity. See the example for usage | |
43 | * | |
cf470720 TO |
44 | * @param array $params |
45 | * Associative array of property name/value. | |
6a488035 TO |
46 | * pairs for the activity. |
47 | * {@getfields activity_create} | |
48 | * | |
77b97be7 | 49 | * @throws API_Exception |
a6c01b45 | 50 | * @return array |
72b3a70c | 51 | * Array containing 'is_error' to denote success or failure and details of the created activity |
6a488035 TO |
52 | * |
53 | * @example ActivityCreate.php Standard create example | |
54 | * @example Activity/ContactRefCustomField.php Create example including setting a contact reference custom field | |
55 | * {@example ActivityCreate.php 0} | |
6a488035 TO |
56 | */ |
57 | function civicrm_api3_activity_create($params) { | |
58 | ||
a7488080 | 59 | if (empty($params['id'])) { |
6a488035 TO |
60 | // an update does not require any mandatory parameters |
61 | civicrm_api3_verify_one_mandatory($params, | |
62 | NULL, | |
63 | array( | |
7cdbcb16 TO |
64 | 'activity_name', |
65 | 'activity_type_id', | |
66 | 'activity_label', | |
6a488035 TO |
67 | ) |
68 | ); | |
69 | } | |
70 | ||
6a488035 TO |
71 | // check for various error and required conditions |
72 | // note that almost all the processing in there should be managed by the wrapper layer | |
73 | // & should be removed - needs testing | |
74 | $errors = _civicrm_api3_activity_check_params($params); | |
75 | ||
76 | // this should not be required as should throw exception rather than return errors - | |
77 | //needs testing | |
78 | if (!empty($errors)) { | |
79 | return $errors; | |
80 | } | |
81 | ||
6a488035 | 82 | // processing for custom data |
10114f2d | 83 | $values = $activityArray = array(); |
6a488035 TO |
84 | _civicrm_api3_custom_format_params($params, $values, 'Activity'); |
85 | ||
86 | if (!empty($values['custom'])) { | |
87 | $params['custom'] = $values['custom']; | |
88 | } | |
89 | ||
90 | // this should be set as a default rather than hard coded | |
91 | // needs testing | |
92 | $params['skipRecentView'] = TRUE; | |
93 | ||
94 | // If this is a case activity, see if there is an existing activity | |
95 | // and set it as an old revision. Also retrieve details we'll need. | |
96 | // this handling should all be moved to the BAO layer | |
7cdbcb16 TO |
97 | $case_id = ''; |
98 | $createRevision = FALSE; | |
6a488035 | 99 | $oldActivityValues = array(); |
e96d5fa3 CW |
100 | // Lookup case id if not supplied |
101 | if (!isset($params['case_id']) && !empty($params['id'])) { | |
102 | $params['case_id'] = CRM_Core_DAO::singleValueQuery("SELECT case_id FROM civicrm_case_activity WHERE activity_id = " . (int) $params['id']); | |
103 | } | |
a7488080 | 104 | if (!empty($params['case_id'])) { |
6a488035 | 105 | $case_id = $params['case_id']; |
a7488080 | 106 | if (!empty($params['id'])) { |
6a488035 TO |
107 | $oldActivityParams = array('id' => $params['id']); |
108 | if (!$oldActivityValues) { | |
109 | CRM_Activity_BAO_Activity::retrieve($oldActivityParams, $oldActivityValues); | |
110 | } | |
111 | if (empty($oldActivityValues)) { | |
10114f2d | 112 | throw new API_Exception(ts("Unable to locate existing activity.")); |
6a488035 TO |
113 | } |
114 | else { | |
115 | $activityDAO = new CRM_Activity_DAO_Activity(); | |
116 | $activityDAO->id = $params['id']; | |
117 | $activityDAO->is_current_revision = 0; | |
118 | if (!$activityDAO->save()) { | |
08007144 TO |
119 | if (is_object($activityDAO)) { |
120 | $activityDAO->free(); | |
121 | } | |
10114f2d | 122 | throw new API_Exception(ts("Unable to revision existing case activity.")); |
6a488035 TO |
123 | } |
124 | $createRevision = TRUE; | |
125 | } | |
126 | } | |
127 | } | |
128 | ||
129 | $deleteActivityAssignment = FALSE; | |
130 | if (isset($params['assignee_contact_id'])) { | |
131 | $deleteActivityAssignment = TRUE; | |
132 | } | |
133 | ||
134 | $deleteActivityTarget = FALSE; | |
135 | if (isset($params['target_contact_id'])) { | |
136 | $deleteActivityTarget = TRUE; | |
137 | } | |
138 | ||
139 | // this should all be handled at the BAO layer | |
140 | $params['deleteActivityAssignment'] = CRM_Utils_Array::value('deleteActivityAssignment', $params, $deleteActivityAssignment); | |
141 | $params['deleteActivityTarget'] = CRM_Utils_Array::value('deleteActivityTarget', $params, $deleteActivityTarget); | |
142 | ||
143 | if ($case_id && $createRevision) { | |
144 | // This is very similar to the copy-to-case action. | |
145 | if (!CRM_Utils_Array::crmIsEmptyArray($oldActivityValues['target_contact'])) { | |
146 | $oldActivityValues['targetContactIds'] = implode(',', array_unique($oldActivityValues['target_contact'])); | |
147 | } | |
148 | if (!CRM_Utils_Array::crmIsEmptyArray($oldActivityValues['assignee_contact'])) { | |
149 | $oldActivityValues['assigneeContactIds'] = implode(',', array_unique($oldActivityValues['assignee_contact'])); | |
150 | } | |
151 | $oldActivityValues['mode'] = 'copy'; | |
152 | $oldActivityValues['caseID'] = $case_id; | |
153 | $oldActivityValues['activityID'] = $oldActivityValues['id']; | |
154 | $oldActivityValues['contactID'] = $oldActivityValues['source_contact_id']; | |
155 | ||
156 | $copyToCase = CRM_Activity_Page_AJAX::_convertToCaseActivity($oldActivityValues); | |
157 | if (empty($copyToCase['error_msg'])) { | |
158 | // now fix some things that are different from copy-to-case | |
159 | // then fall through to the create below to update with the passed in params | |
160 | $params['id'] = $copyToCase['newId']; | |
161 | $params['is_auto'] = 0; | |
162 | $params['original_id'] = empty($oldActivityValues['original_id']) ? $oldActivityValues['id'] : $oldActivityValues['original_id']; | |
163 | } | |
164 | else { | |
10114f2d | 165 | throw new API_Exception(ts("Unable to create new revision of case activity.")); |
6a488035 TO |
166 | } |
167 | } | |
168 | ||
169 | // create activity | |
170 | $activityBAO = CRM_Activity_BAO_Activity::create($params); | |
171 | ||
172 | if (isset($activityBAO->id)) { | |
173 | if ($case_id && !$createRevision) { | |
174 | // If this is a brand new case activity we need to add this | |
175 | $caseActivityParams = array('activity_id' => $activityBAO->id, 'case_id' => $case_id); | |
176 | CRM_Case_BAO_Case::processCaseActivity($caseActivityParams); | |
177 | } | |
178 | ||
179 | _civicrm_api3_object_to_array($activityBAO, $activityArray[$activityBAO->id]); | |
180 | return civicrm_api3_create_success($activityArray, $params, 'activity', 'get', $activityBAO); | |
181 | } | |
182 | } | |
11e09c59 TO |
183 | |
184 | /** | |
6a488035 TO |
185 | * Specify Meta data for create. Note that this data is retrievable via the getfields function |
186 | * and is used for pre-filling defaults and ensuring mandatory requirements are met. | |
cf470720 TO |
187 | * @param array $params |
188 | * (reference) array of parameters determined by getfields. | |
6a488035 TO |
189 | */ |
190 | function _civicrm_api3_activity_create_spec(&$params) { | |
191 | ||
192 | //default for source_contact_id = currently logged in user | |
193 | $params['source_contact_id']['api.default'] = 'user_contact_id'; | |
194 | ||
67744c4e CW |
195 | $params['status_id']['api.aliases'] = array('activity_status'); |
196 | ||
6a488035 TO |
197 | $params['assignee_contact_id'] = array( |
198 | 'name' => 'assignee_id', | |
199 | 'title' => 'assigned to', | |
200 | 'type' => 1, | |
2f3d72cf | 201 | 'FKClassName' => 'CRM_Activity_DAO_ActivityContact', |
6a488035 TO |
202 | ); |
203 | $params['target_contact_id'] = array( | |
204 | 'name' => 'target_id', | |
205 | 'title' => 'Activity Target', | |
206 | 'type' => 1, | |
2f3d72cf | 207 | 'FKClassName' => 'CRM_Activity_DAO_ActivityContact', |
6a488035 | 208 | ); |
2f3d72cf | 209 | |
210 | $params['source_contact_id'] = array( | |
7cdbcb16 TO |
211 | 'name' => 'source_contact_id', |
212 | 'title' => 'Activity Source Contact', | |
213 | 'type' => 1, | |
214 | 'FKClassName' => 'CRM_Activity_DAO_ActivityContact', | |
215 | 'api.default' => 'user_contact_id', | |
2f3d72cf | 216 | ); |
217 | ||
6a488035 TO |
218 | } |
219 | ||
220 | /** | |
221 | * Gets a CiviCRM activity according to parameters | |
222 | * | |
cf470720 TO |
223 | * @param array $params |
224 | * Associative array of property name/value. | |
6a488035 TO |
225 | * pairs for the activity. |
226 | * | |
227 | * @return array | |
228 | * | |
28a04ea9 | 229 | * {@getfields activity_get} |
6a488035 TO |
230 | * @example ActivityGet.php Basic example |
231 | * @example Activity/DateTimeHigh.php Example get with date filtering | |
232 | * {@example ActivityGet.php 0} | |
233 | */ | |
234 | function civicrm_api3_activity_get($params) { | |
235 | if (!empty($params['contact_id'])) { | |
236 | $activities = CRM_Activity_BAO_Activity::getContactActivity($params['contact_id']); | |
237 | //BAO function doesn't actually return a contact ID - hack api for now & add to test so when api re-write happens it won't get missed | |
238 | foreach ($activities as $key => $activityArray) { | |
239 | $activities[$key]['id'] = $key; | |
240 | } | |
241 | } | |
242 | else { | |
243 | $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE); | |
244 | } | |
35671d00 | 245 | $options = _civicrm_api3_get_options_from_params($params, FALSE, 'activity', 'get'); |
22e263ad | 246 | if ($options['is_count']) { |
e2e3c1ce EM |
247 | return civicrm_api3_create_success($activities, $params, 'activity', 'get'); |
248 | } | |
6a488035 | 249 | |
ab5fa8f2 TO |
250 | $activities = _civicrm_api3_activity_get_formatResult($params, $activities); |
251 | //legacy custom data get - so previous formatted response is still returned too | |
252 | return civicrm_api3_create_success($activities, $params, 'activity', 'get'); | |
253 | } | |
254 | ||
255 | /** | |
256 | * Given a list of activities, append any extra data requested about the activities | |
257 | * | |
258 | * NOTE: Called by civicrm-core and CiviHR | |
259 | * | |
cf470720 TO |
260 | * @param array $params |
261 | * API request parameters. | |
ab5fa8f2 | 262 | * @param array $activities |
a6c01b45 | 263 | * @return array |
72b3a70c | 264 | * new activities list |
ab5fa8f2 TO |
265 | */ |
266 | function _civicrm_api3_activity_get_formatResult($params, $activities) { | |
6a488035 TO |
267 | $returns = CRM_Utils_Array::value('return', $params, array()); |
268 | if (!is_array($returns)) { | |
269 | $returns = str_replace(' ', '', $returns); | |
270 | $returns = explode(',', $returns); | |
271 | } | |
272 | $returns = array_fill_keys($returns, 1); | |
273 | ||
274 | foreach ($params as $n => $v) { | |
275 | if (substr($n, 0, 7) == 'return.') { | |
276 | $returnkey = substr($n, 7); | |
277 | $returns[$returnkey] = $v; | |
278 | } | |
279 | } | |
2f3d72cf | 280 | $returns['source_contact_id'] = 1; |
6a488035 TO |
281 | foreach ($returns as $n => $v) { |
282 | switch ($n) { | |
283 | case 'assignee_contact_id': | |
284 | foreach ($activities as $key => $activityArray) { | |
285 | $activities[$key]['assignee_contact_id'] = CRM_Activity_BAO_ActivityAssignment::retrieveAssigneeIdsByActivityId($activityArray['id']); | |
286 | } | |
287 | break; | |
35671d00 | 288 | |
6a488035 TO |
289 | case 'target_contact_id': |
290 | foreach ($activities as $key => $activityArray) { | |
291 | $activities[$key]['target_contact_id'] = CRM_Activity_BAO_ActivityTarget::retrieveTargetIdsByActivityId($activityArray['id']); | |
292 | } | |
293 | break; | |
35671d00 | 294 | |
42d30b83 DL |
295 | case 'source_contact_id': |
296 | foreach ($activities as $key => $activityArray) { | |
297 | $activities[$key]['source_contact_id'] = CRM_Activity_BAO_Activity::getSourceContactID($activityArray['id']); | |
298 | } | |
299 | break; | |
35671d00 | 300 | |
6a488035 TO |
301 | default: |
302 | if (substr($n, 0, 6) == 'custom') { | |
303 | $returnProperties[$n] = $v; | |
304 | } | |
305 | } | |
306 | } | |
307 | if (!empty($activities) && (!empty($returnProperties) || !empty($params['contact_id']))) { | |
308 | foreach ($activities as $activityId => $values) { | |
10114f2d EM |
309 | //@todo - should possibly load activity type id if not loaded (update with id) |
310 | _civicrm_api3_custom_data_get($activities[$activityId], 'Activity', $activityId, NULL, CRM_Utils_Array::value('activity_type_id', $values)); | |
6a488035 TO |
311 | } |
312 | } | |
ab5fa8f2 | 313 | return $activities; |
6a488035 TO |
314 | } |
315 | ||
2f3d72cf | 316 | |
6a488035 TO |
317 | /** |
318 | * Delete a specified Activity. | |
319 | * | |
cf470720 TO |
320 | * @param array $params |
321 | * Array holding 'id' of activity to be deleted. | |
6a488035 TO |
322 | * {@getfields activity_delete} |
323 | * | |
10114f2d | 324 | * @throws API_Exception |
6a488035 TO |
325 | * @return void|CRM_Core_Error An error if 'activityName or ID' is invalid, |
326 | * permissions are insufficient, etc. or CiviCRM success array | |
327 | * | |
328 | * | |
329 | * | |
330 | * @example ActivityDelete.php Standard Delete Example | |
331 | * | |
6a488035 TO |
332 | */ |
333 | function civicrm_api3_activity_delete($params) { | |
334 | ||
335 | if (CRM_Activity_BAO_Activity::deleteActivity($params)) { | |
336 | return civicrm_api3_create_success(1, $params, 'activity', 'delete'); | |
337 | } | |
338 | else { | |
10114f2d | 339 | throw new API_Exception('Could not delete activity'); |
6a488035 TO |
340 | } |
341 | } | |
342 | ||
343 | /** | |
c490a46a | 344 | * Check for required params |
6a488035 | 345 | * |
cf470720 TO |
346 | * @param array $params |
347 | * Associated array of fields. | |
10114f2d EM |
348 | * |
349 | * @throws API_Exception | |
350 | * @throws Exception | |
a6c01b45 | 351 | * @return array |
72b3a70c | 352 | * array with errors |
6a488035 TO |
353 | */ |
354 | function _civicrm_api3_activity_check_params(&$params) { | |
355 | ||
356 | $contactIDFields = array_intersect_key($params, | |
7cdbcb16 TO |
357 | array( |
358 | 'source_contact_id' => 1, | |
359 | 'assignee_contact_id' => 1, | |
360 | 'target_contact_id' => 1, | |
361 | ) | |
6a488035 | 362 | ); |
42d30b83 DL |
363 | |
364 | // this should be handled by wrapper layer & probably the api would already manage it | |
365 | //correctly by doing post validation - ie. a failure should result in a roll-back = an error | |
366 | // needs testing | |
6a488035 TO |
367 | if (!empty($contactIDFields)) { |
368 | $contactIds = array(); | |
369 | foreach ($contactIDFields as $fieldname => $contactfield) { | |
370 | if (empty($contactfield)) { | |
371 | continue; | |
372 | } | |
373 | if (is_array($contactfield)) { | |
374 | foreach ($contactfield as $contactkey => $contactvalue) { | |
375 | $contactIds[$contactvalue] = $contactvalue; | |
376 | } | |
377 | } | |
378 | else { | |
379 | $contactIds[$contactfield] = $contactfield; | |
380 | } | |
381 | } | |
382 | ||
6a488035 TO |
383 | $sql = ' |
384 | SELECT count(*) | |
385 | FROM civicrm_contact | |
386 | WHERE id IN (' . implode(', ', $contactIds) . ' )'; | |
387 | if (count($contactIds) != CRM_Core_DAO::singleValueQuery($sql)) { | |
86bfa4f6 | 388 | throw new API_Exception('Invalid ' . ' Contact Id'); |
6a488035 TO |
389 | } |
390 | } | |
391 | ||
35671d00 | 392 | $activityIds = array( |
7cdbcb16 TO |
393 | 'activity' => CRM_Utils_Array::value('id', $params), |
394 | 'parent' => CRM_Utils_Array::value('parent_id', $params), | |
395 | 'original' => CRM_Utils_Array::value('original_id', $params), | |
6a488035 TO |
396 | ); |
397 | ||
398 | foreach ($activityIds as $id => $value) { | |
399 | if ($value && | |
400 | !CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $value, 'id') | |
401 | ) { | |
10114f2d | 402 | throw new API_Exception('Invalid ' . ucfirst($id) . ' Id'); |
6a488035 TO |
403 | } |
404 | } | |
405 | // this should be handled by wrapper layer & probably the api would already manage it | |
406 | //correctly by doing pseudoconstant validation | |
407 | // needs testing | |
a60ed840 | 408 | $activityTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'validate'); |
7cdbcb16 TO |
409 | $activityName = CRM_Utils_Array::value('activity_name', $params); |
410 | $activityName = ucfirst($activityName); | |
6a488035 TO |
411 | $activityLabel = CRM_Utils_Array::value('activity_label', $params); |
412 | if ($activityLabel) { | |
a60ed840 | 413 | $activityTypes = CRM_Activity_BAO_Activity::buildOptions('activity_type_id', 'create'); |
6a488035 TO |
414 | } |
415 | ||
416 | $activityTypeId = CRM_Utils_Array::value('activity_type_id', $params); | |
417 | ||
418 | if ($activityName || $activityLabel) { | |
419 | $activityTypeIdInList = array_search(($activityName ? $activityName : $activityLabel), $activityTypes); | |
420 | ||
421 | if (!$activityTypeIdInList) { | |
35671d00 | 422 | $errorString = $activityName ? "Invalid Activity Name : $activityName" : "Invalid Activity Type Label"; |
6a488035 TO |
423 | throw new Exception($errorString); |
424 | } | |
425 | elseif ($activityTypeId && ($activityTypeId != $activityTypeIdInList)) { | |
10114f2d | 426 | throw new API_Exception('Mismatch in Activity'); |
6a488035 TO |
427 | } |
428 | $params['activity_type_id'] = $activityTypeIdInList; | |
429 | } | |
430 | elseif ($activityTypeId && | |
431 | !array_key_exists($activityTypeId, $activityTypes) | |
432 | ) { | |
10114f2d | 433 | throw new API_Exception('Invalid Activity Type ID'); |
6a488035 TO |
434 | } |
435 | ||
6a488035 TO |
436 | // check for activity duration minutes |
437 | // this should be validated @ the wrapper layer not here | |
438 | // needs testing | |
439 | if (isset($params['duration_minutes']) && !is_numeric($params['duration_minutes'])) { | |
10114f2d | 440 | throw new API_Exception('Invalid Activity Duration (in minutes)'); |
6a488035 TO |
441 | } |
442 | ||
6a488035 TO |
443 | //if adding a new activity & date_time not set make it now |
444 | // this should be managed by the wrapper layer & setting ['api.default'] in speces | |
445 | // needs testing | |
8cc574cf | 446 | if (empty($params['id']) && empty($params['activity_date_time'])) { |
6a488035 TO |
447 | $params['activity_date_time'] = CRM_Utils_Date::processDate(date('Y-m-d H:i:s')); |
448 | } | |
449 | ||
450 | return NULL; | |
451 | } | |
452 | ||
dabf9814 | 453 | /** |
7cdbcb16 | 454 | * @see _civicrm_api3_generic_getlist_params |
dabf9814 | 455 | * |
7cdbcb16 TO |
456 | * @param array $request |
457 | * API request. | |
dabf9814 CW |
458 | */ |
459 | function _civicrm_api3_activity_getlist_params(&$request) { | |
7cdbcb16 TO |
460 | $fieldsToReturn = array( |
461 | 'activity_date_time', | |
462 | 'activity_type_id', | |
463 | 'subject', | |
464 | 'source_contact_id', | |
465 | ); | |
dabf9814 CW |
466 | $request['params']['return'] = array_unique(array_merge($fieldsToReturn, $request['extra'])); |
467 | $request['params']['options']['sort'] = 'activity_date_time DESC'; | |
468 | $request['params'] += array( | |
469 | 'is_current_revision' => 1, | |
470 | 'is_deleted' => 0, | |
471 | ); | |
472 | } | |
473 | ||
474 | /** | |
475 | * @see _civicrm_api3_generic_getlist_output | |
476 | * | |
8c6b335b CW |
477 | * @param array $result |
478 | * @param array $request | |
dabf9814 CW |
479 | * |
480 | * @return array | |
481 | */ | |
482 | function _civicrm_api3_activity_getlist_output($result, $request) { | |
483 | $output = array(); | |
484 | if (!empty($result['values'])) { | |
485 | foreach ($result['values'] as $row) { | |
486 | $data = array( | |
487 | 'id' => $row[$request['id_field']], | |
488 | 'label' => $row[$request['label_field']] ? $row[$request['label_field']] : ts('(no subject)'), | |
7cdbcb16 TO |
489 | 'description' => array( |
490 | CRM_Core_Pseudoconstant::getLabel('CRM_Activity_BAO_Activity', 'activity_type_id', $row['activity_type_id']), | |
491 | ), | |
dabf9814 CW |
492 | ); |
493 | if (!empty($row['activity_date_time'])) { | |
494 | $data['description'][0] .= ': ' . CRM_Utils_Date::customFormat($row['activity_date_time']); | |
495 | } | |
496 | if (!empty($row['source_contact_id'])) { | |
7cdbcb16 TO |
497 | $data['description'][] = ts('By %1', array( |
498 | 1 => CRM_Core_DAO::getFieldValue('CRM_Contact_DAO_Contact', $row['source_contact_id'], 'display_name'), | |
499 | )); | |
dabf9814 CW |
500 | } |
501 | foreach ($request['extra'] as $field) { | |
502 | $data['extra'][$field] = isset($row[$field]) ? $row[$field] : NULL; | |
503 | } | |
504 | $output[] = $data; | |
505 | } | |
506 | } | |
507 | return $output; | |
508 | } |