Read about our upcoming Code of Conduct on this issue

label_reference_filter.rb 2.71 KB
Newer Older
1
2
module Banzai
  module Filter
3
    # HTML filter that replaces label references with links.
4
    class LabelReferenceFilter < AbstractReferenceFilter
5
6
      self.reference_type = :label

7
8
      def self.object_class
        Label
Robert Speicher's avatar
Robert Speicher committed
9
10
      end

11
      def find_object(project, id)
12
        find_labels(project).find(id)
13
14
      end

15
      def self.references_in(text, pattern = Label.reference_pattern)
16
        unescape_html_entities(text).gsub(pattern) do |match|
17
          yield match, $~[:label_id].to_i, $~[:label_name], $~[:project], $~[:namespace], $~
18
        end
Robert Speicher's avatar
Robert Speicher committed
19
20
      end

21
      def references_in(text, pattern = Label.reference_pattern)
22
        unescape_html_entities(text).gsub(pattern) do |match|
23
24
25
          namespace, project = $~[:namespace], $~[:project]
          project_path = full_project_path(namespace, project)
          label = find_label(project_path, $~[:label_id], $~[:label_name])
26

27
          if label
28
            yield match, label.id, project, namespace, $~
Robert Speicher's avatar
Robert Speicher committed
29
30
31
32
33
34
          else
            match
          end
        end
      end

35
36
37
      def find_label(project_ref, label_id, label_name)
        project = project_from_ref(project_ref)
        return unless project
Robert Speicher's avatar
Robert Speicher committed
38

39
        label_params = label_params(label_id, label_name)
40
41
42
43
        find_labels(project).find_by(label_params)
      end

      def find_labels(project)
44
        LabelsFinder.new(nil, project_id: project.id).execute(skip_authorization: true)
Robert Speicher's avatar
Robert Speicher committed
45
46
      end

47
48
49
50
51
52
53
54
      # Parameters to pass to `Label.find_by` based on the given arguments
      #
      # id   - Integer ID to pass. If present, returns {id: id}
      # name - String name to pass. If `id` is absent, finds by name without
      #        surrounding quotes.
      #
      # Returns a Hash.
      def label_params(id, name)
55
        if name
56
          { name: name.tr('"', '') }
57
        else
58
59
60
61
62
63
64
65
66
67
68
          { id: id.to_i }
        end
      end

      def url_for_object(label, project)
        h = Gitlab::Routing.url_helpers
        h.namespace_project_issues_url(project.namespace, project, label_name: label.name,
                                                                   only_path:  context[:only_path])
      end

      def object_link_text(object, matches)
69
70
71
72
        project_path     = full_project_path(matches[:namespace], matches[:project])
        project_from_ref = project_from_ref_cached(project_path)
        reference        = project_from_ref.to_human_reference(project)
        label_suffix     = " <i>in #{reference}</i>" if reference.present?
73

74
        LabelsHelper.render_colored_label(object, label_suffix)
75
76
      end

77
      def unescape_html_entities(text)
78
        CGI.unescapeHTML(text.to_s)
79
      end
80
81
82
83
84

      def object_link_title(object)
        # use title of wrapped element instead
        nil
      end
Robert Speicher's avatar
Robert Speicher committed
85
86
87
    end
  end
end