INFRA-132 - phpcbf Drupal.WhiteSpace.ScopeIndent.IncorrectExact
[civicrm-core.git] / CRM / Contact / BAO / GroupNesting.php
CommitLineData
6a488035
TO
1<?php
2/*
3 +--------------------------------------------------------------------+
39de6fd5 4 | CiviCRM version 4.6 |
6a488035
TO
5 +--------------------------------------------------------------------+
6 | Copyright U.S. PIRG Education Fund (c) 2007 |
7 | Licensed to CiviCRM under the Academic Free License version 3.0. |
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 +--------------------------------------------------------------------+
d25dd0ee 27 */
6a488035
TO
28
29/**
30 *
31 * @package CRM
32 * @copyright U.S. PIRG 2007
33 * $Id$
34 *
35 */
36class CRM_Contact_BAO_GroupNesting extends CRM_Contact_DAO_GroupNesting implements Iterator {
37
38 static $_sortOrder = 'ASC';
39
40 private $_current;
41
42 private $_parentStack = array();
43
44 private $_lastParentlessGroup;
45
46 private $_styleLabels;
47
48 private $_styleIndent;
49
50 private $_alreadyStyled = FALSE;
51
52 /**
100fef9d 53 * Class constructor
6a488035 54 */
00be9182 55 public function __construct($styleLabels = FALSE, $styleIndent = "&nbsp;--&nbsp;") {
6a488035
TO
56 parent::__construct();
57 $this->_styleLabels = $styleLabels;
58 $this->_styleIndent = $styleIndent;
59 }
60
86538308
EM
61 /**
62 * @param $sortOrder
63 */
00be9182 64 public function setSortOrder($sortOrder) {
6a488035
TO
65 switch ($sortOrder) {
66 case 'ASC':
67 case 'DESC':
68 if ($sortOrder != self::$_sortOrder) {
69 self::$_sortOrder = $sortOrder;
70 $this->rewind();
71 }
72 break;
73
74 default:
75 // spit out some error, someday
76 }
77 }
78
86538308
EM
79 /**
80 * @return string
81 */
00be9182 82 public function getSortOrder() {
6a488035
TO
83 return self::$_sortOrder;
84 }
85
86538308
EM
86 /**
87 * @return int
88 */
00be9182 89 public function getCurrentNestingLevel() {
6a488035
TO
90 return count($this->_parentStack);
91 }
92
93 /**
94 * Go back to the first element in the group nesting graph,
95 * which is the first group (according to _sortOrder) that
96 * has no parent groups
97 */
00be9182 98 public function rewind() {
6a488035
TO
99 $this->_parentStack = array();
100 // calling _getNextParentlessGroup w/ no arguments
101 // makes it return the first parentless group
102 $firstGroup = $this->_getNextParentlessGroup();
103 $this->_current = $firstGroup;
104 $this->_lastParentlessGroup = $firstGroup;
105 $this->_alreadyStyled = FALSE;
106 }
107
2b37475d
CW
108 /**
109 * @return mixed
110 */
00be9182 111 public function current() {
6a488035
TO
112 if ($this->_styleLabels &&
113 $this->valid() &&
114 !$this->_alreadyStyled
115 ) {
353ffa53 116 $styledGroup = clone($this->_current);
6a488035 117 $nestingLevel = $this->getCurrentNestingLevel();
353ffa53 118 $indent = '';
6a488035
TO
119 while ($nestingLevel--) {
120 $indent .= $this->_styleIndent;
121 }
122 $styledGroup->title = $indent . $styledGroup->title;
123
124 $this->_current = &$styledGroup;
125 $this->_alreadyStyled = TRUE;
126 }
127 return $this->_current;
128 }
129
86538308
EM
130 /**
131 * @return string
132 */
00be9182 133 public function key() {
6a488035
TO
134 $group = &$this->_current;
135 $ids = array();
136 foreach ($this->_parentStack as $parentGroup) {
137 $ids[] = $parentGroup->id;
138 }
139 $key = implode('-', $ids);
140 if (strlen($key) > 0) {
141 $key .= '-';
142 }
143 $key .= $group->id;
144 return $key;
145 }
146
86538308
EM
147 /**
148 * @return CRM_Contact_BAO_Group|null
149 */
00be9182 150 public function next() {
6a488035
TO
151 $currentGroup = &$this->_current;
152 $childGroup = $this->_getNextChildGroup($currentGroup);
153 if ($childGroup) {
154 $nextGroup = &$childGroup;
155 $this->_parentStack[] = &$this->_current;
156 }
157 else {
158 $nextGroup = $this->_getNextSiblingGroup($currentGroup);
159 if (!$nextGroup) {
160 // no sibling, find an ancestor w/ a sibling
3bdca100 161 for (;;) {
6a488035
TO
162 // since we pop this array everytime, we should be
163 // reasonably safe from infinite loops, I think :)
164 $ancestor = array_pop($this->_parentStack);
165 $this->_current = &$ancestor;
166 if ($ancestor == NULL) {
167 break;
168 }
169 $nextGroup = $this->_getNextSiblingGroup($ancestor);
170 if ($nextGroup) {
171 break;
172 }
173 }
174 }
175 }
176 $this->_current = &$nextGroup;
177 $this->_alreadyStyled = FALSE;
178 return $nextGroup;
179 }
180
86538308
EM
181 /**
182 * @return bool
183 */
00be9182 184 public function valid() {
6a488035
TO
185 if ($this->_current) {
186 return TRUE;
187 }
188 else {
189 return FALSE;
190 }
191 }
192
86538308
EM
193 /**
194 * @param null $group
195 *
196 * @return CRM_Contact_BAO_Group|null
197 */
00be9182 198 public function _getNextParentlessGroup(&$group = NULL) {
6a488035 199 $lastParentlessGroup = $this->_lastParentlessGroup;
353ffa53 200 $nextGroup = new CRM_Contact_BAO_Group();
6a488035
TO
201 $nextGroup->order_by = 'title ' . self::$_sortOrder;
202 $nextGroup->find();
203 if ($group == NULL) {
204 $sawLast = TRUE;
205 }
206 else {
207 $sawLast = FALSE;
208 }
209 while ($nextGroup->fetch()) {
210 if (!self::hasParentGroups($nextGroup->id) && $sawLast) {
211 return $nextGroup;
212 }
213 elseif ($lastParentlessGroup->id == $nextGroup->id) {
214 $sawLast = TRUE;
215 }
216 }
217 return NULL;
218 }
219
86538308
EM
220 /**
221 * @param $parentGroup
222 * @param null $group
223 *
224 * @return CRM_Contact_BAO_Group|null
225 */
00be9182 226 public function _getNextChildGroup(&$parentGroup, &$group = NULL) {
6a488035
TO
227 $children = self::getChildGroupIds($parentGroup->id);
228 if (count($children) > 0) {
229 // we have child groups, so get the first one based on _sortOrder
230 $childGroup = new CRM_Contact_BAO_Group();
231 $cgQuery = "SELECT * FROM civicrm_group WHERE id IN (" . implode(',', $children) . ") ORDER BY title " . self::$_sortOrder;
232 $childGroup->query($cgQuery);
233 $currentGroup = &$this->_current;
234 if ($group == NULL) {
235 $sawLast = TRUE;
236 }
237 else {
238 $sawLast = FALSE;
239 }
240 while ($childGroup->fetch()) {
241 if ($sawLast) {
242 return $childGroup;
243 }
244 elseif ($currentGroup->id === $childGroup->id) {
245 $sawLast = TRUE;
246 }
247 }
248 }
249 return NULL;
250 }
251
86538308
EM
252 /**
253 * @param $group
254 *
255 * @return CRM_Contact_BAO_Group|null
256 */
00be9182 257 public function _getNextSiblingGroup(&$group) {
6a488035
TO
258 $parentGroup = end($this->_parentStack);
259 if ($parentGroup) {
260 $nextGroup = $this->_getNextChildGroup($parentGroup, $group);
261 return $nextGroup;
262 }
263 else {
264 /* if we get here, it could be because we're out of siblings
e70a7fc0
TO
265 * (in which case we return null) or because we're at the
266 * top level groups which do not have parents but may still
267 * have siblings, so check for that first.
268 */
6a488035
TO
269
270 $nextGroup = $this->_getNextParentlessGroup($group);
271 if ($nextGroup) {
272 $this->_lastParentlessGroup = $nextGroup;
273 return $nextGroup;
274 }
275 return NULL;
276 }
277 }
278
279 /**
280 * Adds a new child group identified by $childGroupId to the group
281 * identified by $groupId
282 *
77c5b619
TO
283 * @param int $parentID
284 * Id of the group to add the child to.
285 * @param int $childID
286 * Id of the new child group.
fd31fa4c 287 *
6a488035 288 *
c490a46a 289 * @return void
6a488035 290 */
00be9182 291 public static function add($parentID, $childID) {
6a488035
TO
292 // TODO: Add checks here to make sure invalid nests can't be created
293 $dao = new CRM_Contact_DAO_GroupNesting();
294 $query = "REPLACE INTO civicrm_group_nesting (child_group_id, parent_group_id) VALUES ($childID,$parentID);";
295 $dao->query($query);
296 }
297
298 /**
299 * Removes a child group identified by $childGroupId from the group
300 * identified by $groupId; does not delete child group, just the
301 * association between the two
302 *
77c5b619
TO
303 * @param $parentID
304 * The id of the group to remove the child from.
305 * @param $childID
306 * The id of the child group being removed.
6a488035 307 *
2b37475d 308 * @return void
6a488035 309 */
00be9182 310 public static function remove($parentID, $childID) {
6a488035
TO
311 $dao = new CRM_Contact_DAO_GroupNesting();
312 $query = "DELETE FROM civicrm_group_nesting WHERE child_group_id = $childID AND parent_group_id = $parentID";
313 $dao->query($query);
314 }
315
316 /**
317 * Removes associations where a child group is identified by $childGroupId from the group
318 * identified by $groupId; does not delete child group, just the
319 * association between the two
320 *
77c5b619
TO
321 * @param int $childID
322 * The id of the child group being removed.
6a488035 323 *
2b37475d 324 * @return void
6a488035 325 */
00be9182 326 public static function removeAllParentForChild($childID) {
6a488035
TO
327 $dao = new CRM_Contact_DAO_GroupNesting();
328 $query = "DELETE FROM civicrm_group_nesting WHERE child_group_id = $childID";
329 $dao->query($query);
330 }
331
332 /**
333 * Returns true if the association between parent and child is present,
334 * false otherwise.
335 *
77c5b619
TO
336 * @param $parentID
337 * The parent id of the association.
338 * @param $childID
339 * The child id of the association.
6a488035 340 *
3bdca100 341 * @return bool
2b37475d 342 * True if association is found, false otherwise.
6a488035 343 */
00be9182 344 public static function isParentChild($parentID, $childID) {
6a488035
TO
345 $dao = new CRM_Contact_DAO_GroupNesting();
346 $query = "SELECT id FROM civicrm_group_nesting WHERE child_group_id = $childID AND parent_group_id = $parentID";
347 $dao->query($query);
348 if ($dao->fetch()) {
349 return TRUE;
350 }
351 return FALSE;
352 }
353
354 /**
355 * Returns true if if the given groupId has 1 or more child groups,
356 * false otherwise.
357 *
77c5b619
TO
358 * @param $groupId
359 * The id of the group to check for child groups.
6a488035 360 *
3bdca100 361 * @return bool
2b37475d 362 * True if 1 or more child groups are found, false otherwise.
6a488035 363 */
00be9182 364 public static function hasChildGroups($groupId) {
6a488035
TO
365 $dao = new CRM_Contact_DAO_GroupNesting();
366 $query = "SELECT child_group_id FROM civicrm_group_nesting WHERE parent_group_id = $groupId LIMIT 1";
367 //print $query . "\n<br><br>";
368 $dao->query($query);
369 if ($dao->fetch()) {
370 return TRUE;
371 }
372 return FALSE;
373 }
374
375 /**
376 * Returns true if the given groupId has 1 or more parent groups,
377 * false otherwise.
378 *
77c5b619
TO
379 * @param $groupId
380 * The id of the group to check for parent groups.
6a488035 381 *
3bdca100 382 * @return bool
2b37475d 383 * True if 1 or more parent groups are found, false otherwise.
6a488035 384 */
00be9182 385 public static function hasParentGroups($groupId) {
6a488035
TO
386 $dao = new CRM_Contact_DAO_GroupNesting();
387 $query = "SELECT parent_group_id FROM civicrm_group_nesting WHERE child_group_id = $groupId LIMIT 1";
388 $dao->query($query);
389 if ($dao->fetch()) {
390 return TRUE;
391 }
392 return FALSE;
393 }
394
395 /**
396 * Returns true if checkGroupId is a parent of one of the groups in
397 * groupIds, false otherwise.
398 *
5a4f6742
CW
399 * @param array $groupIds
400 * of group ids (or one group id) to serve as the starting point.
77c5b619
TO
401 * @param $checkGroupId
402 * The group id to check if it is a parent of the $groupIds group(s).
6a488035 403 *
3bdca100 404 * @return bool
2b37475d 405 * True if $checkGroupId points to a group that is a parent of one of the $groupIds groups, false otherwise.
6a488035 406 */
00be9182 407 public static function isParentGroup($groupIds, $checkGroupId) {
6a488035
TO
408 if (!is_array($groupIds)) {
409 $groupIds = array($groupIds);
410 }
411 $dao = new CRM_Contact_DAO_GroupNesting();
412 $query = "SELECT parent_group_id FROM civicrm_group_nesting WHERE child_group_id IN (" . implode(',', $groupIds) . ")";
413 $dao->query($query);
414 while ($dao->fetch()) {
415 $parentGroupId = $dao->parent_group_id;
416 if ($parentGroupId == $checkGroupId) {
417 /* print "One of these: <pre>";
e70a7fc0
TO
418 print_r($groupIds);
419 print "</pre> has groupId $checkGroupId as an ancestor.<br/>"; */
6a488035
TO
420
421 return TRUE;
422 }
423 }
424 return FALSE;
425 }
426
427 /**
428 * Returns true if checkGroupId is a child of one of the groups in
429 * groupIds, false otherwise.
430 *
5a4f6742
CW
431 * @param array $groupIds
432 * of group ids (or one group id) to serve as the starting point.
77c5b619
TO
433 * @param $checkGroupId
434 * The group id to check if it is a child of the $groupIds group(s).
6a488035 435 *
3bdca100 436 * @return bool
2b37475d 437 * True if $checkGroupId points to a group that is a child of one of the $groupIds groups, false otherwise.
6a488035 438 */
00be9182 439 public static function isChildGroup($groupIds, $checkGroupId) {
6a488035
TO
440
441 if (!is_array($groupIds)) {
442 $groupIds = array($groupIds);
443 }
444 $dao = new CRM_Contact_DAO_GroupNesting();
445 $query = "SELECT child_group_id FROM civicrm_group_nesting WHERE parent_group_id IN (" . implode(',', $groupIds) . ")";
446 //print $query;
447 $dao->query($query);
448 while ($dao->fetch()) {
449 $childGroupId = $dao->child_group_id;
450 if ($childGroupId == $checkGroupId) {
451 /* print "One of these: <pre>";
e70a7fc0
TO
452 print_r($groupIds);
453 print "</pre> has groupId $checkGroupId as a descendent.<br/><br/>"; */
6a488035
TO
454
455 return TRUE;
456 }
457 }
458 return FALSE;
459 }
460
461 /**
462 * Returns true if checkGroupId is an ancestor of one of the groups in
463 * groupIds, false otherwise.
464 *
5a4f6742
CW
465 * @param array $groupIds
466 * of group ids (or one group id) to serve as the starting point.
77c5b619
TO
467 * @param $checkGroupId
468 * The group id to check if it is an ancestor of the $groupIds group(s).
6a488035 469 *
3bdca100 470 * @return bool
2b37475d 471 * True if $checkGroupId points to a group that is an ancestor of one of the $groupIds groups, false otherwise.
6a488035 472 */
00be9182 473 public static function isAncestorGroup($groupIds, $checkGroupId) {
6a488035
TO
474 if (!is_array($groupIds)) {
475 $groupIds = array($groupIds);
476 }
477 $dao = new CRM_Contact_DAO_GroupNesting();
478 $query = "SELECT parent_group_id FROM civicrm_group_nesting WHERE child_group_id IN (" . implode(',', $groupIds) . ")";
479 $dao->query($query);
480 $nextGroupIds = array();
481 $gotAtLeastOneResult = FALSE;
482 while ($dao->fetch()) {
483 $gotAtLeastOneResult = TRUE;
484 $parentGroupId = $dao->parent_group_id;
485 if ($parentGroupId == $checkGroupId) {
486 /* print "One of these: <pre>";
e70a7fc0
TO
487 print_r($groupIds);
488 print "</pre> has groupId $checkGroupId as an ancestor.<br/>"; */
6a488035
TO
489
490 return TRUE;
491 }
492 $nextGroupIds[] = $parentGroupId;
493 }
494 if ($gotAtLeastOneResult) {
495 return self::isAncestorGroup($nextGroupIds, $checkGroupId);
496 }
497 else {
498 return FALSE;
499 }
500 }
501
502 /**
503 * Returns true if checkGroupId is a descendent of one of the groups in
504 * groupIds, false otherwise.
505 *
5a4f6742
CW
506 * @param array $groupIds
507 * of group ids (or one group id) to serve as the starting point.
77c5b619
TO
508 * @param $checkGroupId
509 * The group id to check if it is a descendent of the $groupIds group(s).
6a488035 510 *
3bdca100 511 * @return bool
2b37475d 512 * True if $checkGroupId points to a group that is a descendent of one of the $groupIds groups, false otherwise.
6a488035 513 */
00be9182 514 public static function isDescendentGroup($groupIds, $checkGroupId) {
6a488035
TO
515 if (!is_array($groupIds)) {
516 $groupIds = array($groupIds);
517 }
518 $dao = new CRM_Contact_DAO_GroupNesting();
519 $query = "SELECT child_group_id FROM civicrm_group_nesting WHERE parent_group_id IN (" . implode(',', $groupIds) . ")";
520 $dao->query($query);
521 $nextGroupIds = array();
522 $gotAtLeastOneResult = FALSE;
523 while ($dao->fetch()) {
524 $gotAtLeastOneResult = TRUE;
525 $childGroupId = $dao->child_group_id;
526 if ($childGroupId == $checkGroupId) {
527 /* print "One of these: <pre>";
e70a7fc0
TO
528 print_r($groupIds);
529 print "</pre> has groupId $checkGroupId as a descendent.<br/><br/>"; */
6a488035
TO
530
531 return TRUE;
532 }
533 $nextGroupIds[] = $childGroupId;
534 }
535 if ($gotAtLeastOneResult) {
536 return self::isDescendentGroup($nextGroupIds, $checkGroupId);
537 }
538 else {
539 return FALSE;
540 }
541 }
542
543 /**
544 * Returns array of group ids of ancestor groups of the specified group.
545 *
5a4f6742 546 * @param array $groupIds
77c5b619 547 * An array of valid group ids (passed by reference).
6a488035 548 *
2a6da8d7 549 * @param bool $includeSelf
6a488035 550 *
2b37475d
CW
551 * @return array
552 * List of groupIds that represent the requested group and its ancestors@access public
6a488035 553 */
00be9182 554 public static function getAncestorGroupIds($groupIds, $includeSelf = TRUE) {
6a488035
TO
555 if (!is_array($groupIds)) {
556 $groupIds = array($groupIds);
557 }
558 $dao = new CRM_Contact_DAO_GroupNesting();
559 $query = "SELECT parent_group_id, child_group_id
560 FROM civicrm_group_nesting
561 WHERE child_group_id IN (" . implode(',', $groupIds) . ")";
562 $dao->query($query);
563 $tmpGroupIds = array();
564 $parentGroupIds = array();
565 if ($includeSelf) {
566 $parentGroupIds = $groupIds;
567 }
568 while ($dao->fetch()) {
569 // make sure we're not following any cyclical references
570 if (!array_key_exists($dao->child_group_id, $parentGroupIds) && $dao->parent_group_id != $groupIds[0]) {
571 $tmpGroupIds[] = $dao->parent_group_id;
572 }
573 }
574 if (!empty($tmpGroupIds)) {
575 $newParentGroupIds = self::getAncestorGroupIds($tmpGroupIds);
576 $parentGroupIds = array_merge($parentGroupIds, $newParentGroupIds);
577 }
578 return $parentGroupIds;
579 }
580
581 /**
582 * Returns array of ancestor groups of the specified group.
583 *
5a4f6742 584 * @param array $groupIds
77c5b619 585 * An array of valid group ids (passed by reference).
6a488035 586 *
2a6da8d7 587 * @param bool $includeSelf
2b37475d
CW
588 * @return array
589 * List of ancestor groups@access public
6a488035 590 */
00be9182 591 public static function getAncestorGroups($groupIds, $includeSelf = TRUE) {
6a488035
TO
592 $groupIds = self::getAncestorGroupIds($groupIds, $includeSelf);
593 $params['id'] = $groupIds;
594 return CRM_Contact_BAO_Group::getGroups($params);
595 }
596
597 /**
598 * Returns array of group ids of child groups of the specified group.
599 *
5a4f6742 600 * @param array $groupIds
77c5b619 601 * An array of valid group ids (passed by reference).
6a488035 602 *
2b37475d
CW
603 * @return array
604 * List of groupIds that represent the requested group and its children@access public
6a488035 605 */
00be9182 606 public static function getChildGroupIds($groupIds) {
6a488035
TO
607 if (!is_array($groupIds)) {
608 $groupIds = array($groupIds);
609 }
610 $dao = new CRM_Contact_DAO_GroupNesting();
611 $query = "SELECT child_group_id FROM civicrm_group_nesting WHERE parent_group_id IN (" . implode(',', $groupIds) . ")";
612 $dao->query($query);
613 $childGroupIds = array();
614 while ($dao->fetch()) {
615 $childGroupIds[] = $dao->child_group_id;
616 }
617 return $childGroupIds;
618 }
619
620 /**
621 * Returns array of group ids of parent groups of the specified group.
622 *
5a4f6742 623 * @param array $groupIds
77c5b619 624 * An array of valid group ids (passed by reference).
6a488035 625 *
2b37475d
CW
626 * @return array
627 * List of groupIds that represent the requested group and its parents@access public
6a488035 628 */
00be9182 629 public static function getParentGroupIds($groupIds) {
6a488035
TO
630 if (!is_array($groupIds)) {
631 $groupIds = array($groupIds);
632 }
633 $dao = new CRM_Contact_DAO_GroupNesting();
634 $query = "SELECT parent_group_id FROM civicrm_group_nesting WHERE child_group_id IN (" . implode(',', $groupIds) . ")";
635 $dao->query($query);
636 $parentGroupIds = array();
637 while ($dao->fetch()) {
638 $parentGroupIds[] = $dao->parent_group_id;
639 }
640 return $parentGroupIds;
641 }
642
643 /**
644 * Returns array of group ids of descendent groups of the specified group.
645 *
5a4f6742 646 * @param array $groupIds
77c5b619 647 * An array of valid group ids (passed by reference).
6a488035 648 *
2a6da8d7 649 * @param bool $includeSelf
2b37475d
CW
650 * @return array
651 * List of groupIds that represent the requested group and its descendents@access public
6a488035 652 */
00be9182 653 public static function getDescendentGroupIds($groupIds, $includeSelf = TRUE) {
6a488035
TO
654 if (!is_array($groupIds)) {
655 $groupIds = array($groupIds);
656 }
657 $dao = new CRM_Contact_DAO_GroupNesting();
658 $query = "SELECT child_group_id, parent_group_id FROM civicrm_group_nesting WHERE parent_group_id IN (" . implode(',', $groupIds) . ")";
659 $dao->query($query);
660 $tmpGroupIds = array();
661 $childGroupIds = array();
662 if ($includeSelf) {
663 $childGroupIds = $groupIds;
664 }
665 while ($dao->fetch()) {
666 // make sure we're not following any cyclical references
667 if (!array_key_exists($dao->parent_group_id, $childGroupIds) && $dao->child_group_id != $groupIds[0]) {
668 $tmpGroupIds[] = $dao->child_group_id;
669 }
670 }
671 if (!empty($tmpGroupIds)) {
672 $newChildGroupIds = self::getDescendentGroupIds($tmpGroupIds);
673 $childGroupIds = array_merge($childGroupIds, $newChildGroupIds);
674 }
675 return $childGroupIds;
676 }
677
678 /**
679 * Returns array of descendent groups of the specified group.
680 *
5a4f6742 681 * @param array $groupIds
2b37475d 682 * An array of valid group ids
6a488035 683 *
2a6da8d7 684 * @param bool $includeSelf
2b37475d
CW
685 * @return array
686 * List of descendent groups@access public
6a488035 687 */
00be9182 688 public static function getDescendentGroups($groupIds, $includeSelf = TRUE) {
6a488035
TO
689 $groupIds = self::getDescendentGroupIds($groupIds, $includeSelf);
690 $params['id'] = $groupIds;
691 return CRM_Contact_BAO_Group::getGroups($params);
692 }
693
694 /**
695 * Returns array of group ids of valid potential child groups of the specified group.
696 *
77c5b619
TO
697 * @param $groupId
698 * The group id to get valid potential children for.
6a488035 699 *
2b37475d
CW
700 * @return array
701 * List of groupIds that represent the valid potential children of the group@access public
6a488035 702 */
00be9182 703 public static function getPotentialChildGroupIds($groupId) {
6a488035
TO
704 $groups = CRM_Contact_BAO_Group::getGroups();
705 $potentialChildGroupIds = array();
706 foreach ($groups as $group) {
707 $potentialChildGroupId = $group->id;
708 // print "Checking if $potentialChildGroupId is a descendent/ancestor of $groupId<br/><br/>";
709 if (!self::isDescendentGroup($groupId, $potentialChildGroupId) &&
710 !self::isAncestorGroup($groupId, $potentialChildGroupId) &&
711 $potentialChildGroupId != $groupId
712 ) {
713 $potentialChildGroupIds[] = $potentialChildGroupId;
714 }
715 }
716 return $potentialChildGroupIds;
717 }
718
86538308 719 /**
100fef9d
CW
720 * @param int $contactId
721 * @param int $parentGroupId
86538308
EM
722 *
723 * @return array
724 */
00be9182 725 public static function getContainingGroups($contactId, $parentGroupId) {
6a488035
TO
726 $groups = CRM_Contact_BAO_Group::getGroups();
727 $containingGroups = array();
728 foreach ($groups as $group) {
729 if (self::isDescendentGroup($parentGroupId, $group->id)) {
730 $members = CRM_Contact_BAO_Group::getMember($group->id);
731 if ($members[$contactId]) {
732 $containingGroups[] = $group->title;
733 }
734 }
735 }
736
737 return $containingGroups;
738 }
96025800 739
6a488035 740}