diff --git a/app/models/concerns/mentionable.rb b/app/models/concerns/mentionable.rb index 7ad8d5b7da7..9339ecc4bce 100644 --- a/app/models/concerns/mentionable.rb +++ b/app/models/concerns/mentionable.rb @@ -47,19 +47,19 @@ module Mentionable SystemNoteService.cross_reference_exists?(target, local_reference) end - def mentioned_users(current_user = nil) + def mentioned_users(current_user = nil, load_lazy_references: true) return [] if mentionable_text.blank? - ext = Gitlab::ReferenceExtractor.new(self.project, current_user) + ext = Gitlab::ReferenceExtractor.new(self.project, current_user, load_lazy_references: load_lazy_references) ext.analyze(mentionable_text) ext.users.uniq end # Extract GFM references to other Mentionables from this Mentionable. Always excludes its #local_reference. - def references(p = project, current_user = self.author, text = mentionable_text) + def references(p = project, current_user = self.author, text = mentionable_text, load_lazy_references: true) return [] if text.blank? - ext = Gitlab::ReferenceExtractor.new(p, current_user) + ext = Gitlab::ReferenceExtractor.new(p, current_user, load_lazy_references: load_lazy_references) ext.analyze(text) (ext.issues + ext.merge_requests + ext.commits).uniq - [local_reference] end diff --git a/app/models/concerns/participable.rb b/app/models/concerns/participable.rb index 7c9597333dd..7a2bea567df 100644 --- a/app/models/concerns/participable.rb +++ b/app/models/concerns/participable.rb @@ -27,7 +27,7 @@ module Participable module ClassMethods def participant(*attrs) - participant_attrs.concat(attrs.map(&:to_s)) + participant_attrs.concat(attrs) end def participant_attrs @@ -37,13 +37,12 @@ module Participable # Be aware that this method makes a lot of sql queries. # Save result into variable if you are going to reuse it inside same request - def participants(current_user = self.author, project = self.project) + def participants(current_user = self.author, project = self.project, load_lazy_references: true) participants = self.class.participant_attrs.flat_map do |attr| meth = method(attr) - value = - if meth.arity == 1 || meth.arity == -1 - meth.call(current_user) + if attr == :mentioned_users + meth.call(current_user, load_lazy_references: false) else meth.call end @@ -51,9 +50,13 @@ module Participable participants_for(value, current_user, project) end.compact.uniq - if project - participants.select! do |user| - user.can?(:read_project, project) + if load_lazy_references + participants = Gitlab::Markdown::ReferenceFilter::LazyReference.load(participants).uniq + + if project + participants.select! do |user| + user.can?(:read_project, project) + end end end @@ -64,12 +67,12 @@ module Participable def participants_for(value, current_user = nil, project = nil) case value - when User + when User, Gitlab::Markdown::ReferenceFilter::LazyReference [value] when Enumerable, ActiveRecord::Relation value.flat_map { |v| participants_for(v, current_user, project) } when Participable - value.participants(current_user, project) + value.participants(current_user, project, load_lazy_references: false) end end end diff --git a/lib/gitlab/reference_extractor.rb b/lib/gitlab/reference_extractor.rb index d6b739d7b9a..895a23ddcc8 100644 --- a/lib/gitlab/reference_extractor.rb +++ b/lib/gitlab/reference_extractor.rb @@ -3,17 +3,17 @@ require 'gitlab/markdown' module Gitlab # Extract possible GFM references from an arbitrary String for further processing. class ReferenceExtractor - attr_accessor :project, :current_user + attr_accessor :project, :current_user, :load_lazy_references - def initialize(project, current_user = nil) + def initialize(project, current_user = nil, load_lazy_references: true) @project = project @current_user = current_user + @load_lazy_references = load_lazy_references end - def analyze(texts) + def analyze(text) references.clear - texts = Array(texts) - @texts = texts.map { |text| Gitlab::Markdown.render_without_gfm(text) } + @text = Gitlab::Markdown.render_without_gfm(text) end %i(user label issue merge_request snippet commit commit_range).each do |type| @@ -29,7 +29,7 @@ module Gitlab type = type.to_sym return references[type] if references.has_key?(type) - references[type] = pipeline_result(type).uniq + references[type] = pipeline_result(type) end end @@ -53,14 +53,15 @@ module Gitlab } pipeline = HTML::Pipeline.new([filter, Gitlab::Markdown::ReferenceGathererFilter], context) + result = pipeline.call(@text) - values = @texts.flat_map do |text| - result = pipeline.call(text) + values = result[:references][filter_type].uniq - result[:references][filter_type] + if @load_lazy_references + values = Gitlab::Markdown::ReferenceFilter::LazyReference.load(values).uniq end - Gitlab::Markdown::ReferenceFilter::LazyReference.load(values) + values end end end