File: badge.rb

package info (click to toggle)
gitlab 17.6.5-19
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 629,368 kB
  • sloc: ruby: 1,915,304; javascript: 557,307; sql: 60,639; xml: 6,509; sh: 4,567; makefile: 1,239; python: 406
file content (68 lines) | stat: -rw-r--r-- 2,405 bytes parent folder | download
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
# frozen_string_literal: true

class Badge < ApplicationRecord
  include FromUnion

  # This structure sets the placeholders that the urls
  # can have. This hash also sets which action to ask when
  # the placeholder is found.
  PLACEHOLDERS = {
    'project_path' => :full_path,
    'project_title' => :title,
    'project_name' => :path,
    'project_id' => :id,
    'project_namespace' => ->(project) { project.project_namespace.to_param },
    'group_name' => ->(project) { project.group&.to_param },
    'gitlab_server' => proc { Gitlab.config.gitlab.host },
    'gitlab_pages_domain' => proc { Gitlab.config.pages.host },
    'default_branch' => :default_branch,
    'commit_sha' => ->(project) { project.commit&.sha },
    'latest_tag' => ->(project) do
      TagsFinder.new(project.repository, per_page: 1, sort: 'updated_desc').execute.first&.name if project.repository
    end
  }.freeze

  # This regex is built dynamically using the keys from the PLACEHOLDER struct.
  # So, we can easily add new placeholder just by modifying the PLACEHOLDER hash.
  # This regex will build the new PLACEHOLDER_REGEX with the new information
  PLACEHOLDERS_REGEX = /(#{PLACEHOLDERS.keys.join('|')})/

  default_scope { order_created_at_asc } # rubocop:disable Cop/DefaultScope

  scope :order_created_at_asc, -> { reorder(created_at: :asc) }

  scope :with_name, ->(name) { where(name: name) }

  validates :link_url, :image_url, addressable_url: true
  validates :type, presence: true

  def rendered_link_url(project = nil)
    build_rendered_url(link_url, project)
  end

  def rendered_image_url(project = nil)
    Gitlab::AssetProxy.proxy_url(
      build_rendered_url(image_url, project)
    )
  end

  private

  def build_rendered_url(url, project = nil)
    return url unless project

    Gitlab::StringPlaceholderReplacer.replace_string_placeholders(url, PLACEHOLDERS_REGEX) do |arg|
      replace_placeholder_action(PLACEHOLDERS[arg], project)
    end
  end

  # The action param represents the :symbol or Proc to call in order
  # to retrieve the return value from the project.
  # This method checks if it is a Proc and use the call method, and if it is
  # a symbol just send the action
  def replace_placeholder_action(action, project)
    return unless project

    action.is_a?(Proc) ? action.call(project) : project.public_send(action) # rubocop:disable GitlabSecurity/PublicSend
  end
end