diff options
author | Mike Greiling <mike@pixelcog.com> | 2017-10-24 07:52:21 +0000 |
---|---|---|
committer | Mike Greiling <mike@pixelcog.com> | 2017-10-24 07:52:21 +0000 |
commit | f7bdfe5098c9a5a3a426344ba1d7dd668212cf7e (patch) | |
tree | 5a1cb2a90b0a2b5114f6f23712b68724b3e8a7e0 /app/models/concerns/group_descendant.rb | |
parent | 9cd528aa7ac5066570cb50b909951a6c6b723935 (diff) | |
parent | e16add2267648d3d3ef1d98f9b53f67a29428791 (diff) | |
download | gitlab-ce-es-module-autosave.tar.gz |
Merge branch 'master' into 'es-module-autosave'es-module-autosave
# Conflicts:
# app/assets/javascripts/issuable_form.js
# app/assets/javascripts/notes.js
Diffstat (limited to 'app/models/concerns/group_descendant.rb')
-rw-r--r-- | app/models/concerns/group_descendant.rb | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/app/models/concerns/group_descendant.rb b/app/models/concerns/group_descendant.rb new file mode 100644 index 00000000000..01957da0bf3 --- /dev/null +++ b/app/models/concerns/group_descendant.rb @@ -0,0 +1,56 @@ +module GroupDescendant + # Returns the hierarchy of a project or group in the from of a hash upto a + # given top. + # + # > project.hierarchy + # => { parent_group => { child_group => project } } + def hierarchy(hierarchy_top = nil, preloaded = nil) + preloaded ||= ancestors_upto(hierarchy_top) + expand_hierarchy_for_child(self, self, hierarchy_top, preloaded) + end + + # Merges all hierarchies of the given groups or projects into an array of + # hashes. All ancestors need to be loaded into the given `descendants` to avoid + # queries down the line. + # + # > GroupDescendant.merge_hierarchy([project, child_group, child_group2, parent]) + # => { parent => [{ child_group => project}, child_group2] } + def self.build_hierarchy(descendants, hierarchy_top = nil) + descendants = Array.wrap(descendants).uniq + return [] if descendants.empty? + + unless descendants.all? { |hierarchy| hierarchy.is_a?(GroupDescendant) } + raise ArgumentError.new('element is not a hierarchy') + end + + all_hierarchies = descendants.map do |descendant| + descendant.hierarchy(hierarchy_top, descendants) + end + + Gitlab::Utils::MergeHash.merge(all_hierarchies) + end + + private + + def expand_hierarchy_for_child(child, hierarchy, hierarchy_top, preloaded) + parent = hierarchy_top if hierarchy_top && child.parent_id == hierarchy_top.id + parent ||= preloaded.detect { |possible_parent| possible_parent.is_a?(Group) && possible_parent.id == child.parent_id } + + if parent.nil? && !child.parent_id.nil? + raise ArgumentError.new('parent was not preloaded') + end + + if parent.nil? && hierarchy_top.present? + raise ArgumentError.new('specified top is not part of the tree') + end + + if parent && parent != hierarchy_top + expand_hierarchy_for_child(parent, + { parent => hierarchy }, + hierarchy_top, + preloaded) + else + hierarchy + end + end +end |