X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=CRM%2FContact%2FBAO%2FGroup.php;h=aab9bc9cd9f7d7102b4d1385c8826d6ed3a8bd7e;hb=35348e87945985be63814c13b72fb4250fc1d8b8;hp=69e043be8a2c7b59d9a311d89c550f610af8608f;hpb=5c7467c59080fe560cafae9f00d790e216259127;p=civicrm-core.git diff --git a/CRM/Contact/BAO/Group.php b/CRM/Contact/BAO/Group.php index 69e043be8a..aab9bc9cd9 100644 --- a/CRM/Contact/BAO/Group.php +++ b/CRM/Contact/BAO/Group.php @@ -3,7 +3,7 @@ +--------------------------------------------------------------------+ | CiviCRM version 4.7 | +--------------------------------------------------------------------+ - | Copyright CiviCRM LLC (c) 2004-2016 | + | Copyright CiviCRM LLC (c) 2004-2017 | +--------------------------------------------------------------------+ | This file is a part of CiviCRM. | | | @@ -28,7 +28,7 @@ /** * * @package CRM - * @copyright CiviCRM LLC (c) 2004-2016 + * @copyright CiviCRM LLC (c) 2004-2017 */ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group { @@ -360,7 +360,7 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group { if (isset($params['group_type'])) { if (is_array($params['group_type'])) { $params['group_type'] = CRM_Core_DAO::VALUE_SEPARATOR . implode(CRM_Core_DAO::VALUE_SEPARATOR, - $params['group_type'] + CRM_Utils_Array::convertCheckboxFormatToArray($params['group_type']) ) . CRM_Core_DAO::VALUE_SEPARATOR; } else { @@ -900,7 +900,7 @@ class CRM_Contact_BAO_Group extends CRM_Contact_DAO_Group { $visibility = CRM_Core_SelectValues::ufVisibility(); while ($object->fetch()) { - $permission = CRM_Contact_BAO_Group::checkPermission($object->id, $object->title); + $permission = CRM_Contact_BAO_Group::checkPermission($object->id, TRUE); //@todo CRM-12209 introduced an ACL check in the whereClause function // it may be that this checking is now obsolete - or that what remains // should be removed to the whereClause (which is also accessed by getCount) @@ -1090,88 +1090,74 @@ WHERE id IN $groupIdString // Sort the groups into the correct storage by the parent // $roots represent the current leaf nodes that need to be checked for // children. $rows represent the unplaced nodes - $roots = $rows = $allGroups = array(); + // $tree contains the child nodes based on their parent_id. + $roots = array(); + $tree = array(); while ($dao->fetch()) { - $allGroups[$dao->id] = array( - 'title' => $dao->title, - 'visibility' => $dao->visibility, - 'description' => $dao->description, - ); - - if ($dao->parents == $parents) { - $roots[] = array( + if ($dao->parents) { + $parentArray = explode(',', $dao->parents); + $parent = $parentArray[0]; + $tree[$parent][] = array( 'id' => $dao->id, - 'prefix' => '', 'title' => $dao->title, + 'visibility' => $dao->visibility, + 'description' => $dao->description, ); } else { - // group can have > 1 parent so $dao->parents may be comma separated list (eg. '1,2,5'). Grab and match on 1st parent. - $parentArray = explode(',', $dao->parents); - $parent = $parentArray[0]; - $rows[] = array( + $roots[] = array( 'id' => $dao->id, - 'prefix' => '', 'title' => $dao->title, - 'parents' => $parent, + 'visibility' => $dao->visibility, + 'description' => $dao->description, ); } } $dao->free(); - // While we have nodes left to build, shift the first (alphabetically) - // node of the list, place it in our groups list and loop through the - // list of unplaced nodes to find its children. We make a copy to - // iterate through because we must modify the unplaced nodes list - // during the loop. - while (count($roots)) { - $new_roots = array(); - $current_rows = $rows; - $root = array_shift($roots); - $groups[$root['id']] = array($root['prefix'], $root['title']); - - // As you find the children, append them to the end of the new set - // of roots (maintain alphabetical ordering). Also remove the node - // from the set of unplaced nodes. - if (is_array($current_rows)) { - foreach ($current_rows as $key => $row) { - if ($row['parents'] == $root['id']) { - $new_roots[] = array( - 'id' => $row['id'], - 'prefix' => $groups[$root['id']][0] . $spacer, - 'title' => $row['title'], - ); - unset($rows[$key]); - } - } - } - //As a group, insert the new roots into the beginning of the roots - //list. This maintains the hierarchical ordering of the tags. - $roots = array_merge($new_roots, $roots); + $hierarchy = array(); + for ($i = 0; $i < count($roots); $i++) { + self::buildGroupHierarchy($hierarchy, $roots[$i], $tree, $titleOnly, $spacer, 0); } + return $hierarchy; + } - // below is the redundant looping to ensure child groups are populated in the case where user does not have - // access to parent groups ( esp. using ACL permissions and logged in user can assess only child groups ) - foreach ($rows as $value) { - $groups[$value['id']] = array($value['prefix'], $value['title']); + /** + * Build a list with groups on alphabetical order and child groups after the parent group. + * + * This is a recursive function filling the $hierarchy parameter. + * + * @param $hierarchy + * @param $group + * @param $tree + * @param $titleOnly + * @param $spacer + * @param $level + */ + private static function buildGroupHierarchy(&$hierarchy, $group, $tree, $titleOnly, $spacer, $level) { + $spaces = str_repeat($spacer, $level); + + if ($titleOnly) { + $hierarchy[$group['id']] = $spaces . $group['title']; } - // Prefix titles with the calcuated spacing to give the visual - // appearance of ordering when transformed into HTML in the form layer. Add description and visibility. - $groupsReturn = array(); - foreach ($groups as $key => $value) { - if ($titleOnly) { - $groupsReturn[$key] = $value[0] . $value[1]; - } - else { - $groupsReturn[$key] = array( - 'title' => $value[0] . $value[1], - 'description' => $allGroups[$key]['description'], - 'visibility' => $allGroups[$key]['visibility'], - ); - } + else { + $hierarchy[$group['id']] = array( + 'title' => $spaces . $group['title'], + 'description' => $group['description'], + 'visibility' => $group['visibility'], + ); } - return $groupsReturn; + // For performance reasons we use a for loop rather than a foreach. + // Metrics for performance in an installation with 2867 groups a foreach + // caused the function getGroupsHierarchy with a foreach execution takes + // around 2.2 seoonds (2,200 ms). + // Changing to a for loop execustion takes around 0.02 seconds (20 ms). + if (isset($tree[$group['id']]) && is_array($tree[$group['id']])) { + for ($i = 0; $i < count($tree[$group['id']]); $i++) { + self::buildGroupHierarchy($hierarchy, $tree[$group['id']][$i], $tree, $titleOnly, $spacer, $level + 1); + } + } } /**