Merge pull request #864 from eileenmcnaughton/CRM-12160
[civicrm-core.git] / api / v2 / Activity.php
1 <?php
2 // $Id: Activity.php 45502 2013-02-08 13:32:55Z kurund $
3
4
5 /*
6 +--------------------------------------------------------------------+
7 | CiviCRM version 4.3 |
8 +--------------------------------------------------------------------+
9 | Copyright CiviCRM LLC (c) 2004-2013 |
10 +--------------------------------------------------------------------+
11 | This file is a part of CiviCRM. |
12 | |
13 | CiviCRM is free software; you can copy, modify, and distribute it |
14 | under the terms of the GNU Affero General Public License |
15 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
16 | |
17 | CiviCRM is distributed in the hope that it will be useful, but |
18 | WITHOUT ANY WARRANTY; without even the implied warranty of |
19 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
20 | See the GNU Affero General Public License for more details. |
21 | |
22 | You should have received a copy of the GNU Affero General Public |
23 | License and the CiviCRM Licensing Exception along |
24 | with this program; if not, contact CiviCRM LLC |
25 | at info[AT]civicrm[DOT]org. If you have questions about the |
26 | GNU Affero General Public License or the licensing of CiviCRM, |
27 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
28 +--------------------------------------------------------------------+
29 */
30
31 /**
32 * File for the CiviCRM APIv2 activity functions
33 *
34 * @package CiviCRM_APIv2
35 * @subpackage API_Activity
36 * @copyright CiviCRM LLC (c) 2004-2013
37 * @version $Id: Activity.php 45502 2013-02-08 13:32:55Z kurund $
38 *
39 */
40
41 /**
42 * Include common API util functions
43 */
44 require_once 'api/v2/utils.php';
45
46 require_once 'CRM/Activity/BAO/Activity.php';
47 require_once 'CRM/Core/DAO/OptionGroup.php';
48
49 // require these to call new function names from deprecated ones in here
50 require_once 'api/v2/ActivityType.php';
51 require_once 'api/v2/ActivityContact.php';
52
53 /**
54 * Create a new Activity.
55 *
56 * Creates a new Activity record and returns the newly created
57 * activity object (including the contact_id property). Minimum
58 * required data values for the various contact_type are:
59 *
60 * Properties which have administratively assigned sets of values
61 * If an unrecognized value is passed, an error
62 * will be returned.
63 *
64 * Modules may invoke crm_get_contact_values($contactID) to
65 * retrieve a list of currently available values for a given
66 * property.
67 *
68 * @param array $params Associative array of property name/value
69 * pairs to insert in new contact.
70 * @param string $activity_type Which class of contact is being created.
71 * Valid values = 'SMS', 'Meeting', 'Event', 'PhoneCall'.
72 * {@schema Activity/Activity.xml}
73 *
74 * @return CRM_Activity|CRM_Error Newly created Activity object
75 */
76 function &civicrm_activity_create(&$params) {
77 _civicrm_initialize();
78
79 $errors = array();
80
81 // check for various error and required conditions
82 $errors = _civicrm_activity_check_params($params, TRUE);
83
84 if (!empty($errors)) {
85 return $errors;
86 }
87
88 // processing for custom data
89 $values = array();
90 _civicrm_custom_format_params($params, $values, 'Activity');
91 if (!empty($values['custom'])) {
92 $params['custom'] = $values['custom'];
93 }
94
95 // create activity
96 $activity = CRM_Activity_BAO_Activity::create($params);
97
98 if (!is_a($activity, 'CRM_Core_Error') && isset($activity->id)) {
99 $activityArray = array('is_error' => 0);
100 }
101 else {
102 $activityArray = array('is_error' => 1);
103 }
104
105 _civicrm_object_to_array($activity, $activityArray);
106
107 return $activityArray;
108 }
109
110 /**
111 *
112 * @param <type> $params
113 * @param <type> $returnCustom
114 *
115 * @return <type>
116 */
117 function civicrm_activity_get($params, $returnCustom = FALSE) {
118 _civicrm_initialize();
119
120 $activityId = CRM_Utils_Array::value('activity_id', $params);
121 if (empty($activityId)) {
122 return civicrm_create_error(ts("Required parameter not found"));
123 }
124
125 if (!is_numeric($activityId)) {
126 return civicrm_create_error(ts("Invalid activity Id"));
127 }
128
129 $activity = _civicrm_activity_get($activityId, $returnCustom);
130
131 if ($activity) {
132 return civicrm_create_success($activity);
133 }
134 else {
135 return civicrm_create_error(ts('Invalid Data'));
136 }
137 }
138
139 /**
140 * Wrapper to make this function compatible with the REST API
141 *
142 * Obsolete now; if no one is using this, it should be removed. -- Wes Morgan
143 */
144 function civicrm_activity_get_contact($params) {
145 // TODO: Spit out deprecation warning here
146 return civicrm_activities_get_contact($params);
147 }
148
149 /**
150 * Retrieve a set of activities, specific to given input params.
151 *
152 * @param array $params (reference ) input parameters.
153 * @deprecated from 3.4 - use civicrm_activity_contact_get
154 *
155 * @return array (reference) array of activities / error message.
156 * @access public
157 */
158 function civicrm_activities_get_contact($params) {
159 // TODO: Spit out deprecation warning here
160 return civicrm_activity_contact_get($params);
161 }
162
163 /**
164 * Update a specified activity.
165 *
166 * Updates activity with the values passed in the 'params' array. An
167 * error is returned if an invalid id or activity Name is passed
168 *
169 * @param CRM_Activity $activity A valid Activity object
170 * @param array $params Associative array of property
171 * name/value pairs to be updated.
172 *
173 * @return CRM_Activity|CRM_Core_Error Return the updated ActivtyType Object else
174 * Error Object (if integrity violation)
175 *
176 * @access public
177 *
178 */
179 function &civicrm_activity_update(&$params) {
180 $errors = array();
181 //check for various error and required conditions
182 $errors = _civicrm_activity_check_params($params);
183
184 if (!empty($errors)) {
185 return $errors;
186 }
187
188 // processing for custom data
189 $values = array();
190 _civicrm_custom_format_params($params, $values, 'Activity');
191 if (!empty($values['custom'])) {
192 $params['custom'] = $values['custom'];
193 }
194
195 $activity = CRM_Activity_BAO_Activity::create($params);
196 $activityArray = array();
197 _civicrm_object_to_array($activity, $activityArray);
198
199 return $activityArray;
200 }
201
202 /**
203 * Delete a specified Activity.
204 *
205 * @param CRM_Activity $activity Activity object to be deleted
206 *
207 * @return void|CRM_Core_Error An error if 'activityName or ID' is invalid,
208 * permissions are insufficient, etc.
209 *
210 * @access public
211 *
212 */
213 function civicrm_activity_delete(&$params) {
214 _civicrm_initialize();
215
216 $errors = array();
217
218 //check for various error and required conditions
219 $errors = _civicrm_activity_check_params($params);
220
221 if (!empty($errors)) {
222 return $errors;
223 }
224
225 if (CRM_Activity_BAO_Activity::deleteActivity($params)) {
226 return civicrm_create_success();
227 }
228 else {
229 return civicrm_create_error(ts('Could not delete activity'));
230 }
231 }
232
233 /**
234 * Retrieve a specific Activity by Id.
235 *
236 * @param int $activityId
237 *
238 * @return array (reference) activity object
239 * @access public
240 */
241 function _civicrm_activity_get($activityId, $returnCustom = FALSE) {
242 $dao = new CRM_Activity_BAO_Activity();
243 $dao->id = $activityId;
244 if ($dao->find(TRUE)) {
245 $activity = array();
246 _civicrm_object_to_array($dao, $activity);
247
248 //also return custom data if needed.
249 if ($returnCustom && !empty($activity)) {
250 $customdata = civicrm_activity_custom_get(array(
251 'activity_id' => $activityId,
252 'activity_type_id' => $activity['activity_type_id'],
253 ));
254 $activity = array_merge($activity, $customdata);
255 }
256
257 return $activity;
258 }
259 else {
260 return FALSE;
261 }
262 }
263
264 /**
265 * Function to check for required params
266 *
267 * @param array $params associated array of fields
268 * @param boolean $addMode true for add mode
269 *
270 * @return array $error array with errors
271 */
272 function _civicrm_activity_check_params(&$params, $addMode = FALSE) {
273 // return error if we do not get any params
274 if (empty($params)) {
275 return civicrm_create_error(ts('Input Parameters empty'));
276 }
277
278 $contactIds = array('source' => CRM_Utils_Array::value('source_contact_id', $params),
279 'assignee' => CRM_Utils_Array::value('assignee_contact_id', $params),
280 'target' => CRM_Utils_Array::value('target_contact_id', $params),
281 );
282
283 foreach ($contactIds as $key => $value) {
284 if (empty($value)) {
285 continue;
286 }
287 $valueIds = array($value);
288 if (is_array($value)) {
289 $valueIds = array();
290 foreach ($value as $id) {
291 if (is_numeric($id)) {
292 $valueIds[$id] = $id;
293 }
294 }
295 }
296 elseif (!is_numeric($value)) {
297 return civicrm_create_error(ts('Invalid %1 Contact Id', array(
298 1 => ucfirst(
299 $key
300 ))));
301 }
302
303 if (empty($valueIds)) {
304 continue;
305 }
306
307 $sql = '
308 SELECT count(*)
309 FROM civicrm_contact
310 WHERE id IN (' . implode(', ', $valueIds) . ' )';
311 if (count($valueIds) != CRM_Core_DAO::singleValueQuery($sql)) {
312 return civicrm_create_error(ts('Invalid %1 Contact Id', array(1 => ucfirst($key))));
313 }
314 }
315
316 $activityIds = array('activity' => CRM_Utils_Array::value('id', $params),
317 'parent' => CRM_Utils_Array::value('parent_id', $params),
318 'original' => CRM_Utils_Array::value('original_id', $params),
319 );
320
321 foreach ($activityIds as $id => $value) {
322 if ($value &&
323 !CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $value, 'id')
324 ) {
325 return civicrm_create_error(ts('Invalid %1 Id', array(1 => ucfirst($id))));
326 }
327 }
328
329 if (!$addMode && !isset($params['id'])) {
330 return civicrm_create_error(ts('Required parameter "id" not found'));
331 }
332
333 // check for source contact id
334 if ($addMode && empty($params['source_contact_id'])) {
335 return civicrm_create_error(ts('Missing Source Contact'));
336 }
337
338 // check for activity subject if add mode
339 if ($addMode && !isset($params['subject'])) {
340 return civicrm_create_error(ts('Missing Subject'));
341 }
342
343 if (!$addMode && $params['id'] && !is_numeric($params['id'])) {
344 return civicrm_create_error(ts('Invalid activity "id"'));
345 }
346
347 require_once 'CRM/Core/PseudoConstant.php';
348 $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, TRUE, 'name');
349
350 // check if activity type_id is passed in
351 if ($addMode && !isset($params['activity_name']) && !isset($params['activity_type_id'])) {
352 //when name AND id are both absent
353 return civicrm_create_error(ts('Missing Activity Type'));
354 }
355 else {
356 $activityName = CRM_Utils_Array::value('activity_name', $params);
357 $activityTypeId = CRM_Utils_Array::value('activity_type_id', $params);
358
359 if ($activityName) {
360 $activityNameId = array_search(ucfirst($activityName), $activityTypes);
361
362 if (!$activityNameId) {
363 return civicrm_create_error(ts('Invalid Activity Name'));
364 }
365 elseif ($activityTypeId && ($activityTypeId != $activityNameId)) {
366 return civicrm_create_error(ts('Mismatch in Activity'));
367 }
368 $params['activity_type_id'] = $activityNameId;
369 }
370 elseif ($activityTypeId &&
371 !array_key_exists($activityTypeId, $activityTypes)
372 ) {
373 return civicrm_create_error(ts('Invalid Activity Type ID'));
374 }
375 }
376
377 // check for activity status is passed in
378 if (isset($params['status_id'])) {
379 require_once "CRM/Core/PseudoConstant.php";
380 $activityStatus = CRM_Core_PseudoConstant::activityStatus();
381
382 if (is_numeric($params['status_id']) && !array_key_exists($params['status_id'], $activityStatus)) {
383 return civicrm_create_error(ts('Invalid Activity Status'));
384 }
385 elseif (!is_numeric($params['status_id'])) {
386 $statusId = array_search($params['status_id'], $activityStatus);
387
388 if (!is_numeric($statusId)) {
389 return civicrm_create_error(ts('Invalid Activity Status'));
390 }
391 }
392 }
393
394 if (isset($params['priority_id']) && is_numeric($params['priority_id'])) {
395 require_once "CRM/Core/PseudoConstant.php";
396 $activityPriority = CRM_Core_PseudoConstant::priority();
397 if (!array_key_exists($params['priority_id'], $activityPriority)) {
398 return civicrm_create_error(ts('Invalid Priority'));
399 }
400 }
401
402 // check for activity duration minutes
403 if (isset($params['duration_minutes']) && !is_numeric($params['duration_minutes'])) {
404 return civicrm_create_error(ts('Invalid Activity Duration (in minutes)'));
405 }
406
407 if ($addMode &&
408 !CRM_Utils_Array::value('activity_date_time', $params)
409 ) {
410 $params['activity_date_time'] = CRM_Utils_Date::processDate(date('Y-m-d H:i:s'));
411 }
412 else {
413 if (CRM_Utils_Array::value('activity_date_time', $params)) {
414 $params['activity_date_time'] = CRM_Utils_Date::processDate($params['activity_date_time']);
415 }
416 }
417
418 return NULL;
419 }
420
421 /**
422 * Convert an email file to an activity
423 */
424 function civicrm_activity_processemail($file, $activityTypeID, $result = array(
425 )) {
426 // do not parse if result array already passed (towards EmailProcessor..)
427 if (empty($result)) {
428 // might want to check that email is ok here
429 if (!file_exists($file) ||
430 !is_readable($file)
431 ) {
432 return CRM_Core_Error::createAPIError(ts('File %1 does not exist or is not readable',
433 array(1 => $file)
434 ));
435 }
436 }
437
438 require_once 'CRM/Utils/Mail/Incoming.php';
439 $result = CRM_Utils_Mail_Incoming::parse($file);
440 if ($result['is_error']) {
441 return $result;
442 }
443
444 $params = _civicrm_activity_buildmailparams($result, $activityTypeID);
445 return civicrm_activity_create($params);
446 }
447
448 /**
449 *
450 * @param <type> $result
451 * @param <type> $activityTypeID
452 *
453 * @return <type>
454 */
455 function _civicrm_activity_buildmailparams($result, $activityTypeID) {
456 // get ready for collecting data about activity to be created
457 $params = array();
458
459 $params['activity_type_id'] = $activityTypeID;
460 $params['status_id'] = 2;
461 $params['source_contact_id'] = $params['assignee_contact_id'] = $result['from']['id'];
462 $params['target_contact_id'] = array();
463 $keys = array('to', 'cc', 'bcc');
464 foreach ($keys as $key) {
465 if (is_array($result[$key])) {
466 foreach ($result[$key] as $key => $keyValue) {
467 if (!empty($keyValue['id'])) {
468 $params['target_contact_id'][] = $keyValue['id'];
469 }
470 }
471 }
472 }
473 $params['subject'] = $result['subject'];
474 $params['activity_date_time'] = $result['date'];
475 $params['details'] = $result['body'];
476
477 for ($i = 1; $i <= 5; $i++) {
478 if (isset($result["attachFile_$i"])) {
479 $params["attachFile_$i"] = $result["attachFile_$i"];
480 }
481 }
482
483 return $params;
484 }
485
486 /**
487 *
488 * @param <type> $file
489 * @param <type> $activityTypeID
490 *
491 * @return <type>
492 * @deprecated since 3.4 use civicrm_activity_processemail
493 */
494 function civicrm_activity_process_email($file, $activityTypeID) {
495 // TODO: Spit out deprecation warning here
496 return civicrm_activity_processemail($file, $activityTypeID);
497 }
498
499 /**
500 * @deprecated since 3.4 use civicrm_activity_type_get
501 *
502 * @return <type>
503 */
504 function civicrm_activity_get_types() {
505 // TODO: Spit out deprecation warning here
506 return civicrm_activity_type_get();
507 }
508
509 /**
510 * Function retrieve activity custom data.
511 *
512 * @param array $params key => value array.
513 *
514 * @return array $customData activity custom data
515 *
516 * @access public
517 */
518 function civicrm_activity_custom_get($params) {
519
520 $customData = array();
521 if (!CRM_Utils_Array::value('activity_id', $params)) {
522 return $customData;
523 }
524
525 require_once 'CRM/Core/BAO/CustomGroup.php';
526 $groupTree = &CRM_Core_BAO_CustomGroup::getTree('Activity',
527 CRM_Core_DAO::$_nullObject,
528 $params['activity_id'],
529 NULL,
530 CRM_Utils_Array::value('activity_type_id', $params)
531 );
532 //get the group count.
533 $groupCount = 0;
534 foreach ($groupTree as $key => $value) {
535 if ($key === 'info') {
536 continue;
537 }
538 $groupCount++;
539 }
540 $formattedGroupTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree,
541 $groupCount,
542 CRM_Core_DAO::$_nullObject
543 );
544 $defaults = array();
545 CRM_Core_BAO_CustomGroup::setDefaults($formattedGroupTree, $defaults);
546 if (!empty($defaults)) {
547 foreach ($defaults as $key => $val) {
548 $customData[$key] = $val;
549 }
550 }
551
552 return $customData;
553 }
554