diff options
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.rb | 95 |
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 |