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