discourse/app/models/badge.rb

259 lines
5.5 KiB
Ruby
Raw Normal View History

require_dependency 'slug'
2014-03-05 06:52:20 -06:00
class Badge < ActiveRecord::Base
# NOTE: These badge ids are not in order! They are grouped logically.
# When picking an id, *search* for it.
BasicUser = 1
Member = 2
Regular = 3
Leader = 4
Welcome = 5
NicePost = 6
GoodPost = 7
GreatPost = 8
Autobiographer = 9
2014-07-07 02:55:25 -05:00
Editor = 10
FirstLike = 11
FirstShare = 12
FirstFlag = 13
2014-07-09 20:18:02 -05:00
FirstLink = 14
2014-07-10 23:17:01 -05:00
FirstQuote = 15
FirstMention = 40
FirstEmoji = 41
2016-04-12 13:09:59 -05:00
FirstOnebox = 42
FirstReplyByEmail = 43
2014-07-16 01:26:22 -05:00
ReadGuidelines = 16
Reader = 17
NiceTopic = 18
GoodTopic = 19
GreatTopic = 20
NiceShare = 21
GoodShare = 22
GreatShare = 23
2015-02-18 12:30:07 -06:00
OneYearAnniversary = 24
2016-03-16 12:48:14 -05:00
Promoter = 25
Campaigner = 26
Champion = 27
2016-03-16 12:48:14 -05:00
PopularLink = 28
HotLink = 29
FamousLink = 30
2016-03-16 12:48:14 -05:00
2016-03-16 12:03:17 -05:00
Appreciated = 36
Respected = 37
Admired = 31
2016-03-16 12:48:14 -05:00
OutOfLove = 33
HigherLove = 34
CrazyInLove = 35
2016-03-16 12:48:14 -05:00
ThankYou = 38
GivesBack = 32
Empathetic = 39
NewUserOfTheMonth = 44
# other consts
AutobiographerMinBioLength = 10
def self.trigger_hash
Hash[*(
Badge::Trigger.constants.map{|k|
[k.to_s.underscore, Badge::Trigger.const_get(k)]
}.flatten
)]
end
2014-07-21 21:46:31 -05:00
module Trigger
None = 0
PostAction = 1
PostRevision = 2
TrustLevelChange = 4
UserChange = 8
PostProcessed = 16 # deprecated
def self.is_none?(trigger)
[None].include? trigger
end
def self.uses_user_ids?(trigger)
[TrustLevelChange, UserChange].include? trigger
end
def self.uses_post_ids?(trigger)
[PostAction, PostRevision].include? trigger
end
end
2014-03-05 06:52:20 -06:00
belongs_to :badge_type
belongs_to :badge_grouping
has_many :user_badges, dependent: :destroy
2014-03-05 06:52:20 -06:00
validates :name, presence: true, uniqueness: true
validates :badge_type, presence: true
validates :allow_title, inclusion: [true, false]
2014-05-23 21:33:46 -05:00
validates :multiple_grant, inclusion: [true, false]
scope :enabled, ->{ where(enabled: true) }
before_create :ensure_not_system
# fields that can not be edited on system badges
def self.protected_system_fields
[
:name, :badge_type_id, :multiple_grant,
:target_posts, :show_posts, :query,
:trigger, :auto_revoke, :listable
]
end
def self.trust_level_badge_ids
(1..4).to_a
end
def self.like_badge_counts
@like_badge_counts ||= {
NicePost => 10,
GoodPost => 25,
2014-09-10 22:30:47 -05:00
GreatPost => 50,
NiceTopic => 10,
GoodTopic => 25,
GreatTopic => 50
}
end
def self.ensure_consistency!
exec_sql <<-SQL.squish
DELETE FROM user_badges
USING user_badges ub
LEFT JOIN users u ON u.id = ub.user_id
WHERE u.id IS NULL
AND user_badges.id = ub.id
SQL
exec_sql <<-SQL.squish
WITH X AS (
SELECT badge_id
, COUNT(user_id) users
FROM user_badges
GROUP BY badge_id
)
UPDATE badges
SET grant_count = X.users
FROM X
WHERE id = X.badge_id
AND grant_count <> X.users
SQL
end
def awarded_for_trust_level?
id <= 4
end
def reset_grant_count!
self.grant_count = UserBadge.where(badge_id: id).count
save!
end
2014-05-21 02:22:42 -05:00
def single_grant?
!self.multiple_grant?
end
def default_icon=(val)
unless self.image
self.icon ||= val
self.icon = val if self.icon == "fa-certificate"
end
end
2014-07-29 17:46:46 -05:00
def default_allow_title=(val)
self.allow_title ||= val
end
2014-07-17 01:10:44 -05:00
def default_badge_grouping_id=(val)
2014-07-18 00:55:42 -05:00
# allow to correct orphans
if !self.badge_grouping_id || self.badge_grouping_id < 0
self.badge_grouping_id = val
end
2014-07-17 01:10:44 -05:00
end
def display_name
key = "badges.#{i18n_name}.name"
I18n.t(key, default: self.name)
end
def long_description
key = "badges.#{i18n_name}.long_description"
I18n.t(key, default: self[:long_description] || '')
end
def long_description=(val)
self[:long_description] = val if val != long_description
val
end
def description
key = "badges.#{i18n_name}.description"
I18n.t(key, default: self[:description] || '')
end
def description=(val)
self[:description] = val if val != description
val
end
def slug
Slug.for(self.display_name, '-')
end
protected
def ensure_not_system
self.id = [Badge.maximum(:id) + 1, 100].max unless id
end
def i18n_name
self.name.downcase.tr(' ', '_')
end
2014-03-05 06:52:20 -06:00
end
# == Schema Information
#
# Table name: badges
#
2014-07-17 01:10:44 -05:00
# id :integer not null, primary key
2016-02-22 17:33:53 -06:00
# name :string not null
2014-07-17 01:10:44 -05:00
# description :text
# badge_type_id :integer not null
# grant_count :integer default(0), not null
# created_at :datetime not null
# updated_at :datetime not null
2014-07-17 01:10:44 -05:00
# allow_title :boolean default(FALSE), not null
# multiple_grant :boolean default(FALSE), not null
2016-02-22 17:33:53 -06:00
# icon :string default("fa-certificate")
2014-07-17 01:10:44 -05:00
# listable :boolean default(TRUE)
# target_posts :boolean default(FALSE)
# query :text
# enabled :boolean default(TRUE), not null
# auto_revoke :boolean default(TRUE), not null
2014-07-21 21:46:31 -05:00
# badge_grouping_id :integer default(5), not null
# trigger :integer
# show_posts :boolean default(FALSE), not null
2014-08-06 22:33:11 -05:00
# system :boolean default(FALSE), not null
# image :string(255)
2015-09-17 19:41:10 -05:00
# long_description :text
2014-03-05 06:52:20 -06:00
#
# Indexes
#
2016-02-22 17:33:53 -06:00
# index_badges_on_badge_type_id (badge_type_id)
# index_badges_on_name (name) UNIQUE
2014-03-05 06:52:20 -06:00
#