Merge pull request #17387 from eileenmcnaughton/ct
[civicrm-core.git] / api / v3 / GroupContact.php
CommitLineData
6a488035 1<?php
6a488035
TO
2/*
3 +--------------------------------------------------------------------+
a30c801b 4 | Copyright CiviCRM LLC. All rights reserved. |
6a488035 5 | |
a30c801b
TO
6 | This work is published under the GNU AGPLv3 license with some |
7 | permitted exceptions and without any warranty. For full license |
8 | and copyright information, see https://civicrm.org/licensing |
6a488035
TO
9 +--------------------------------------------------------------------+
10 */
11
12/**
244bbdd8 13 * This api exposes CiviCRM GroupContact records.
6a488035 14 *
b081365f
CW
15 * This api is for adding/removing contacts from a group,
16 * or fetching a list of groups for a contact.
17 *
18 * Important note: This api does not fetch smart groups for a contact.
244bbdd8 19 * To fetch all contacts in a smart group, use the Contact api
b081365f
CW
20 * passing a contact_id and group_id.
21 *
22 * To create/delete groups, use the group api instead.
6a488035 23 *
b081365f 24 * @package CiviCRM_APIv3
6a488035
TO
25 */
26
6a488035 27/**
244bbdd8 28 * Fetch a list of groups for a contact, or contacts for a group.
22242c87 29 *
244bbdd8
CW
30 * @Note: this only applies to static groups, not smart groups.
31 * To fetch all contacts in a smart group, use the Contact api
32 * passing a contact_id and group_id.
22242c87 33 *
6a488035
TO
34 * If no status mentioned in params, by default 'added' will be used
35 * to fetch the records
36 *
cf470720
TO
37 * @param array $params
38 * Name value pair of contact information.
6a488035 39 *
a6c01b45 40 * @return array
72b3a70c 41 * list of groups, given contact subsribed to
6a488035
TO
42 */
43function civicrm_api3_group_contact_get($params) {
44
45 if (empty($params['contact_id'])) {
46 if (empty($params['status'])) {
47 //default to 'Added'
48 $params['status'] = 'Added';
49 }
50 //ie. id passed in so we have to return something
3d700d00 51 return _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params);
6a488035
TO
52 }
53 $status = CRM_Utils_Array::value('status', $params, 'Added');
54
f748c073 55 $groupId = $params['group_id'] ?? NULL;
bd1fbcb7 56 $values = CRM_Contact_BAO_GroupContact::getContactGroup($params['contact_id'], $status, NULL, FALSE, TRUE, FALSE, TRUE, $groupId);
244bbdd8 57 return civicrm_api3_create_success($values, $params, 'GroupContact');
6a488035
TO
58}
59
8d47034f
J
60/**
61 * Adjust metadata for Create action.
62 *
63 * @param array $params
64 */
65function _civicrm_api3_group_contact_create_spec(&$params) {
66 $params['contact_id']['api.required'] = 1;
67 $params['group_id']['api.required'] = 1;
68}
69
6a488035 70/**
22242c87
EM
71 * Add contact(s) to group(s).
72 *
b081365f
CW
73 * This api has a legacy/nonstandard signature.
74 * On success, the return array will be structured as follows:
0b882a86 75 * ```
b081365f 76 * array(
6a488035
TO
77 * "is_error" => 0,
78 * "version" => 3,
79 * "count" => 3,
80 * "values" => array(
81 * "not_added" => integer,
82 * "added" => integer,
83 * "total_count" => integer
84 * )
b081365f 85 * )
0b882a86 86 * ```
6a488035 87 *
b081365f 88 * On failure, the return array will be structured as follows:
0b882a86 89 * ```
b081365f 90 * array(
6a488035
TO
91 * 'is_error' => 1,
92 * 'error_message' = string,
93 * 'error_data' = mixed or undefined
b081365f 94 * )
0b882a86 95 * ```
b081365f
CW
96 *
97 * @param array $params
8d47034f
J
98 * Input parameters:
99 * - "contact_id" (required): First contact to add, or array of Contact IDs
100 * - "group_id" (required): First group to add contact(s) to, or array of Group IDs
101 * - "status" (optional): "Added" (default), "Pending" or "Removed"
102 * Legacy input parameters (will be deprecated):
103 * - "contact_id.1" etc. (optional): Additional contact_id to add to group(s)
104 * - "group_id.1" etc. (optional): Additional groups to add contact(s) to
b081365f
CW
105 *
106 * @return array
107 * Information about operation results
6a488035
TO
108 */
109function civicrm_api3_group_contact_create($params) {
3d700d00
CW
110 // Nonstandard bao - doesn't accept ID as a param, so convert id to group_id + contact_id
111 if (!empty($params['id'])) {
cf8f0fff 112 $getParams = ['id' => $params['id']];
3d700d00
CW
113 $info = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $getParams);
114 if (!empty($info['values'][$params['id']])) {
115 $params['group_id'] = $info['values'][$params['id']]['group_id'];
116 $params['contact_id'] = $info['values'][$params['id']]['contact_id'];
117 }
118 }
6a488035
TO
119 $action = CRM_Utils_Array::value('status', $params, 'Added');
120 return _civicrm_api3_group_contact_common($params, $action);
121}
11e09c59 122
6a488035 123/**
22242c87 124 * Delete group contact record.
6a488035 125 *
72b3a70c 126 * @param array $params
a6c01b45 127 * @return array
8089541a
SL
128 * @throws API_Exception
129 * @throws CiviCRM_API3_Exception
e0b82b44 130 * @deprecated
6a488035
TO
131 */
132function civicrm_api3_group_contact_delete($params) {
3c64f1f6 133 $checkParams = $params;
cf8f0fff
CW
134 if (!empty($checkParams['status']) && in_array($checkParams['status'], ['Removed', 'Deleted'])) {
135 $checkParams['status'] = ['IN' => ['Added', 'Pending']];
3c64f1f6
SL
136 }
137 elseif (!empty($checkParams['status']) && $checkParams['status'] == 'Added') {
cf8f0fff 138 $checkParams['status'] = ['IN' => ['Pending', 'Removed']];
3c64f1f6
SL
139 }
140 elseif (!empty($checkParams['status'])) {
141 unset($checkParams['status']);
142 }
143 $groupContact = civicrm_api3('GroupContact', 'get', $checkParams);
144 if ($groupContact['count'] == 0 && !empty($params['skip_undelete'])) {
cf8f0fff 145 $checkParams['status'] = ['IN' => ['Removed', 'Pending']];
3c64f1f6
SL
146 }
147 $groupContact2 = civicrm_api3('GroupContact', 'get', $checkParams);
4e5d12a1 148 if ($groupContact['count'] == 0 && $groupContact2['count'] == 0) {
a60c0bc8
SL
149 throw new API_Exception('Cannot Delete GroupContact');
150 }
3d700d00
CW
151 $params['status'] = CRM_Utils_Array::value('status', $params, empty($params['skip_undelete']) ? 'Removed' : 'Deleted');
152 // "Deleted" isn't a real option so skip the api wrapper to avoid pseudoconstant validation
153 return civicrm_api3_group_contact_create($params);
6a488035 154}
11e09c59
TO
155
156/**
dc64d047
EM
157 * Adjust metadata.
158 *
d0997921 159 * @param array $params
6a488035
TO
160 */
161function _civicrm_api3_group_contact_delete_spec(&$params) {
162 // set as not required no either/or std yet
163 $params['id']['api.required'] = 0;
164}
165
166/**
d1b0d05e 167 * Get pending group contacts.
6a488035 168 *
72b3a70c 169 * @param array $params
6a488035 170 *
72b3a70c 171 * @return array|int
e0b82b44 172 * @deprecated
6a488035
TO
173 */
174function civicrm_api3_group_contact_pending($params) {
175 $params['status'] = 'Pending';
176 return civicrm_api('GroupContact', 'Create', $params);
177}
178
179/**
dc64d047 180 * Group contact helper function.
6a488035 181 *
b081365f
CW
182 * @todo behaviour is highly non-standard - need to figure out how to make this 'behave'
183 * & at the very least return IDs & details of the groups created / changed
184 *
6a488035
TO
185 * @param array $params
186 * @param string $op
187 *
5396af74 188 * @return array
6a488035
TO
189 */
190function _civicrm_api3_group_contact_common($params, $op = 'Added') {
191
cf8f0fff
CW
192 $contactIDs = [];
193 $groupIDs = [];
8d47034f 194
cc7968d8 195 // CRM-16959: Handle multiple Contact IDs and Group IDs in legacy format
8d47034f 196 // (contact_id.1, contact_id.2) or as an array
6a488035
TO
197 foreach ($params as $n => $v) {
198 if (substr($n, 0, 10) == 'contact_id') {
8d47034f
J
199 if (is_array($v)) {
200 foreach ($v as $arr_v) {
201 $contactIDs[] = $arr_v;
202 }
203 }
204 else {
205 $contactIDs[] = $v;
206 }
6a488035
TO
207 }
208 elseif (substr($n, 0, 8) == 'group_id') {
8d47034f
J
209 if (is_array($v)) {
210 foreach ($v as $arr_v) {
211 $groupIDs[] = $arr_v;
212 }
213 }
214 else {
215 $groupIDs[] = $v;
216 }
6a488035
TO
217 }
218 }
219
6a488035
TO
220 $method = CRM_Utils_Array::value('method', $params, 'API');
221 $status = CRM_Utils_Array::value('status', $params, $op);
f748c073 222 $tracking = $params['tracking'] ?? NULL;
6a488035
TO
223
224 if ($op == 'Added' || $op == 'Pending') {
cf8f0fff 225 $extraReturnValues = [
6a488035
TO
226 'total_count' => 0,
227 'added' => 0,
21dfd5f5 228 'not_added' => 0,
cf8f0fff 229 ];
6a488035
TO
230 foreach ($groupIDs as $groupID) {
231 list($tc, $a, $na) = CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIDs,
232 $groupID,
233 $method,
234 $status,
235 $tracking
236 );
237 $extraReturnValues['total_count'] += $tc;
238 $extraReturnValues['added'] += $a;
239 $extraReturnValues['not_added'] += $na;
240 }
241 }
242 else {
cf8f0fff 243 $extraReturnValues = [
6a488035
TO
244 'total_count' => 0,
245 'removed' => 0,
21dfd5f5 246 'not_removed' => 0,
cf8f0fff 247 ];
6a488035
TO
248 foreach ($groupIDs as $groupID) {
249 list($tc, $r, $nr) = CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIDs, $groupID, $method, $status, $tracking);
250 $extraReturnValues['total_count'] += $tc;
251 $extraReturnValues['removed'] += $r;
252 $extraReturnValues['not_removed'] += $nr;
253 }
254 }
244bbdd8
CW
255 // can't pass this by reference
256 $dao = NULL;
257 return civicrm_api3_create_success(1, $params, 'GroupContact', 'create', $dao, $extraReturnValues);
6a488035 258}
11e09c59
TO
259
260/**
dc64d047
EM
261 * Update group contact status.
262 *
6a488035 263 * @deprecated - this should be part of create but need to know we aren't missing something
dc64d047 264 *
d0997921 265 * @param array $params
dc64d047 266 *
645ee340
EM
267 * @return bool
268 * @throws \API_Exception
6a488035
TO
269 */
270function civicrm_api3_group_contact_update_status($params) {
271
cf8f0fff 272 civicrm_api3_verify_mandatory($params, NULL, ['contact_id', 'group_id']);
6a488035 273
c49a2977 274 CRM_Contact_BAO_GroupContact::addContactsToGroup(
cf8f0fff 275 [$params['contact_id']],
c49a2977
CW
276 $params['group_id'],
277 CRM_Utils_Array::value('method', $params, 'API'),
278 'Added',
279 CRM_Utils_Array::value('tracking', $params)
280 );
6a488035
TO
281
282 return TRUE;
283}
284
a14e9d08 285/**
dc64d047
EM
286 * Deprecated function notices.
287 *
a14e9d08 288 * @deprecated api notice
a6c01b45 289 * @return array
16b10e64 290 * Array of deprecated actions
a14e9d08
CW
291 */
292function _civicrm_api3_group_contact_deprecation() {
cf8f0fff 293 return [
a14e9d08
CW
294 'delete' => 'GroupContact "delete" action is deprecated in favor of "create".',
295 'pending' => 'GroupContact "pending" action is deprecated in favor of "create".',
296 'update_status' => 'GroupContact "update_status" action is deprecated in favor of "create".',
cf8f0fff 297 ];
a14e9d08 298}