Merge pull request #353 from eileenmcnaughton/trunk-kill-eval
[civicrm-core.git] / api / v2 / Relationship.php
1 <?php
2 // $Id: Relationship.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 relationship functions
33 *
34 * @package CiviCRM_APIv2
35 * @subpackage API_Relationship
36 *
37 * @copyright CiviCRM LLC (c) 2004-2013
38 * @version $Id: Relationship.php 45502 2013-02-08 13:32:55Z kurund $
39 *
40 */
41
42 /**
43 * Include utility functions
44 */
45 require_once 'api/v2/utils.php';
46 require_once 'CRM/Contact/BAO/Relationship.php';
47 require_once 'CRM/Contact/BAO/RelationshipType.php';
48
49 /**
50 * Add or update a relationship
51 *
52 * @param array $params (reference ) input parameters
53 *
54 * @return array (reference) id of created or updated record
55 * @static void
56 * @access public
57 */
58 function civicrm_relationship_create(&$params) {
59 _civicrm_initialize();
60
61 // check params for required fields (add/update)
62 $error = _civicrm_relationship_check_params($params);
63 if (civicrm_error($error)) {
64 return $error;
65 }
66 $values = array();
67 require_once 'CRM/Contact/BAO/Relationship.php';
68 $error = _civicrm_relationship_format_params($params, $values);
69
70 if (civicrm_error($error)) {
71 return $error;
72 }
73
74 $ids = array();
75 $action = CRM_Core_Action::ADD;
76 require_once 'CRM/Utils/Array.php';
77
78 if (CRM_Utils_Array::value('id', $params)) {
79 $ids['relationship'] = $params['id'];
80 $ids['contactTarget'] = $params['contact_id_b'];
81 $action = CRM_Core_Action::UPDATE;
82 }
83
84 $values['relationship_type_id'] = $params['relationship_type_id'] . '_a_b';
85 $values['contact_check'] = array($params['contact_id_b'] => $params['contact_id_b']);
86 $ids['contact'] = $params['contact_id_a'];
87
88 $relationshipBAO = CRM_Contact_BAO_Relationship::create($values, $ids);
89
90 if (is_a($relationshipBAO, 'CRM_Core_Error')) {
91 return civicrm_create_error('Relationship can not be created');
92 }
93 elseif ($relationshipBAO[1]) {
94 return civicrm_create_error('Relationship is not valid');
95 }
96 elseif ($relationshipBAO[2]) {
97 return civicrm_create_error('Relationship already exists');
98 }
99 CRM_Contact_BAO_Relationship::relatedMemberships($params['contact_id_a'], $values, $ids, $action);
100
101 return civicrm_create_success(array('id' => implode(',', $relationshipBAO[4])));
102 }
103
104 /**
105 * Delete a relationship
106 *
107 * @param id of relationship $id
108 *
109 * @return boolean true if success, else false
110 * @static void
111 * @access public
112 */
113 function civicrm_relationship_delete(&$params) {
114
115 if (empty($params)) {
116 return civicrm_create_error('No input parameter present');
117 }
118
119 if (!is_array($params)) {
120 return civicrm_create_error(ts('Input parameter is not an array'));
121 }
122
123 if (!CRM_Utils_Array::value('id', $params)) {
124 return civicrm_create_error('Missing required parameter');
125 }
126 require_once 'CRM/Utils/Rule.php';
127 if ($params['id'] != NULL && !CRM_Utils_Rule::integer($params['id'])) {
128 return civicrm_create_error('Invalid value for relationship ID');
129 }
130
131 $relationBAO = new CRM_Contact_BAO_Relationship();
132 $relationBAO->id = $params['id'];
133 if (!$relationBAO->find(TRUE)) {
134 return civicrm_create_error(ts('Relationship id is not valid'));
135 }
136 else {
137 $relationBAO->del($params['id']);
138 return civicrm_create_success(ts('Deleted relationship successfully'));
139 }
140 }
141
142 /**
143 * Function to update relationship
144 *
145 * @param array $params Associative array of property name/value pairs to update the relationship
146 *
147 * @return array Array with relationship information
148 *
149 * @access public
150 *
151 */
152 function civicrm_relationship_update($params) {
153 try {
154 _civicrm_initialize();
155 $errorScope = CRM_Core_TemporaryErrorScope::useException();
156
157 /*
158 * Erik Hommel, 5 Oct 2010 : fix for CRM-6895
159 * check if required field relationship_id is in the parms. As the
160 * CRM_Contact_BAO_Relationship::getRelatonship throws up some issues
161 * (CRM-6905) the relationship is retrieved with a direct query
162 */
163
164
165 civicrm_verify_mandatory($params, 'CRM_Contact_DAO_Relationship', array('relationship_id'));
166
167 $names = array(
168 'id', 'contact_id_a', 'contact_id_b',
169 'relationship_type_id', 'start_date', 'end_date', 'is_active',
170 'description', 'is_permission_a_b', 'is_permission_b_a', 'case_id',
171 );
172
173 $relationship_id = (int) $params['relationship_id'];
174 $query = "SELECT * FROM civicrm_relationship WHERE id = $relationship_id";
175 $daoRelations = CRM_Core_DAO::executeQuery($query);
176 while ($daoRelations->fetch()) {
177 foreach ($names as $name) {
178 $current_values[$name] = $daoRelations->$name;
179 }
180 }
181 $params = array_merge($current_values, $params);
182 $params['start_date'] = date("Ymd", strtotime($params['start_date']));
183 $params['end_date'] = date("Ymd", strtotime($params['end_date']));
184
185 return civicrm_relationship_create($params);
186 }
187 catch(PEAR_Exception$e) {
188 return civicrm_create_error($e->getMessage());
189 }
190 catch(Exception$e) {
191 return civicrm_create_error($e->getMessage());
192 }
193 }
194
195 /**
196 * Function to get the relationship
197 *
198 * @param array $params (reference ) input parameters
199 param['contact_id'] is mandatory
200 *
201 * @return Array of all relationship.
202 *
203 * @access public
204 */
205 function civicrm_relationship_get($params) {
206 if (!isset($params['contact_id'])) {
207 return civicrm_create_error(ts('Could not find contact_id in input parameters.'));
208 }
209
210 return civicrm_contact_relationship_get($params);
211 }
212
213 /**
214 * backward compatibility function to match broken naming convention in v2.2.1 and prior
215 */
216 function civicrm_get_relationships($contact_a, $contact_b = NULL, $relationshipTypes = NULL, $sort = NULL) {
217 return civicrm_contact_relationship_get($contact_a, $contact_b, $relationshipTypes, $sort);
218 }
219
220 /**
221 * Function to get the relationship
222 *
223 * @param array $contact_a (reference ) input parameters.
224 * @param array $contact_b (reference ) input parameters.
225 * @param array $relationshipTypes an array of Relationship Type Name.
226 * @param string $sort sort all relationship by relationshipId (eg asc/desc)
227 *
228 * @return Array of all relationship.
229 *
230 * @access public
231 */
232 function civicrm_contact_relationship_get($contact_a, $contact_b = NULL, $relationshipTypes = NULL, $sort = NULL) {
233 if (!is_array($contact_a)) {
234 return civicrm_create_error(ts('Input parameter is not an array'));
235 }
236
237 if (!isset($contact_a['contact_id'])) {
238 return civicrm_create_error(ts('Could not find contact_id in input parameters.'));
239 }
240 require_once 'CRM/Contact/BAO/Relationship.php';
241 $contactID = $contact_a['contact_id'];
242 $relationships = CRM_Contact_BAO_Relationship::getRelationship($contactID);
243
244 if (!empty($relationshipTypes)) {
245 $result = array();
246 foreach ($relationshipTypes as $relationshipName) {
247 foreach ($relationships as $key => $relationship) {
248 if ($relationship['relation'] == $relationshipName) {
249 $result[$key] = $relationship;
250 }
251 }
252 }
253 $relationships = $result;
254 }
255
256 if (isset($contact_b['contact_id'])) {
257 $cid = $contact_b['contact_id'];
258 $result = array();
259
260 foreach ($relationships as $key => $relationship) {
261 if ($relationship['cid'] == $cid) {
262 $result[$key] = $relationship;
263 }
264 }
265 $relationships = $result;
266 }
267
268 //sort by relationship id
269 if ($sort) {
270 if (strtolower($sort) == 'asc') {
271 ksort($relationships);
272 }
273 elseif (strtolower($sort) == 'desc') {
274 krsort($relationships);
275 }
276 }
277
278 //handle custom data.
279 require_once 'CRM/Core/BAO/CustomGroup.php';
280
281 foreach ($relationships as $relationshipId => $values) {
282 $groupTree = &CRM_Core_BAO_CustomGroup::getTree('Relationship', CRM_Core_DAO::$_nullObject, $relationshipId, FALSE,
283 $values['civicrm_relationship_type_id']
284 );
285 $formatTree = CRM_Core_BAO_CustomGroup::formatGroupTree($groupTree, 1, CRM_Core_DAO::$_nullObject);
286
287 $defaults = array();
288 CRM_Core_BAO_CustomGroup::setDefaults($formatTree, $defaults);
289
290 if (!empty($defaults)) {
291 foreach ($defaults as $key => $val) {
292 $relationships[$relationshipId][$key] = $val;
293 }
294 }
295 }
296
297 if ($relationships) {
298 return civicrm_create_success($relationships);
299 }
300 else {
301 return civicrm_create_error(ts('Invalid Data'));
302 }
303 }
304
305 /**
306 * take the input parameter list as specified in the data model and
307 * convert it into the same format that we use in QF and BAO object
308 *
309 * @param array $params Associative array of property name/value
310 * pairs to insert in new contact.
311 * @param array $values The reformatted properties that we can use internally
312 * '
313 *
314 * @return array|CRM_Error
315 * @access public
316 */
317 function _civicrm_relationship_format_params(&$params, &$values) {
318 // copy all the relationship fields as is
319
320 $fields = CRM_Contact_DAO_Relationship::fields();
321 _civicrm_store_values($fields, $params, $values);
322
323 $relationTypes = CRM_Core_PseudoConstant::relationshipType('name', TRUE);
324
325 foreach ($params as $key => $value) {
326 // ignore empty values or empty arrays etc
327 require_once 'CRM/Utils/System.php';
328 if (CRM_Utils_System::isNull($value)) {
329 continue;
330 }
331
332 switch ($key) {
333 case 'contact_id_a':
334 case 'contact_id_b':
335 require_once 'CRM/Utils/Rule.php';
336 if (!CRM_Utils_Rule::integer($value)) {
337 return civicrm_create_error("contact_id not valid: $value");
338 }
339 $dao = new CRM_Core_DAO();
340 $qParams = array();
341 $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
342 $qParams
343 );
344 if (!$svq) {
345 return civicrm_create_error("Invalid Contact ID: There is no contact record with contact_id = $value.");
346 }
347 break;
348
349 case 'start_date':
350 case 'end_date':
351 if (!CRM_Utils_Rule::qfDate($value)) {
352 return civicrm_create_error("$key not a valid date: $value");
353 }
354 break;
355
356 case 'relationship_type':
357 foreach ($relationTypes as $relTypId => $relValue) {
358 if (CRM_Utils_Array::key(ucfirst($value), $relValue)) {
359 $relationshipTypeId = $relTypId;
360 break;
361 }
362 }
363
364 if ($relationshipTypeId) {
365 if (CRM_Utils_Array::value('relationship_type_id', $values) &&
366 $relationshipTypeId != $values['relationship_type_id']
367 ) {
368 return civicrm_create_error('Mismatched Relationship Type and Relationship Type Id');
369 }
370 $values['relationship_type_id'] = $params['relationship_type_id'] = $relationshipTypeId;
371 }
372 else {
373 return civicrm_create_error('Invalid Relationship Type');
374 }
375 case 'relationship_type_id':
376 if ($key == 'relationship_type_id' && !array_key_exists($value, $relationTypes)) {
377 return civicrm_create_error("$key not a valid: $value");
378 }
379
380 // execute for both relationship_type and relationship_type_id
381 $relation = $relationTypes[$params['relationship_type_id']];
382 require_once 'CRM/Contact/BAO/Contact.php';
383 if ($relation['contact_type_a'] &&
384 $relation['contact_type_a'] != CRM_Contact_BAO_Contact::getContactType($params['contact_id_a'])
385 ) {
386 return civicrm_create_error("Contact ID :{$params['contact_id_a']} is not of contact type {$relation['contact_type_a']}");
387 }
388 if ($relation['contact_type_b'] &&
389 $relation['contact_type_b'] != CRM_Contact_BAO_Contact::getContactType($params['contact_id_b'])
390 ) {
391 return civicrm_create_error("Contact ID :{$params['contact_id_b']} is not of contact type {$relation['contact_type_b']}");
392 }
393 break;
394
395 default:
396 break;
397 }
398 }
399
400 if (array_key_exists('note', $params)) {
401 $values['note'] = $params['note'];
402 }
403 _civicrm_custom_format_params($params, $values, 'Relationship');
404
405 return array();
406 }
407
408 /**
409 * This function ensures that we have the right input parameters
410 *
411 * We also need to make sure we run all the form rules on the params list
412 * to ensure that the params are valid
413 *
414 * @param array $params Associative array of property name/value
415 * pairs to insert in new relationship.
416 *
417 * @return bool|CRM_Utils_Error
418 * @access private
419 */
420 function _civicrm_relationship_check_params(&$params) {
421 static $required = array(
422 'contact_id_a' => NULL,
423 'contact_id_b' => NULL,
424 'relationship_type_id' => 'relationship_type',
425 );
426
427 // params should be an array
428 if (!is_array($params)) {
429 return civicrm_create_error('Input parameter is not an array');
430 }
431 // cannot create with empty params
432 if (empty($params)) {
433 return civicrm_create_error('Input Parameters empty');
434 }
435 // check params for validity of Relationship id
436 if (CRM_Utils_Array::value('id', $params)) {
437 require_once 'CRM/Contact/BAO/Relationship.php';
438 $relation = new CRM_Contact_BAO_Relationship();
439 $relation->id = $params['id'];
440 if (!$relation->find(TRUE)) {
441 return civicrm_create_error('Relationship id is not valid');
442 }
443 else {
444 if (($params['contact_id_a'] != $relation->contact_id_a) ||
445 ($params['contact_id_b'] != $relation->contact_id_b)
446 ) {
447 return civicrm_create_error('Cannot change the contacts once relationship has been created');
448 }
449 }
450 }
451
452 $valid = TRUE;
453 $error = '';
454 foreach ($required as $field => $eitherField) {
455 if (!CRM_Utils_Array::value($field, $params)) {
456 if ($eitherField && CRM_Utils_Array::value($eitherField, $params)) {
457 continue;
458 }
459 $valid = FALSE;
460 $error .= " $field";
461 }
462 }
463
464 if (!$valid) {
465 return civicrm_create_error('Required fields not found' . $error);
466 }
467
468 return array();
469 }
470