Welcome to mirror list, hosted at ThFree Co, Russian Federation.

label_reference_filter.rb « references « filter « banzai « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: bf6b3e47d3b413d6c409d6c554e3768396e67169 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# frozen_string_literal: true

module Banzai
  module Filter
    module References
      # HTML filter that replaces label references with links.
      class LabelReferenceFilter < AbstractReferenceFilter
        self.reference_type = :label
        self.object_class   = Label

        def find_object(parent_object, id)
          find_labels(parent_object).find(id)
        end

        def references_in(text, pattern = Label.reference_pattern)
          labels = {}
          unescaped_html = unescape_html_entities(text).gsub(pattern) do |match|
            namespace = $~[:namespace]
            project = $~[:project]
            project_path = reference_cache.full_project_path(namespace, project)
            label = find_label_cached(project_path, $~[:label_id], $~[:label_name])

            if label
              labels[label.id] = yield match, label.id, project, namespace, $~
              "#{REFERENCE_PLACEHOLDER}#{label.id}"
            else
              match
            end
          end

          return text if labels.empty?

          escape_with_placeholders(unescaped_html, labels)
        end

        def find_label_cached(parent_ref, label_id, label_name)
          cached_call(:banzai_find_label_cached, label_name&.tr('"', '') || label_id, path: [object_class, parent_ref]) do
            find_label(parent_ref, label_id, label_name)
          end
        end

        def find_label(parent_ref, label_id, label_name)
          parent = parent_from_ref(parent_ref)
          return unless parent

          label_params = label_params(label_id, label_name)
          find_labels(parent).find_by(label_params)
        end

        def find_labels(parent)
          params = if parent.is_a?(Group)
                     { group_id: parent.id,
                       include_ancestor_groups: true,
                       only_group_labels: true }
                   else
                     { project: parent,
                       include_ancestor_groups: true }
                   end

          LabelsFinder.new(nil, params).execute(skip_authorization: true)
        end

        # 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)
          if name
            { name: name.tr('"', '') }
          else
            { id: id.to_i }
          end
        end

        def url_for_object(label, parent)
          label_url_method =
            if context[:label_url_method]
              context[:label_url_method]
            elsif parent.is_a?(Project)
              :project_issues_url
            end

          return unless label_url_method

          Gitlab::Routing.url_helpers.public_send(label_url_method, parent, label_name: label.name, only_path: context[:only_path]) # rubocop:disable GitlabSecurity/PublicSend
        end

        def object_link_text(object, matches)
          label_suffix = ''
          parent = project || group

          if project || full_path_ref?(matches)
            project_path    = reference_cache.full_project_path(matches[:namespace], matches[:project])
            parent_from_ref = from_ref_cached(project_path)
            reference       = parent_from_ref.to_human_reference(parent)

            label_suffix = " <i>in #{ERB::Util.html_escape(reference)}</i>" if reference.present?
          end

          presenter = object.present(issuable_subject: parent)
          LabelsHelper.render_colored_label(presenter, suffix: label_suffix)
        end

        def wrap_link(link, label)
          presenter = label.present(issuable_subject: project || group)
          LabelsHelper.wrap_label_html(link, small: true, label: presenter)
        end

        def full_path_ref?(matches)
          matches[:namespace] && matches[:project]
        end

        def reference_class(type, tooltip: true)
          super + ' gl-link gl-label-link'
        end

        def object_link_title(object, matches)
          presenter = object.present(issuable_subject: project || group)
          LabelsHelper.label_tooltip_title(presenter)
        end
      end
    end
  end
end

Banzai::Filter::References::LabelReferenceFilter.prepend_mod_with('Banzai::Filter::References::LabelReferenceFilter')