diff options
Diffstat (limited to 'app/services/snippets/count_service.rb')
-rw-r--r-- | app/services/snippets/count_service.rb | 77 |
1 files changed, 77 insertions, 0 deletions
diff --git a/app/services/snippets/count_service.rb b/app/services/snippets/count_service.rb new file mode 100644 index 00000000000..9a3d33c75cf --- /dev/null +++ b/app/services/snippets/count_service.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +# Service for calculating visible Snippet counts via one query +# for the given user or project. +# +# Authorisation level checks will be included, ensuring the correct +# counts will be returned for the given user (if any). +# +# Basic usage: +# +# user = User.find(1) +# +# Snippets::CountService.new(user, author: user).execute +# #=> { +# are_public: 1, +# are_internal: 1, +# are_private: 1, +# all: 3 +# } +# +# Counts can be scoped to a project: +# +# user = User.find(1) +# project = Project.find(1) +# +# Snippets::CountService.new(user, project: project).execute +# #=> { +# are_public: 1, +# are_internal: 1, +# are_private: 0, +# all: 2 +# } +# +# Either a project or an author *must* be supplied. +module Snippets + class CountService + def initialize(current_user, author: nil, project: nil) + if !author && !project + raise( + ArgumentError, 'Must provide either an author or a project' + ) + end + + @snippets_finder = SnippetsFinder.new(current_user, author: author, project: project) + end + + def execute + counts = snippet_counts + return {} unless counts + + counts.slice( + :are_public, + :are_private, + :are_internal, + :are_public_or_internal, + :total + ) + end + + private + + # rubocop: disable CodeReuse/ActiveRecord + def snippet_counts + @snippets_finder.execute + .reorder(nil) + .select(" + count(case when snippets.visibility_level=#{Snippet::PUBLIC} and snippets.secret is FALSE then 1 else null end) as are_public, + count(case when snippets.visibility_level=#{Snippet::INTERNAL} then 1 else null end) as are_internal, + count(case when snippets.visibility_level=#{Snippet::PRIVATE} then 1 else null end) as are_private, + count(case when visibility_level=#{Snippet::PUBLIC} OR visibility_level=#{Snippet::INTERNAL} then 1 else null end) as are_public_or_internal, + count(*) as total + ") + .first + end + # rubocop: enable CodeReuse/ActiveRecord + end +end |