From c419c26f560b7f2a2cbd08080e4e3a892c7bc43e Mon Sep 17 00:00:00 2001 From: Arpit Jalan Date: Sat, 17 Feb 2018 10:40:30 +0530 Subject: [PATCH] FEATURE: new site setting 'max_emojis_in_title' --- app/models/topic.rb | 1 + config/locales/server.en.yml | 2 + config/site_settings.yml | 1 + lib/validators/max_emojis_validator.rb | 11 ++++ .../validators/max_emojis_validator_spec.rb | 50 +++++++++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 lib/validators/max_emojis_validator.rb create mode 100644 spec/components/validators/max_emojis_validator_spec.rb diff --git a/app/models/topic.rb b/app/models/topic.rb index 3b3c74b956a..ac6af153922 100644 --- a/app/models/topic.rb +++ b/app/models/topic.rb @@ -84,6 +84,7 @@ class Topic < ActiveRecord::Base topic_title_length: true, censored_words: true, quality_title: { unless: :private_message? }, + max_emojis: true, unique_among: { unless: Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) }, message: :has_already_been_used, allow_blank: true, diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index 2c8986e6e4a..96bdd775b22 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -114,6 +114,7 @@ en: not_an_integer: must be an integer odd: must be odd record_invalid: ! 'Validation failed: %{errors}' + max_emojis: "can't have more than %{max_emojis_count} emoji" restrict_dependent_destroy: one: "Cannot delete record because a dependent %{record} exists" many: "Cannot delete record because dependent %{record} exist" @@ -984,6 +985,7 @@ en: min_topic_title_length: "Minimum allowed topic title length in characters" max_topic_title_length: "Maximum allowed topic title length in characters" min_personal_message_title_length: "Minimum allowed title length for a message in characters" + max_emojis_in_title: "Maximum allowed emojis in topic title" min_search_term_length: "Minimum valid search term length in characters" search_tokenize_chinese_japanese_korean: "Force search to tokenize Chinese/Japanese/Korean even on non CJK sites" search_prefer_recent_posts: "If searching your large forum is slow, this option tries an index of more recent posts first" diff --git a/config/site_settings.yml b/config/site_settings.yml index 2550cfaeb7d..c3bff313e51 100644 --- a/config/site_settings.yml +++ b/config/site_settings.yml @@ -502,6 +502,7 @@ posting: client: true default: 2 min: 1 + max_emojis_in_title: 1 allow_uncategorized_topics: client: true default: true diff --git a/lib/validators/max_emojis_validator.rb b/lib/validators/max_emojis_validator.rb new file mode 100644 index 00000000000..f208f66b1e0 --- /dev/null +++ b/lib/validators/max_emojis_validator.rb @@ -0,0 +1,11 @@ +class MaxEmojisValidator < ActiveModel::EachValidator + + def validate_each(record, attribute, value) + if Emoji.unicode_unescape(value).scan(/:([\w\-+]*(?::t\d)?):/).size > SiteSetting.max_emojis_in_title + record.errors.add( + attribute, :max_emojis, + max_emojis_count: SiteSetting.max_emojis_in_title + ) + end + end +end diff --git a/spec/components/validators/max_emojis_validator_spec.rb b/spec/components/validators/max_emojis_validator_spec.rb new file mode 100644 index 00000000000..a268e707e26 --- /dev/null +++ b/spec/components/validators/max_emojis_validator_spec.rb @@ -0,0 +1,50 @@ +# encoding: UTF-8 + +require 'rails_helper' +require 'validators/max_emojis_validator' + +describe MaxEmojisValidator do + + # simulate Rails behavior (singleton) + def validate + @validator ||= MaxEmojisValidator.new(attributes: :title) + @validator.validate_each(record, :title, record.title) + end + + shared_examples "validating any topic title" do + it 'adds an error when emoji count is greater than SiteSetting.max_emojis_in_title' do + SiteSetting.max_emojis_in_title = 3 + record.title = '🧐 Lots of emojis here 🎃 :joy: :sunglasses:' + validate + expect(record.errors[:title]).to be_present + end + end + + describe 'topic' do + let(:record) { Fabricate.build(:topic) } + + it 'does not add an error when emoji count is good' do + SiteSetting.max_emojis_in_title = 2 + + record.title = 'To Infinity and beyond! 🚀 :woman:t5:' + validate + expect(record.errors[:title]).to_not be_present + end + + include_examples "validating any topic title" + end + + describe 'private message' do + let(:record) { Fabricate.build(:private_message_topic) } + + it 'does not add an error when emoji count is good' do + SiteSetting.max_emojis_in_title = 1 + + record.title = 'To Infinity and beyond! 🚀' + validate + expect(record.errors[:title]).to_not be_present + end + + include_examples "validating any topic title" + end +end