Merge pull request #1493 from davecivicrm/CRM-13257
[civicrm-core.git] / CRM / Contact / BAO / GroupContact.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 4.3 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2013 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26*/
27
28/**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2013
32 * $Id$
33 *
34 */
35class CRM_Contact_BAO_GroupContact extends CRM_Contact_DAO_GroupContact {
36
37 /**
38 * class constructor
39 */
40 function __construct() {
41 parent::__construct();
42 }
43
44 /**
45 * takes an associative array and creates a groupContact object
46 *
47 * the function extract all the params it needs to initialize the create a
48 * group object. the params array could contain additional unused name/value
49 * pairs
50 *
51 * @param array $params (reference ) an assoc array of name/value pairs
52 *
53 * @return object CRM_Contact_BAO_Group object
54 * @access public
55 * @static
56 */
57 static function add(&$params) {
58
59 $dataExists = self::dataExists($params);
60 if (!$dataExists) {
61 return NULL;
62 }
63
64 $groupContact = new CRM_Contact_BAO_GroupContact();
65 $groupContact->copyValues($params);
66 CRM_Contact_BAO_SubscriptionHistory::create($params);
67 $groupContact->save();
68 return $groupContact;
69 }
70
71 /**
72 * Check if there is data to create the object
73 *
74 * @param array $params (reference ) an assoc array of name/value pairs
75 *
76 * @return boolean
77 * @access public
78 * @static
79 */
80 static function dataExists(&$params) {
81 // return if no data present
82 if ($params['group_id'] == 0) {
83 return FALSE;
84 }
85
86 return TRUE;
87 }
88
89 /**
90 * Given the list of params in the params array, fetch the object
91 * and store the values in the values array
92 *
93 * @param array $params input parameters to find object
94 * @param array $values output values of the object
95 * @param array $ids the array that holds all the db ids
96 *
97 * @return array (reference) the values that could be potentially assigned to smarty
98 * @access public
99 * @static
100 */
101 static function getValues(&$params, &$values) {
102 if (empty($params)) {
103 return NULL;
104 }
105 $values['group']['data'] = &CRM_Contact_BAO_GroupContact::getContactGroup($params['contact_id'],
106 'Added',
107 3
108 );
109
110 // get the total count of groups
111 $values['group']['totalCount'] = CRM_Contact_BAO_GroupContact::getContactGroup($params['contact_id'],
112 'Added',
113 NULL,
114 TRUE
115 );
116
117 return NULL;
118 }
119
120 /**
121 * Given an array of contact ids, add all the contacts to the group
122 *
123 * @param array $contactIds (reference ) the array of contact ids to be added
124 * @param int $groupId the id of the group
125 *
126 * @return array (total, added, notAdded) count of contacts added to group
127 * @access public
128 * @static
129 */
130 static function addContactsToGroup(
131 &$contactIds,
132 $groupId,
133 $method = 'Admin',
134 $status = 'Added',
135 $tracking = NULL
136 ) {
137
138
139 CRM_Utils_Hook::pre('create', 'GroupContact', $groupId, $contactIds);
140
141 list($numContactsAdded,
142 $numContactsNotAdded
143 ) = self::bulkAddContactsToGroup($contactIds,
144 $groupId,
145 $method,
146 $status,
147 $tracking
148 );
149
150 // also reset the acl cache
151 $config = CRM_Core_Config::singleton();
152 if (!$config->doNotResetCache) {
153 CRM_ACL_BAO_Cache::resetCache();
154 }
155
156 // reset the group contact cache for all group(s)
157 // if this group is being used as a smart group
158 CRM_Contact_BAO_GroupContactCache::remove();
159
160 CRM_Utils_Hook::post('create', 'GroupContact', $groupId, $contactIds);
161
162 return array(count($contactIds), $numContactsAdded, $numContactsNotAdded);
163 }
164
165 /**
166 * Given an array of contact ids, remove all the contacts from the group
167 *
168 * @param array $contactIds (reference ) the array of contact ids to be removed
169 * @param int $groupId the id of the group
170 *
171 * @return array (total, removed, notRemoved) count of contacts removed to group
172 * @access public
173 * @static
174 */
175 static function removeContactsFromGroup(
176 &$contactIds,
177 $groupId,
178 $method = 'Admin',
179 $status = 'Removed',
180 $tracking = NULL
181 ) {
182 if (!is_array($contactIds)) {
183 return array(0, 0, 0);
184 }
185
186 if ($status == 'Removed' || $status == 'Deleted') {
187 $op = 'delete';
188 }
189 else {
190 $op = 'edit';
191 }
192
193 CRM_Utils_Hook::pre($op, 'GroupContact', $groupId, $contactIds);
194
195 $date = date('YmdHis');
196 $numContactsRemoved = 0;
197 $numContactsNotRemoved = 0;
198
199 $group = new CRM_Contact_DAO_Group();
200 $group->id = $groupId;
201 $group->find(TRUE);
202
203 foreach ($contactIds as $contactId) {
204 if ($status == 'Deleted') {
205 $query = "DELETE FROM civicrm_group_contact WHERE contact_id=$contactId AND group_id=$groupId";
206 $dao = CRM_Core_DAO::executeQuery($query);
207 $historyParams = array(
208 'group_id' => $groupId,
209 'contact_id' => $contactId,
210 'status' => $status,
211 'method' => $method,
212 'date' => $date,
213 'tracking' => $tracking,
214 );
215 CRM_Contact_BAO_SubscriptionHistory::create($historyParams);
216 }
217 else {
218 $groupContact = new CRM_Contact_DAO_GroupContact();
219 $groupContact->group_id = $groupId;
220 $groupContact->contact_id = $contactId;
221 // check if the selected contact id already a member, or if this is
222 // an opt-out of a smart group.
223 // if not a member remove to groupContact else keep the count of contacts that are not removed
224 if ($groupContact->find(TRUE) || $group->saved_search_id) {
225 // remove the contact from the group
226 $numContactsRemoved++;
227 }
228 else {
229 $numContactsNotRemoved++;
230 }
231
232 //now we grant the negative membership to contact if not member. CRM-3711
233 $historyParams = array(
234 'group_id' => $groupId,
235 'contact_id' => $contactId,
236 'status' => $status,
237 'method' => $method,
238 'date' => $date,
239 'tracking' => $tracking,
240 );
241 CRM_Contact_BAO_SubscriptionHistory::create($historyParams);
242 $groupContact->status = $status;
243 $groupContact->save();
244 }
245 }
246
247 // also reset the acl cache
248 $config = CRM_Core_Config::singleton();
249 if (!$config->doNotResetCache) {
250 CRM_ACL_BAO_Cache::resetCache();
251 }
252
253 // reset the group contact cache for all group(s)
254 // if this group is being used as a smart group
255 CRM_Contact_BAO_GroupContactCache::remove();
256
257 CRM_Utils_Hook::post($op, 'GroupContact', $groupId, $contactIds);
258
259 return array(count($contactIds), $numContactsRemoved, $numContactsNotRemoved);
260 }
261
262 /**
263 * Function to get list of all the groups and groups for a contact
264 *
265 * @param int $contactId contact id
266 *
267 * @access public
268 *
269 * @return array $values this array has key-> group id and value group title
270 * @static
271 */
272 static function getGroupList($contactId = 0, $visibility = FALSE) {
273 $group = new CRM_Contact_DAO_Group();
274
275 $select = $from = $where = '';
276
277 $select = 'SELECT DISTINCT civicrm_group.id, civicrm_group.title ';
278 $from = ' FROM civicrm_group ';
279 $where = " WHERE civicrm_group.is_active = 1 ";
280 if ($contactId) {
281 $from .= ' , civicrm_group_contact ';
282 $where .= " AND civicrm_group.id = civicrm_group_contact.group_id
283 AND civicrm_group_contact.contact_id = " . CRM_Utils_Type::escape($contactId, 'Integer');
284 }
285
286 if ($visibility) {
287 $where .= " AND civicrm_group.visibility != 'User and User Admin Only'";
288 }
289
290 $orderby = " ORDER BY civicrm_group.name";
291 $sql = $select . $from . $where . $orderby;
292
293 $group->query($sql);
294
295 $values = array();
296 while ($group->fetch()) {
297 $values[$group->id] = $group->title;
298 }
299
300 return $values;
301 }
302
303 /**
304 * Function to get the list of groups for contact based on status of group membership
305 *
306 * @param int $contactId contact id
307 * @param string $status state of membership
308 * @param int $numGroupContact number of groups for a contact that should be shown
309 * @param boolean $count true if we are interested only in the count
310 * @param boolean $ignorePermission true if we should ignore permissions for the current user
311 * useful in profile where permissions are limited for the user. If left
312 * at false only groups viewable by the current user are returned
313 * @param boolean $onlyPublicGroups true if we want to hide system groups
314 *
315 * @return array (reference )|int $values the relevant data object values for the contact or
316 * the total count when $count is true
317 *
318 * $access public
319 */
320 static function &getContactGroup(
321 $contactId,
322 $status = NULL,
323 $numGroupContact = NULL,
324 $count = FALSE,
325 $ignorePermission = FALSE,
326 $onlyPublicGroups = FALSE,
327 $excludeHidden = TRUE
328 ) {
329 if ($count) {
330 $select = 'SELECT count(DISTINCT civicrm_group_contact.id)';
331 }
332 else {
333 $select = 'SELECT
334 civicrm_group_contact.id as civicrm_group_contact_id,
335 civicrm_group.title as group_title,
336 civicrm_group.visibility as visibility,
337 civicrm_group_contact.status as status,
338 civicrm_group.id as group_id,
339 civicrm_group.is_hidden as is_hidden,
340 civicrm_subscription_history.date as date,
341 civicrm_subscription_history.method as method';
342 }
343
344 $where = " WHERE contact_a.id = %1 AND civicrm_group.is_active = 1 ";
345
346 if ($excludeHidden) {
347 $where .= " AND civicrm_group.is_hidden = 0 ";
348 }
349
350 $params = array(1 => array($contactId, 'Integer'));
351 if (!empty($status)) {
352 $where .= ' AND civicrm_group_contact.status = %2';
353 $params[2] = array($status, 'String');
354 }
355 $tables = array(
356 'civicrm_group_contact' => 1,
357 'civicrm_group' => 1,
358 'civicrm_subscription_history' => 1,
359 );
360 $whereTables = array();
361 if ($ignorePermission) {
362 $permission = ' ( 1 ) ';
363 }
364 else {
365 $permission = CRM_Core_Permission::getPermissionedStaticGroupClause(CRM_Core_Permission::VIEW, $tables, $whereTables);
366 }
367
368 $from = CRM_Contact_BAO_Query::fromClause($tables);
369
370 $where .= " AND $permission ";
371
372 if ($onlyPublicGroups) {
373 $where .= " AND civicrm_group.visibility != 'User and User Admin Only' ";
374 }
375
376 $order = $limit = '';
377 if (!$count) {
378 $order = ' ORDER BY civicrm_group.title, civicrm_subscription_history.date ASC';
379
380 if ($numGroupContact) {
381 $limit = " LIMIT 0, $numGroupContact";
382 }
383 }
384
385 $sql = $select . $from . $where . $order . $limit;
386
387 if ($count) {
388 $result = CRM_Core_DAO::singleValueQuery($sql, $params);
389 return $result;
390 }
391 else {
392 $dao = CRM_Core_DAO::executeQuery($sql, $params);
393 $values = array();
394 while ($dao->fetch()) {
395 $id = $dao->civicrm_group_contact_id;
396 $values[$id]['id'] = $id;
397 $values[$id]['group_id'] = $dao->group_id;
398 $values[$id]['title'] = $dao->group_title;
399 $values[$id]['visibility'] = $dao->visibility;
400 $values[$id]['is_hidden'] = $dao->is_hidden;
401 switch ($dao->status) {
402 case 'Added':
403 $prefix = 'in_';
404 break;
405
406 case 'Removed':
407 $prefix = 'out_';
408 break;
409
410 default:
411 $prefix = 'pending_';
412 }
413 $values[$id][$prefix . 'date'] = $dao->date;
414 $values[$id][$prefix . 'method'] = $dao->method;
415 if ($status == 'Removed') {
416 $query = "SELECT `date` as `date_added` FROM civicrm_subscription_history WHERE id = (SELECT max(id) FROM civicrm_subscription_history WHERE contact_id = %1 AND status = \"Added\" AND group_id = $dao->group_id )";
417 $dateDAO = CRM_Core_DAO::executeQuery($query, $params);
418 if ($dateDAO->fetch()) {
419 $values[$id]['date_added'] = $dateDAO->date_added;
420 }
421 }
422 }
423 return $values;
424 }
425 }
426
427 /**
428 * Returns membership details of a contact for a group
429 *
430 * @param int $contactId id of the contact
431 * @param int $groupID Id of a perticuler group
432 * @param string $method If we want the subscription history details for a specific method
433 *
434 * @return object of group contact
435 * @access public
436 * @static
437 */
438 function &getMembershipDetail($contactId, $groupID, $method = 'Email') {
439 $leftJoin = $where = $orderBy = null;
440
441 if ($method) {
442 $leftJoin =
443 "LEFT JOIN civicrm_subscription_history ON (civicrm_group_contact.contact_id = civicrm_subscription_history.contact_id)";
444 $where = "AND civicrm_subscription_history.method ='Email'";
445 $orderBy = "ORDER BY civicrm_subscription_history.id DESC";
446 }
447 $query = "
448SELECT *
449 FROM civicrm_group_contact
450 $leftJoin
451 WHERE civicrm_group_contact.contact_id = %1
452 AND civicrm_group_contact.group_id = %2
453 $where
454 $orderBy
455";
456
457 $params = array(
458 1 => array($contactId, 'Integer'),
459 2 => array($groupID, 'Integer'),
460 );
461 $dao = CRM_Core_DAO::executeQuery($query, $params);
462 $dao->fetch();
463 return $dao;
464 }
465
466 /**
467 * Method to update the Status of Group member form 'Pending' to 'Added'
468 *
469 * @param int $contactId id of the contact
470 *
471 * @param int $groupID Id of a perticuler group
472 *
473 * @param mixed $tracking tracking information for history
474 *
475 * @return null If success
476 * @access public
477 * @static
478 */
479 static function updateGroupMembershipStatus($contactId, $groupID, $method = 'Email', $tracking = NULL) {
480 if (!isset($contactId) && !isset($groupID)) {
481 return CRM_Core_Error::fatal("$contactId or $groupID should not empty");
482 }
483
484 $query = "
485UPDATE civicrm_group_contact
486 SET civicrm_group_contact.status = 'Added'
487 WHERE civicrm_group_contact.contact_id = %1
488 AND civicrm_group_contact.group_id = %2";
489 $params = array(
490 1 => array($contactId, 'Integer'),
491 2 => array($groupID, 'Integer'),
492 );
493
494 $dao = CRM_Core_DAO::executeQuery($query, $params);
495
496 $params = array(
497 'contact_id' => $contactId,
498 'group_id' => $groupID,
499 'status' => 'Added',
500 'method' => $method,
501 'tracking' => $tracking,
502 );
503
504 CRM_Contact_BAO_SubscriptionHistory::create($params);
505 return NULL;
506 }
507
508 /**
509 * Method to get Group Id
510 *
511 * @param int $groupContactID Id of a perticuler group
512 *
513 *
514 * @return groupID
515 * @access public
516 * @static
517 */
518 static function getGroupId($groupContactID) {
519 $dao = new CRM_Contact_DAO_GroupContact();
520 $dao->id = $groupContactID;
521 $dao->find(TRUE);
522 return $dao->group_id;
523 }
524
525 /**
526 * takes an associative array and creates / removes
527 * contacts from the groups
528 *
529 *
530 * @param array $params (reference ) an assoc array of name/value pairs
531 * @param array $contactId contact id
532 *
533 * @return none
534 * @access public
535 * @static
536 */
537 static function create(&$params, $contactId, $visibility = FALSE, $method = 'Admin') {
538 $contactIds = array();
539 $contactIds[] = $contactId;
540
541 //if $visibility is true we are coming in via profile mean $method = 'Web'
542 $ignorePermission = FALSE;
543 if ($visibility) {
544 $ignorePermission = TRUE;
545 }
546
547 if ($contactId) {
548 $contactGroupList = &CRM_Contact_BAO_GroupContact::getContactGroup($contactId, 'Added',
549 NULL, FALSE, $ignorePermission
550 );
551 if (is_array($contactGroupList)) {
552 foreach ($contactGroupList as $key) {
553 $groupId = $key['group_id'];
554 $contactGroup[$groupId] = $groupId;
555 }
556 }
557 }
558
559 // get the list of all the groups
560 $allGroup = CRM_Contact_BAO_GroupContact::getGroupList(0, $visibility);
561
562 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
563 if (!is_array($params)) {
564 $params = array();
565 }
566
567 // this fix is done to prevent warning generated by array_key_exits incase of empty array is given as input
568 if (!isset($contactGroup) || !is_array($contactGroup)) {
569 $contactGroup = array();
570 }
571
572 // check which values has to be add/remove contact from group
573 foreach ($allGroup as $key => $varValue) {
574 if (CRM_Utils_Array::value($key, $params) && !array_key_exists($key, $contactGroup)) {
575 // add contact to group
576 CRM_Contact_BAO_GroupContact::addContactsToGroup($contactIds, $key, $method);
577 }
578 elseif (!CRM_Utils_Array::value($key, $params) && array_key_exists($key, $contactGroup)) {
579 // remove contact from group
580 CRM_Contact_BAO_GroupContact::removeContactsFromGroup($contactIds, $key, $method);
581 }
582 }
583 }
584
585 static function isContactInGroup($contactID, $groupID) {
586 if (!CRM_Utils_Rule::positiveInteger($contactID) ||
587 !CRM_Utils_Rule::positiveInteger($groupID)
588 ) {
589 return FALSE;
590 }
591
592 $params = array(
593 array('group', 'IN', array($groupID => 1), 0, 0),
594 array('contact_id', '=', $contactID, 0, 0),
595 );
596 list($contacts, $_) = CRM_Contact_BAO_Query::apiQuery($params, array('contact_id'));
597
598 if (!empty($contacts)) {
599 return TRUE;
600 }
601 return FALSE;
602 }
603
604 /**
605 * Function merges the groups from otherContactID to mainContactID
606 * along with subscription history
607 *
608 * @param int $mainContactId contact id of main contact record.
609 * @param int $otherContactId contact id of record which is going to merge.
610 *
611 * @see CRM_Dedupe_Merger::cpTables()
612 *
613 * TODO: use the 3rd $sqls param to append sql statements rather than executing them here
614 *
615 * @return void.
616 * @static
617 */
618 static function mergeGroupContact($mainContactId, $otherContactId) {
619 $params = array(1 => array($mainContactId, 'Integer'),
620 2 => array($otherContactId, 'Integer'),
621 );
622
623 // find all groups that are in otherContactID but not in mainContactID, copy them over
624 $sql = "
625SELECT cOther.group_id
626FROM civicrm_group_contact cOther
627LEFT JOIN civicrm_group_contact cMain ON cOther.group_id = cMain.group_id AND cMain.contact_id = %1
628WHERE cOther.contact_id = %2
629AND cMain.contact_id IS NULL
630";
631 $dao = CRM_Core_DAO::executeQuery($sql, $params);
632
633 $otherGroupIDs = array();
634 while ($dao->fetch()) {
635 $otherGroupIDs[] = $dao->group_id;
636 }
637
638 if (!empty($otherGroupIDs)) {
639 $otherGroupIDString = implode(',', $otherGroupIDs);
640
641 $sql = "
642UPDATE civicrm_group_contact
643SET contact_id = %1
644WHERE contact_id = %2
645AND group_id IN ( $otherGroupIDString )
646";
647 CRM_Core_DAO::executeQuery($sql, $params);
648
649 $sql = "
650UPDATE civicrm_subscription_history
651SET contact_id = %1
652WHERE contact_id = %2
653AND group_id IN ( $otherGroupIDString )
654";
655 CRM_Core_DAO::executeQuery($sql, $params);
656 }
657
658 $sql = "
659SELECT cOther.group_id as group_id,
660 cOther.status as group_status
661FROM civicrm_group_contact cMain
662INNER JOIN civicrm_group_contact cOther ON cMain.group_id = cOther.group_id
663WHERE cMain.contact_id = %1
664AND cOther.contact_id = %2
665";
666 $dao = CRM_Core_DAO::executeQuery($sql, $params);
667
668 $groupIDs = array();
669 while ($dao->fetch()) {
670 // only copy it over if it has added status and migrate the history
671 if ($dao->group_status == 'Added') {
672 $groupIDs[] = $dao->group_id;
673 }
674 }
675
676 if (!empty($groupIDs)) {
677 $groupIDString = implode(',', $groupIDs);
678
679 $sql = "
680UPDATE civicrm_group_contact
681SET status = 'Added'
682WHERE contact_id = %1
683AND group_id IN ( $groupIDString )
684";
685 CRM_Core_DAO::executeQuery($sql, $params);
686
687 $sql = "
688UPDATE civicrm_subscription_history
689SET contact_id = %1
690WHERE contact_id = %2
691AND group_id IN ( $groupIDString )
692";
693 CRM_Core_DAO::executeQuery($sql, $params);
694 }
695
696 // delete all the other group contacts
697 $sql = "
698 DELETE
699 FROM civicrm_group_contact
700 WHERE contact_id = %2
701 ";
702 CRM_Core_DAO::executeQuery($sql, $params);
703
704 $sql = "
705 DELETE
706 FROM civicrm_subscription_history
707 WHERE contact_id = %2
708 ";
709 CRM_Core_DAO::executeQuery($sql, $params);
710 }
711
712 /**
713 * Given an array of contact ids, add all the contacts to the group
714 *
715 * @param array $contactIds (reference ) the array of contact ids to be added
716 * @param int $groupId the id of the group
717 *
718 * @return array (total, added, notAdded) count of contacts added to group
719 * @access public
720 * @static
721 */
722 static function bulkAddContactsToGroup(
723 $contactIDs,
724 $groupID,
725 $method = 'Admin',
726 $status = 'Added',
727 $tracking = NULL
728 ) {
729
730 $numContactsAdded = 0;
731 $numContactsNotAdded = 0;
732
733 $contactGroupSQL = "
734REPLACE INTO civicrm_group_contact ( group_id, contact_id, status )
735VALUES
736";
737 $subscriptioHistorySQL = "
738INSERT INTO civicrm_subscription_history( group_id, contact_id, date, method, status, tracking )
739VALUES
740";
741
742 $date = date('YmdHis');
743
744 // to avoid long strings, lets do BULK_INSERT_HIGH_COUNT values at a time
745 while (!empty($contactIDs)) {
746 $input = array_splice($contactIDs, 0, CRM_Core_DAO::BULK_INSERT_HIGH_COUNT);
747 $contactStr = implode(',', $input);
748
749 // lets check their current status
750 $sql = "
751SELECT GROUP_CONCAT(contact_id) as contactStr
752FROM civicrm_group_contact
753WHERE group_id = %1
754AND status = %2
755AND contact_id IN ( $contactStr )
756";
757 $params = array(1 => array($groupID, 'Integer'),
758 2 => array($status, 'String'),
759 );
760
761 $presentIDs = array();
762 $dao = CRM_Core_DAO::executeQuery($sql, $params);
763 if ($dao->fetch()) {
764 $presentIDs = explode(',', $dao->contactStr);
765 $presentIDs = array_flip($presentIDs);
766 }
767
768 $gcValues = $shValues = array();
769 foreach ($input as $cid) {
770 if (isset($presentIDs[$cid])) {
771 $numContactsNotAdded++;
772 continue;
773 }
774
775 $gcValues[] = "( $groupID, $cid, '$status' )";
776 $shValues[] = "( $groupID, $cid, '$date', '$method', '$status', '$tracking' )";
777 $numContactsAdded++;
778 }
779
780 if (!empty($gcValues)) {
781 $cgSQL = $contactGroupSQL . implode(",\n", $gcValues);
782 CRM_Core_DAO::executeQuery($cgSQL);
783
784 $shSQL = $subscriptioHistorySQL . implode(",\n", $shValues);
785 CRM_Core_DAO::executeQuery($shSQL);
786 }
787 }
788
789 return array($numContactsAdded, $numContactsNotAdded);
790 }
791}
792