summaryrefslogtreecommitdiff
path: root/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb')
-rw-r--r--lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb95
1 files changed, 95 insertions, 0 deletions
diff --git a/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
new file mode 100644
index 00000000000..40aab896212
--- /dev/null
+++ b/lib/gitlab/background_migration/user_mentions/models/concerns/isolated_mentionable.rb
@@ -0,0 +1,95 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module BackgroundMigration
+ module UserMentions
+ module Models
+ # == IsolatedMentionable concern
+ #
+ # Shortcutted for isolation version of Mentionable to be used in mentions migrations
+ #
+ module IsolatedMentionable
+ extend ::ActiveSupport::Concern
+
+ class_methods do
+ # Indicate which attributes of the Mentionable to search for GFM references.
+ def attr_mentionable(attr, options = {})
+ attr = attr.to_s
+ mentionable_attrs << [attr, options]
+ end
+ end
+
+ included do
+ # Accessor for attributes marked mentionable.
+ cattr_accessor :mentionable_attrs, instance_accessor: false do
+ []
+ end
+
+ if self < Participable
+ participant -> (user, ext) { all_references(user, extractor: ext) }
+ end
+ end
+
+ def all_references(current_user = nil, extractor: nil)
+ # Use custom extractor if it's passed in the function parameters.
+ if extractor
+ extractors[current_user] = extractor
+ else
+ extractor = extractors[current_user] ||= ::Gitlab::ReferenceExtractor.new(project, current_user)
+
+ extractor.reset_memoized_values
+ end
+
+ self.class.mentionable_attrs.each do |attr, options|
+ text = __send__(attr) # rubocop:disable GitlabSecurity/PublicSend
+ options = options.merge(
+ cache_key: [self, attr],
+ author: author,
+ skip_project_check: skip_project_check?
+ ).merge(mentionable_params)
+
+ cached_html = self.try(:updated_cached_html_for, attr.to_sym)
+ options[:rendered] = cached_html if cached_html
+
+ extractor.analyze(text, options)
+ end
+
+ extractor
+ end
+
+ def extractors
+ @extractors ||= {}
+ end
+
+ def skip_project_check?
+ false
+ end
+
+ def build_mention_values
+ refs = all_references(author)
+
+ {
+ "#{self.user_mention_model.resource_foreign_key}": user_mention_resource_id,
+ note_id: user_mention_note_id,
+ mentioned_users_ids: array_to_sql(refs.mentioned_users.pluck(:id)),
+ mentioned_projects_ids: array_to_sql(refs.mentioned_projects.pluck(:id)),
+ mentioned_groups_ids: array_to_sql(refs.mentioned_groups.pluck(:id))
+ }
+ end
+
+ def array_to_sql(ids_array)
+ return unless ids_array.present?
+
+ '{' + ids_array.join(", ") + '}'
+ end
+
+ private
+
+ def mentionable_params
+ {}
+ end
+ end
+ end
+ end
+ end
+end