Commit | Line | Data |
---|---|---|
6a488035 TO |
1 | <?php |
2 | // $Id$ | |
3 | ||
4 | /* | |
5 | +--------------------------------------------------------------------+ | |
6 | | CiviCRM version 4.3 | | |
7 | +--------------------------------------------------------------------+ | |
8 | | Copyright CiviCRM LLC (c) 2004-2013 | | |
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 | |
35 | * @copyright CiviCRM LLC (c) 2004-2013 | |
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 | * | |
44 | * @param array $params Associative array of property name/value | |
45 | * pairs for the activity. | |
46 | * {@getfields activity_create} | |
47 | * | |
48 | * @return array Array containing 'is_error' to denote success or failure and details of the created activity | |
49 | * | |
50 | * @example ActivityCreate.php Standard create example | |
51 | * @example Activity/ContactRefCustomField.php Create example including setting a contact reference custom field | |
52 | * {@example ActivityCreate.php 0} | |
53 | * | |
54 | */ | |
55 | function civicrm_api3_activity_create($params) { | |
56 | ||
57 | if (!CRM_Utils_Array::value('id', $params)) { | |
58 | // an update does not require any mandatory parameters | |
59 | civicrm_api3_verify_one_mandatory($params, | |
60 | NULL, | |
61 | array( | |
62 | 'activity_name', 'activity_type_id', 'activity_label', | |
63 | ) | |
64 | ); | |
65 | } | |
66 | ||
67 | $errors = array(); | |
68 | ||
69 | // check for various error and required conditions | |
70 | // note that almost all the processing in there should be managed by the wrapper layer | |
71 | // & should be removed - needs testing | |
72 | $errors = _civicrm_api3_activity_check_params($params); | |
73 | ||
74 | // this should not be required as should throw exception rather than return errors - | |
75 | //needs testing | |
76 | if (!empty($errors)) { | |
77 | return $errors; | |
78 | } | |
79 | ||
80 | ||
81 | // processing for custom data | |
82 | $values = array(); | |
83 | _civicrm_api3_custom_format_params($params, $values, 'Activity'); | |
84 | ||
85 | if (!empty($values['custom'])) { | |
86 | $params['custom'] = $values['custom']; | |
87 | } | |
88 | ||
89 | // this should be set as a default rather than hard coded | |
90 | // needs testing | |
91 | $params['skipRecentView'] = TRUE; | |
92 | ||
93 | // If this is a case activity, see if there is an existing activity | |
94 | // and set it as an old revision. Also retrieve details we'll need. | |
95 | // this handling should all be moved to the BAO layer | |
96 | $case_id = ''; | |
97 | $createRevision = FALSE; | |
98 | $oldActivityValues = array(); | |
99 | if (CRM_Utils_Array::value('case_id', $params)) { | |
100 | $case_id = $params['case_id']; | |
101 | if (CRM_Utils_Array::value('id', $params)) { | |
102 | $oldActivityParams = array('id' => $params['id']); | |
103 | if (!$oldActivityValues) { | |
104 | CRM_Activity_BAO_Activity::retrieve($oldActivityParams, $oldActivityValues); | |
105 | } | |
106 | if (empty($oldActivityValues)) { | |
107 | return civicrm_api3_create_error(ts("Unable to locate existing activity."), NULL, CRM_Core_DAO::$_nullObject); | |
108 | } | |
109 | else { | |
110 | $activityDAO = new CRM_Activity_DAO_Activity(); | |
111 | $activityDAO->id = $params['id']; | |
112 | $activityDAO->is_current_revision = 0; | |
113 | if (!$activityDAO->save()) { | |
114 | return civicrm_api3_create_error(ts("Unable to revision existing case activity."), NULL, $activityDAO); | |
115 | } | |
116 | $createRevision = TRUE; | |
117 | } | |
118 | } | |
119 | } | |
120 | ||
121 | $deleteActivityAssignment = FALSE; | |
122 | if (isset($params['assignee_contact_id'])) { | |
123 | $deleteActivityAssignment = TRUE; | |
124 | } | |
125 | ||
126 | $deleteActivityTarget = FALSE; | |
127 | if (isset($params['target_contact_id'])) { | |
128 | $deleteActivityTarget = TRUE; | |
129 | } | |
130 | ||
131 | // this should all be handled at the BAO layer | |
132 | $params['deleteActivityAssignment'] = CRM_Utils_Array::value('deleteActivityAssignment', $params, $deleteActivityAssignment); | |
133 | $params['deleteActivityTarget'] = CRM_Utils_Array::value('deleteActivityTarget', $params, $deleteActivityTarget); | |
134 | ||
135 | if ($case_id && $createRevision) { | |
136 | // This is very similar to the copy-to-case action. | |
137 | if (!CRM_Utils_Array::crmIsEmptyArray($oldActivityValues['target_contact'])) { | |
138 | $oldActivityValues['targetContactIds'] = implode(',', array_unique($oldActivityValues['target_contact'])); | |
139 | } | |
140 | if (!CRM_Utils_Array::crmIsEmptyArray($oldActivityValues['assignee_contact'])) { | |
141 | $oldActivityValues['assigneeContactIds'] = implode(',', array_unique($oldActivityValues['assignee_contact'])); | |
142 | } | |
143 | $oldActivityValues['mode'] = 'copy'; | |
144 | $oldActivityValues['caseID'] = $case_id; | |
145 | $oldActivityValues['activityID'] = $oldActivityValues['id']; | |
146 | $oldActivityValues['contactID'] = $oldActivityValues['source_contact_id']; | |
147 | ||
148 | $copyToCase = CRM_Activity_Page_AJAX::_convertToCaseActivity($oldActivityValues); | |
149 | if (empty($copyToCase['error_msg'])) { | |
150 | // now fix some things that are different from copy-to-case | |
151 | // then fall through to the create below to update with the passed in params | |
152 | $params['id'] = $copyToCase['newId']; | |
153 | $params['is_auto'] = 0; | |
154 | $params['original_id'] = empty($oldActivityValues['original_id']) ? $oldActivityValues['id'] : $oldActivityValues['original_id']; | |
155 | } | |
156 | else { | |
157 | return civicrm_api3_create_error(ts("Unable to create new revision of case activity."), NULL, CRM_Core_DAO::$_nullObject); | |
158 | } | |
159 | } | |
160 | ||
161 | // create activity | |
162 | $activityBAO = CRM_Activity_BAO_Activity::create($params); | |
163 | ||
164 | if (isset($activityBAO->id)) { | |
165 | if ($case_id && !$createRevision) { | |
166 | // If this is a brand new case activity we need to add this | |
167 | $caseActivityParams = array('activity_id' => $activityBAO->id, 'case_id' => $case_id); | |
168 | CRM_Case_BAO_Case::processCaseActivity($caseActivityParams); | |
169 | } | |
170 | ||
171 | _civicrm_api3_object_to_array($activityBAO, $activityArray[$activityBAO->id]); | |
172 | return civicrm_api3_create_success($activityArray, $params, 'activity', 'get', $activityBAO); | |
173 | } | |
174 | } | |
11e09c59 TO |
175 | |
176 | /** | |
6a488035 TO |
177 | * Specify Meta data for create. Note that this data is retrievable via the getfields function |
178 | * and is used for pre-filling defaults and ensuring mandatory requirements are met. | |
179 | * @param array $params (reference) array of parameters determined by getfields | |
180 | */ | |
181 | function _civicrm_api3_activity_create_spec(&$params) { | |
182 | ||
183 | //default for source_contact_id = currently logged in user | |
184 | $params['source_contact_id']['api.default'] = 'user_contact_id'; | |
185 | ||
186 | $params['assignee_contact_id'] = array( | |
187 | 'name' => 'assignee_id', | |
188 | 'title' => 'assigned to', | |
189 | 'type' => 1, | |
190 | 'FKClassName' => 'CRM_Activity_DAO_ActivityAssignment', | |
191 | ); | |
192 | $params['target_contact_id'] = array( | |
193 | 'name' => 'target_id', | |
194 | 'title' => 'Activity Target', | |
195 | 'type' => 1, | |
196 | 'FKClassName' => 'CRM_Activity_DAO_ActivityTarget', | |
197 | ); | |
198 | $params['activity_status_id'] = array( | |
199 | 'name' => 'status_id', | |
200 | 'title' => 'Status Id', | |
201 | 'type' => 1, | |
202 | ); | |
203 | } | |
204 | ||
205 | /** | |
206 | * Gets a CiviCRM activity according to parameters | |
207 | * | |
208 | * @param array $params Associative array of property name/value | |
209 | * pairs for the activity. | |
210 | * | |
211 | * @return array | |
212 | * | |
213 | * {@getfields activity_get} | |
214 | * @example ActivityGet.php Basic example | |
215 | * @example Activity/DateTimeHigh.php Example get with date filtering | |
216 | * {@example ActivityGet.php 0} | |
217 | */ | |
218 | function civicrm_api3_activity_get($params) { | |
219 | if (!empty($params['contact_id'])) { | |
220 | $activities = CRM_Activity_BAO_Activity::getContactActivity($params['contact_id']); | |
221 | //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 | |
222 | foreach ($activities as $key => $activityArray) { | |
223 | $activities[$key]['id'] = $key; | |
224 | } | |
225 | } | |
226 | else { | |
227 | $activities = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE); | |
228 | } | |
229 | ||
230 | $returns = CRM_Utils_Array::value('return', $params, array()); | |
231 | if (!is_array($returns)) { | |
232 | $returns = str_replace(' ', '', $returns); | |
233 | $returns = explode(',', $returns); | |
234 | } | |
235 | $returns = array_fill_keys($returns, 1); | |
236 | ||
237 | foreach ($params as $n => $v) { | |
238 | if (substr($n, 0, 7) == 'return.') { | |
239 | $returnkey = substr($n, 7); | |
240 | $returns[$returnkey] = $v; | |
241 | } | |
242 | } | |
243 | ||
244 | foreach ($returns as $n => $v) { | |
245 | switch ($n) { | |
246 | case 'assignee_contact_id': | |
247 | foreach ($activities as $key => $activityArray) { | |
248 | $activities[$key]['assignee_contact_id'] = CRM_Activity_BAO_ActivityAssignment::retrieveAssigneeIdsByActivityId($activityArray['id']); | |
249 | } | |
250 | break; | |
251 | case 'target_contact_id': | |
252 | foreach ($activities as $key => $activityArray) { | |
253 | $activities[$key]['target_contact_id'] = CRM_Activity_BAO_ActivityTarget::retrieveTargetIdsByActivityId($activityArray['id']); | |
254 | } | |
255 | break; | |
256 | default: | |
257 | if (substr($n, 0, 6) == 'custom') { | |
258 | $returnProperties[$n] = $v; | |
259 | } | |
260 | } | |
261 | } | |
262 | if (!empty($activities) && (!empty($returnProperties) || !empty($params['contact_id']))) { | |
263 | foreach ($activities as $activityId => $values) { | |
264 | ||
265 | _civicrm_api3_custom_data_get($activities[$activityId], 'Activity', $activityId, NULL, $values['activity_type_id']); | |
266 | } | |
267 | } | |
268 | //legacy custom data get - so previous formatted response is still returned too | |
269 | return civicrm_api3_create_success($activities, $params, 'activity', 'get'); | |
270 | } | |
271 | ||
272 | /** | |
273 | * Delete a specified Activity. | |
274 | * | |
275 | * @param array $params array holding 'id' of activity to be deleted | |
276 | * {@getfields activity_delete} | |
277 | * | |
278 | * @return void|CRM_Core_Error An error if 'activityName or ID' is invalid, | |
279 | * permissions are insufficient, etc. or CiviCRM success array | |
280 | * | |
281 | * | |
282 | * | |
283 | * @example ActivityDelete.php Standard Delete Example | |
284 | * | |
285 | * | |
286 | */ | |
287 | function civicrm_api3_activity_delete($params) { | |
288 | ||
289 | if (CRM_Activity_BAO_Activity::deleteActivity($params)) { | |
290 | return civicrm_api3_create_success(1, $params, 'activity', 'delete'); | |
291 | } | |
292 | else { | |
293 | return civicrm_api3_create_error('Could not delete activity'); | |
294 | } | |
295 | } | |
296 | ||
297 | /** | |
298 | * Function to check for required params | |
299 | * | |
300 | * @param array $params associated array of fields | |
301 | * @param boolean $addMode true for add mode | |
302 | * | |
303 | * @return array $error array with errors | |
304 | */ | |
305 | function _civicrm_api3_activity_check_params(&$params) { | |
306 | ||
307 | $contactIDFields = array_intersect_key($params, | |
308 | array( | |
309 | 'source_contact_id' => 1, | |
310 | 'assignee_contact_id' => 1, | |
311 | 'target_contact_id' => 1, | |
312 | ) | |
313 | ); | |
314 | // this should be handled by wrapper layer & probably the api would already manage it | |
315 | //correctly by doing post validation - ie. a failure should result in a roll-back = an error | |
316 | // needs testing | |
317 | if (!empty($contactIDFields)) { | |
318 | $contactIds = array(); | |
319 | foreach ($contactIDFields as $fieldname => $contactfield) { | |
320 | if (empty($contactfield)) { | |
321 | continue; | |
322 | } | |
323 | if (is_array($contactfield)) { | |
324 | foreach ($contactfield as $contactkey => $contactvalue) { | |
325 | $contactIds[$contactvalue] = $contactvalue; | |
326 | } | |
327 | } | |
328 | else { | |
329 | $contactIds[$contactfield] = $contactfield; | |
330 | } | |
331 | } | |
332 | ||
333 | ||
334 | $sql = ' | |
335 | SELECT count(*) | |
336 | FROM civicrm_contact | |
337 | WHERE id IN (' . implode(', ', $contactIds) . ' )'; | |
338 | if (count($contactIds) != CRM_Core_DAO::singleValueQuery($sql)) { | |
339 | return civicrm_api3_create_error('Invalid ' . ' Contact Id'); | |
340 | } | |
341 | } | |
342 | ||
343 | ||
344 | $activityIds = array('activity' => CRM_Utils_Array::value('id', $params), | |
345 | 'parent' => CRM_Utils_Array::value('parent_id', $params), | |
346 | 'original' => CRM_Utils_Array::value('original_id', $params), | |
347 | ); | |
348 | ||
349 | foreach ($activityIds as $id => $value) { | |
350 | if ($value && | |
351 | !CRM_Core_DAO::getFieldValue('CRM_Activity_DAO_Activity', $value, 'id') | |
352 | ) { | |
353 | return civicrm_api3_create_error('Invalid ' . ucfirst($id) . ' Id'); | |
354 | } | |
355 | } | |
356 | // this should be handled by wrapper layer & probably the api would already manage it | |
357 | //correctly by doing pseudoconstant validation | |
358 | // needs testing | |
359 | $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'name', TRUE); | |
360 | $activityName = CRM_Utils_Array::value('activity_name', $params); | |
361 | $activityName = ucfirst($activityName); | |
362 | $activityLabel = CRM_Utils_Array::value('activity_label', $params); | |
363 | if ($activityLabel) { | |
364 | $activityTypes = CRM_Core_PseudoConstant::activityType(TRUE, TRUE, FALSE, 'label', TRUE); | |
365 | } | |
366 | ||
367 | $activityTypeId = CRM_Utils_Array::value('activity_type_id', $params); | |
368 | ||
369 | if ($activityName || $activityLabel) { | |
370 | $activityTypeIdInList = array_search(($activityName ? $activityName : $activityLabel), $activityTypes); | |
371 | ||
372 | if (!$activityTypeIdInList) { | |
373 | $errorString = $activityName ? "Invalid Activity Name : $activityName" : "Invalid Activity Type Label"; | |
374 | throw new Exception($errorString); | |
375 | } | |
376 | elseif ($activityTypeId && ($activityTypeId != $activityTypeIdInList)) { | |
377 | return civicrm_api3_create_error('Mismatch in Activity'); | |
378 | } | |
379 | $params['activity_type_id'] = $activityTypeIdInList; | |
380 | } | |
381 | elseif ($activityTypeId && | |
382 | !array_key_exists($activityTypeId, $activityTypes) | |
383 | ) { | |
384 | return civicrm_api3_create_error('Invalid Activity Type ID'); | |
385 | } | |
386 | ||
387 | // check for activity status is passed in | |
388 | // note this should all be removed in favour of wrapper layer validation | |
389 | // needs testing | |
390 | if (isset($params['activity_status_id'])) { | |
391 | $activityStatus = CRM_Core_PseudoConstant::activityStatus(); | |
392 | ||
393 | if (is_numeric($params['activity_status_id']) && !array_key_exists($params['activity_status_id'], $activityStatus)) { | |
394 | return civicrm_api3_create_error('Invalid Activity Status'); | |
395 | } | |
396 | elseif (!is_numeric($params['activity_status_id'])) { | |
397 | $statusId = array_search($params['activity_status_id'], $activityStatus); | |
398 | ||
399 | if (!is_numeric($statusId)) { | |
400 | return civicrm_api3_create_error('Invalid Activity Status'); | |
401 | } | |
402 | } | |
403 | } | |
404 | ||
405 | ||
406 | ||
407 | // check for activity duration minutes | |
408 | // this should be validated @ the wrapper layer not here | |
409 | // needs testing | |
410 | if (isset($params['duration_minutes']) && !is_numeric($params['duration_minutes'])) { | |
411 | return civicrm_api3_create_error('Invalid Activity Duration (in minutes)'); | |
412 | } | |
413 | ||
414 | ||
415 | //if adding a new activity & date_time not set make it now | |
416 | // this should be managed by the wrapper layer & setting ['api.default'] in speces | |
417 | // needs testing | |
418 | if (!CRM_Utils_Array::value('id', $params) && | |
419 | !CRM_Utils_Array::value('activity_date_time', $params) | |
420 | ) { | |
421 | $params['activity_date_time'] = CRM_Utils_Date::processDate(date('Y-m-d H:i:s')); | |
422 | } | |
423 | ||
424 | return NULL; | |
425 | } | |
426 |