Add min_private_message_title_length site setting so private messages can have short titles

This commit is contained in:
Neil Lalonde 2013-06-04 17:58:25 -04:00
parent 89ef726bb3
commit 2465c9c724
9 changed files with 131 additions and 9 deletions

View File

@ -68,6 +68,10 @@ Discourse.Composer = Discourse.Model.extend({
return false; return false;
}.property('editingPost', 'creatingTopic', 'post.post_number'), }.property('editingPost', 'creatingTopic', 'post.post_number'),
canCategorize: function() {
return (this.get('editTitle') && !this.get('creatingPrivateMessage'));
}.property('editTitle', 'creatingPrivateMessage'),
showAdminOptions: function() { showAdminOptions: function() {
if (this.get('creatingTopic') && Discourse.User.current('staff')) return true; if (this.get('creatingTopic') && Discourse.User.current('staff')) return true;
return false; return false;
@ -164,9 +168,8 @@ Discourse.Composer = Discourse.Model.extend({
// - creating a new topic // - creating a new topic
// - editing the 1st post // - editing the 1st post
// - creating a private message // - creating a private message
if (this.get('editTitle') &&
(this.get('titleLength') < Discourse.SiteSettings.min_topic_title_length || if (this.get('editTitle') && !this.get('titleLengthValid')) return true;
this.get('titleLength') > Discourse.SiteSettings.max_topic_title_length) ) return true;
// Need at least one user when sending a private message // Need at least one user when sending a private message
if ( this.get('creatingPrivateMessage') && if ( this.get('creatingPrivateMessage') &&
@ -178,11 +181,20 @@ Discourse.Composer = Discourse.Model.extend({
// reply is always required // reply is always required
if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true; if (this.get('replyLength') < Discourse.SiteSettings.min_post_length) return true;
if (this.get('editTitle') && !Discourse.SiteSettings.allow_uncategorized_topics && !this.get('categoryName')) return true; if (this.get('canCategorize') && !Discourse.SiteSettings.allow_uncategorized_topics && !this.get('categoryName')) return true;
return false; return false;
}.property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryName'), }.property('loading', 'editTitle', 'titleLength', 'targetUsernames', 'replyLength', 'categoryName'),
titleLengthValid: function() {
if (this.get('creatingPrivateMessage')) {
if (this.get('titleLength') < Discourse.SiteSettings.min_private_message_title_length) return false;
} else {
if (this.get('titleLength') < Discourse.SiteSettings.min_topic_title_length) return false;
}
return (this.get('titleLength') <= Discourse.SiteSettings.max_topic_title_length);
}.property('titleLength'),
// The text for the save button // The text for the save button
saveText: function() { saveText: function() {
switch (this.get('action')) { switch (this.get('action')) {
@ -519,7 +531,11 @@ Discourse.Composer = Discourse.Model.extend({
@property missingTitleCharacters @property missingTitleCharacters
**/ **/
missingTitleCharacters: function() { missingTitleCharacters: function() {
return Discourse.SiteSettings.min_topic_title_length - this.get('titleLength'); if (this.get('creatingPrivateMessage')) {
return Discourse.SiteSettings.min_private_message_title_length - this.get('titleLength');
} else {
return Discourse.SiteSettings.min_topic_title_length - this.get('titleLength');
}
}.property('titleLength'), }.property('titleLength'),

View File

@ -373,10 +373,11 @@ Discourse.ComposerView = Discourse.View.extend({
titleValidation: function() { titleValidation: function() {
var title = this.get('content.title'), reason; var title = this.get('content.title'), reason;
var minLength = (this.get('content.creatingPrivateMessage') ? Discourse.SiteSettings.min_private_message_title_length : Discourse.SiteSettings.min_topic_title_length);
if( !title || title.length < 1 ){ if( !title || title.length < 1 ){
reason = Em.String.i18n('composer.error.title_missing'); reason = Em.String.i18n('composer.error.title_missing');
} else if( title.length < Discourse.SiteSettings.min_topic_title_length ) { } else if( title.length < minLength ) {
reason = Em.String.i18n('composer.error.title_too_short', {min: Discourse.SiteSettings.min_topic_title_length}) reason = Em.String.i18n('composer.error.title_too_short', {min: minLength})
} else if( title.length > Discourse.SiteSettings.max_topic_title_length ) { } else if( title.length > Discourse.SiteSettings.max_topic_title_length ) {
reason = Em.String.i18n('composer.error.title_too_long', {max: Discourse.SiteSettings.max_topic_title_length}) reason = Em.String.i18n('composer.error.title_too_long', {max: Discourse.SiteSettings.max_topic_title_length})
} }

View File

@ -34,6 +34,7 @@ class SiteSetting < ActiveRecord::Base
client_setting(:max_post_length, 16000) client_setting(:max_post_length, 16000)
client_setting(:min_topic_title_length, 15) client_setting(:min_topic_title_length, 15)
client_setting(:max_topic_title_length, 255) client_setting(:max_topic_title_length, 255)
client_setting(:min_private_message_title_length, 2)
client_setting(:allow_uncategorized_topics, true) client_setting(:allow_uncategorized_topics, true)
client_setting(:min_search_term_length, 3) client_setting(:min_search_term_length, 3)
client_setting(:flush_timings_secs, 5) client_setting(:flush_timings_secs, 5)
@ -227,6 +228,10 @@ class SiteSetting < ActiveRecord::Base
min_topic_title_length..max_topic_title_length min_topic_title_length..max_topic_title_length
end end
def self.private_message_title_length
min_private_message_title_length..max_topic_title_length
end
def self.post_length def self.post_length
min_post_length..max_post_length min_post_length..max_post_length
end end

View File

@ -39,8 +39,7 @@ class Topic < ActiveRecord::Base
before_validation :sanitize_title before_validation :sanitize_title
validates :title, :presence => true, validates :title, :presence => true,
:length => { :in => SiteSetting.topic_title_length, :topic_title_length => true,
:allow_blank => true },
:quality_title => { :unless => :private_message? }, :quality_title => { :unless => :private_message? },
:unique_among => { :unless => Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) }, :unique_among => { :unless => Proc.new { |t| (SiteSetting.allow_duplicate_topic_titles? || t.private_message?) },
:message => :has_already_been_used, :message => :has_already_been_used,

View File

@ -418,6 +418,7 @@ en:
max_post_length: "Maximum post length in characters" max_post_length: "Maximum post length in characters"
min_topic_title_length: "Minimum topic title length in characters" min_topic_title_length: "Minimum topic title length in characters"
max_topic_title_length: "Maximum topic title length in characters" max_topic_title_length: "Maximum topic title length in characters"
min_private_message_title_length: "Minimum title length for a private message in characters"
min_search_term_length: "Minimum search term length in characters" min_search_term_length: "Minimum search term length in characters"
allow_uncategorized_topics: "Allow topics to be created without a category" allow_uncategorized_topics: "Allow topics to be created without a category"
allow_duplicate_topic_titles: "Allow topics with identical titles" allow_duplicate_topic_titles: "Allow topics with identical titles"

View File

@ -0,0 +1,16 @@
class TopicTitleLengthValidator < ActiveModel::EachValidator
def initialize(options)
@topic_title_validator = ActiveModel::Validations::LengthValidator.new({attributes: :title, in: SiteSetting.topic_title_length, allow_blank: true})
@private_message_title_validator = ActiveModel::Validations::LengthValidator.new({attributes: :title, in: SiteSetting.private_message_title_length, allow_blank: true})
super
end
def validate_each(record, attribute, value)
if record.private_message?
@private_message_title_validator.validate_each(record, attribute, value)
else
@topic_title_validator.validate_each(record, attribute, value)
end
end
end

View File

@ -0,0 +1,60 @@
# encoding: UTF-8
require 'spec_helper'
require 'validators/topic_title_length_validator'
describe TopicTitleLengthValidator do
let(:validator) { TopicTitleLengthValidator.new({attributes: :title}) }
subject(:validate) { validator.validate_each(record,:title,record.title) }
shared_examples "validating any topic title" do
it 'adds an error when topic title is greater than SiteSetting.max_topic_title_length' do
record.title = 'a' * (SiteSetting.max_topic_title_length + 1)
validate
expect(record.errors[:title]).to be_present
end
end
describe 'topic' do
let(:record) { Fabricate.build(:topic) }
it 'adds an error when topic title is shorter than SiteSetting.min_topic_title_length' do
record.title = 'a' * (SiteSetting.min_topic_title_length - 1)
validate
expect(record.errors[:title]).to be_present
end
it 'does not add an error when length is good' do
record.title = 'a' * (SiteSetting.min_topic_title_length)
validate
expect(record.errors[:title]).to_not be_present
end
include_examples "validating any topic title"
end
describe 'private message' do
before do
SiteSetting.stubs(:min_private_message_title_length).returns(3)
end
let(:record) { Fabricate.build(:private_message_topic) }
it 'adds an error when topic title is shorter than SiteSetting.min_private_message_title_length' do
record.title = 'a' * (SiteSetting.min_private_message_title_length - 1)
validate
expect(record.errors[:title]).to be_present
end
it 'does not add an error when topic title is shorter than SiteSetting.min_topic_title_length' do
SiteSetting.stubs(:min_topic_title_length).returns(15)
record.title = 'a' * (SiteSetting.min_private_message_title_length)
validate
expect(record.errors[:title]).to_not be_present
end
include_examples "validating any topic title"
end
end

View File

@ -156,4 +156,11 @@ describe SiteSetting do
SiteSetting.post_length.should == (SiteSetting.defaults[:min_post_length]..SiteSetting.defaults[:max_post_length]) SiteSetting.post_length.should == (SiteSetting.defaults[:min_post_length]..SiteSetting.defaults[:max_post_length])
end end
end end
describe 'private_message_title_length' do
it 'returns a range of min/max pm topic title length' do
expect(SiteSetting.private_message_title_length).to eq(SiteSetting.defaults[:min_private_message_title_length]..SiteSetting.defaults[:max_topic_title_length])
end
end
end end

View File

@ -52,6 +52,23 @@ describe Topic do
end end
end end
context 'private message title' do
before do
SiteSetting.stubs(:min_topic_title_length).returns(15)
SiteSetting.stubs(:min_private_message_title_length).returns(3)
end
it 'allows shorter titles' do
pm = Fabricate.build(:private_message_topic, title: 'a' * SiteSetting.min_private_message_title_length)
expect(pm).to be_valid
end
it 'but not too short' do
pm = Fabricate.build(:private_message_topic, title: 'a')
expect(pm).to_not be_valid
end
end
context 'topic title uniqueness' do context 'topic title uniqueness' do
let!(:topic) { Fabricate(:topic) } let!(:topic) { Fabricate(:topic) }