Merge pull request #3917 from eileenmcnaughton/CRM-15168
[civicrm-core.git] / api / v3 / Relationship.php
CommitLineData
6a488035 1<?php
6a488035
TO
2
3/*
4 +--------------------------------------------------------------------+
731a0992 5 | CiviCRM version 4.5 |
6a488035 6 +--------------------------------------------------------------------+
731a0992 7 | Copyright CiviCRM LLC (c) 2004-2014 |
6a488035
TO
8 +--------------------------------------------------------------------+
9 | This file is a part of CiviCRM. |
10 | |
11 | CiviCRM is free software; you can copy, modify, and distribute it |
12 | under the terms of the GNU Affero General Public License |
13 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
14 | |
15 | CiviCRM is distributed in the hope that it will be useful, but |
16 | WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
18 | See the GNU Affero General Public License for more details. |
19 | |
20 | You should have received a copy of the GNU Affero General Public |
21 | License and the CiviCRM Licensing Exception along |
22 | with this program; if not, contact CiviCRM LLC |
23 | at info[AT]civicrm[DOT]org. If you have questions about the |
24 | GNU Affero General Public License or the licensing of CiviCRM, |
25 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
26 +--------------------------------------------------------------------+
27*/
28
29/**
30 * File for the CiviCRM APIv3 relationship functions
31 *
32 * @package CiviCRM_APIv3
33 * @subpackage API_Relationship
34 *
731a0992 35 * @copyright CiviCRM LLC (c) 2004-2014
6a488035
TO
36 * @version $Id: Relationship.php 30486 2010-11-02 16:12:09Z shot $
37 *
38 */
39
40/**
41 * Add or update a relationship
42 *
77b97be7 43 * @param array $params input parameters
6a488035 44 *
77b97be7 45 * @throws API_Exception
6a488035
TO
46 * @example RelationshipCreate.php Std Create example
47 *
48 * @return array API Result Array
49 * {@getfields relationship_create}
50 * @static void
51 * @access public
6a488035
TO
52 */
53function civicrm_api3_relationship_create($params) {
54
55 $values = array();
56 _civicrm_api3_relationship_format_params($params, $values);
57 $ids = array();
4404e34e 58 $action = CRM_Core_Action::ADD;
6a488035 59
a7488080 60 if (!empty($params['id'])) {
6a488035 61 $ids['contactTarget'] = $values['contact_id_b'];
4404e34e 62 $action = CRM_Core_Action::UPDATE;
6a488035
TO
63 }
64
65 $values['relationship_type_id'] = $values['relationship_type_id'] . '_a_b';
26dcc9eb 66 if(!empty($params['contact_id_b'])){
67 $values['contact_check'] = array($params['contact_id_b'] => $params['contact_id_b']);
68 }
69 if(!empty($values['contact_id_a'])){
70 $ids['contact'] = $values['contact_id_a'];
71 }
6a488035
TO
72 $relationshipBAO = CRM_Contact_BAO_Relationship::create($values, $ids);
73
74 if ($relationshipBAO[1]) {
26dcc9eb 75 throw new API_Exception('Relationship is not valid');
6a488035
TO
76 }
77 elseif ($relationshipBAO[2]) {
26dcc9eb 78 throw new API_Exception('Relationship already exists');
6a488035 79 }
4404e34e
CW
80 // Handle related memberships CRM-13652
81 if (!empty($params['contact_id_a'])) {
82 CRM_Contact_BAO_Relationship::relatedMemberships($params['contact_id_a'], $values, $ids, $action);
83 }
26dcc9eb 84 $id = $relationshipBAO[4][0];
85 $values = array();
86 _civicrm_api3_object_to_array($relationshipBAO[5][$id], $values[$id]);
87 return civicrm_api3_create_success($values, $params, 'relationship', 'create');
6a488035 88}
11e09c59
TO
89
90/**
6a488035
TO
91 * Adjust Metadata for Create action
92 *
93 * @param array $params array or parameters determined by getfields
94 */
95function _civicrm_api3_relationship_create_spec(&$params) {
96 $params['contact_id_a']['api.required'] = 1;
97 $params['contact_id_b']['api.required'] = 1;
98 $params['relationship_type_id']['api.required'] = 1;
99 $params['is_active']['api.default'] = 1;
100}
101
102/**
103 * Delete a relationship
104 *
105 * @param array $params
106 *
107 * @return array API Result Array
108 * {@getfields relationship_delete}
109 * @example RelationshipDelete.php Delete Example
110 *
111 * @static void
112 * @access public
113 */
114function civicrm_api3_relationship_delete($params) {
115
6a488035
TO
116 if (!CRM_Utils_Rule::integer($params['id'])) {
117 return civicrm_api3_create_error('Invalid value for relationship ID');
118 }
119
120 $relationBAO = new CRM_Contact_BAO_Relationship();
121 $relationBAO->id = $params['id'];
122 if (!$relationBAO->find(TRUE)) {
123 return civicrm_api3_create_error('Relationship id is not valid');
124 }
125 else {
126 $relationBAO->del($params['id']);
127 return civicrm_api3_create_success('Deleted relationship successfully');
128 }
129}
130
131/**
132 * Function to get the relationship
133 *
134 * @param array $params input parameters.
135 * @todo Result is inconsistent depending on whether contact_id is passed in :
136 * - if you pass in contact_id - it just returns all relationships for 'contact_id'
137 * - if you don't pass in contact_id then it does a filter on the relationship table (DAO based search)
138 *
139 * @return Array API Result Array
140 * {@getfields relationship_get}
141 * @example RelationshipGet.php
142 * @access public
143 */
144function civicrm_api3_relationship_get($params) {
75638074 145 $options = _civicrm_api3_get_options_from_params($params);
c9c41397 146
a7488080 147 if (empty($params['contact_id'])) {
c9c41397 148 if(!empty($params['membership_type_id']) && empty($params['relationship_type_id'])) {
149 CRM_Contact_BAO_Relationship::membershipTypeToRelationshipTypes($params);
150 }
6a488035
TO
151 $relationships = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE);
152 }
153 else {
154 $relationships = array();
155 $relationships = CRM_Contact_BAO_Relationship::getRelationship($params['contact_id'],
156 CRM_Utils_Array::value('status_id', $params),
157 0,
75638074 158 CRM_Utils_Array::value('is_count', $options),
159 CRM_Utils_Array::value('id', $params),
160 NULL,
161 NULL,
162 FALSE,
163 $params
6a488035
TO
164 );
165 }
75638074 166 //perhaps we should add a 'getcount' but at this stage lets just handle getcount output
167 if($options['is_count']) {
168 return array('count' => $relationships);
169 }
6a488035
TO
170 foreach ($relationships as $relationshipId => $values) {
171 _civicrm_api3_custom_data_get($relationships[$relationshipId], 'Relationship', $relationshipId, NULL, CRM_Utils_Array::value('relationship_type_id',$values));
172 }
6a488035
TO
173 return civicrm_api3_create_success($relationships, $params);
174}
175
176/**
177 * take the input parameter list as specified in the data model and
178 * convert it into the same format that we use in QF and BAO object
179 *
77b97be7 180 * @param array $params Associative array of property name/value
6a488035 181 * pairs to insert in new contact.
77b97be7 182 * @param array $values The reformatted properties that we can use internally
6a488035
TO
183 * '
184 *
77b97be7 185 * @throws Exception
6a488035
TO
186 * @return array|CRM_Error
187 * @access public
188 */
189function _civicrm_api3_relationship_format_params($params, &$values) {
190 // copy all the relationship fields as is
191
192 $fields = CRM_Contact_DAO_Relationship::fields();
193 _civicrm_api3_store_values($fields, $params, $values);
194
195 $relationTypes = CRM_Core_PseudoConstant::relationshipType('name');
a7488080 196 if (!empty($params['id'])) {
6a488035
TO
197 $relation = new CRM_Contact_BAO_Relationship();
198 $relation->id = $params['id'];
199 if (!$relation->find(TRUE)) {
200 throw new Exception('Relationship id is not valid');
201 }
202 else {
203 if ((isset($params['contact_id_a']) && $params['contact_id_a'] != $relation->contact_id_a) ||
204 (isset($params['contact_id_b']) && $params['contact_id_b'] != $relation->contact_id_b)
205 ) {
206 throw new Exception('Cannot change the contacts once relationship has been created');
207 }
208 else {
209 // since the BAO function is not std & won't accept just 'id' (aargh) let's
210 // at least return our BAO here
211 $values = array();
212 _civicrm_api3_object_to_array($relation, $values);
213 $values = array_merge($values, $params);
214 // and we need to reformat our date fields....
215 $dateFields = array('start_date', 'end_date');
216 foreach ($dateFields as $dateField){
217 $values[$dateField] = CRM_Utils_Date::processDate($values[$dateField]);
218 }
219 }
220 }
221 }
222
223 foreach ($params as $key => $value) {
224 // ignore empty values or empty arrays etc
6a488035
TO
225 if (CRM_Utils_System::isNull($value)) {
226 continue;
227 }
228
229 switch ($key) {
230 case 'contact_id_a':
231 case 'contact_id_b':
6a488035
TO
232 if (!CRM_Utils_Rule::integer($value)) {
233 throw new Exception("contact_id not valid: $value");
234 }
235 $dao = new CRM_Core_DAO();
236 $qParams = array();
237 $svq = $dao->singleValueQuery("SELECT id FROM civicrm_contact WHERE id = $value",
238 $qParams
239 );
240 if (!$svq) {
241 throw new Exception("Invalid Contact ID: There is no contact record with contact_id = $value.");
242 }
243 break;
244
245 case 'relationship_type':
246 foreach ($relationTypes as $relTypId => $relValue) {
247 if (CRM_Utils_Array::key(ucfirst($value), $relValue)) {
248 $relationshipTypeId = $relTypId;
249 break;
250 }
251 }
252
253 if ($relationshipTypeId) {
a7488080 254 if (!empty($values['relationship_type_id']) &&
6a488035
TO
255 $relationshipTypeId != $values['relationship_type_id']
256 ) {
257 throw new Exception('Mismatched Relationship Type and Relationship Type Id');
258 }
259 $values['relationship_type_id'] = $params['relationship_type_id'] = $relationshipTypeId;
260 }
261 else {
262 throw new Exception('Invalid Relationship Type');
263 }
264 case 'relationship_type_id':
265 if ($key == 'relationship_type_id' && !array_key_exists($value, $relationTypes)) {
266 throw new Exception("$key not a valid: $value");
267 }
268
269 // execute for both relationship_type and relationship_type_id
270 $relation = $relationTypes[$params['relationship_type_id']];
271 if (!empty($params['contact_id_a']) && $relation['contact_type_a'] &&
272 $relation['contact_type_a'] != CRM_Contact_BAO_Contact::getContactType($params['contact_id_a'])
273 ) {
274 throw new Exception("Contact ID :{$params['contact_id_a']} is not of contact type {$relation['contact_type_a']}");
275 }
276 if (!empty($params['contact_id_b']) && $relation['contact_type_b'] &&
277 $relation['contact_type_b'] != CRM_Contact_BAO_Contact::getContactType($params['contact_id_b'])
278 ) {
279 throw new Exception("Contact ID :{$params['contact_id_b']} is not of contact type {$relation['contact_type_b']}");
280 }
281 break;
282
283 default:
284 break;
285 }
286 }
287
288 if (array_key_exists('note', $params)) {
289 $values['note'] = $params['note'];
290 }
291 _civicrm_api3_custom_format_params($params, $values, 'Relationship');
292
293 return array();
294}