app/models/post.rb in radiant-forum-extension-2.1.6 vs app/models/post.rb in radiant-forum-extension-3.0.0.rc3
- old
+ new
@@ -9,15 +9,15 @@
accepts_nested_attributes_for :topic
accepts_nested_attributes_for :attachments, :allow_destroy => true
validates_presence_of :reader, :body
+ before_save :update_search_text
after_create :notify_holder_of_creation
after_destroy :notify_holder_of_destruction
-
+
default_scope :order => "posts.created_at DESC"
-
named_scope :comments, :conditions => "page_id IS NOT NULL"
named_scope :non_comments, :conditions => "page_id IS NULL"
named_scope :imported, :conditions => "old_id IS NOT NULL"
named_scope :in_topic, lambda { |topic| { :conditions => ["topic_id = ?", topic.id] }}
named_scope :in_topics, lambda { |topics|
@@ -30,34 +30,50 @@
named_scope :distinct_readers, :select => "DISTINCT posts.reader_id" do
def count
self.length # replacing a SQL shortcut that omits the distinct clause
end
end
- named_scope :containing, lambda { |term|
- {
- :conditions => ["posts.body LIKE :term OR topics.name LIKE :term", {:term => "%#{term}%"}],
- :joins => "LEFT OUTER JOIN topics on posts.topic_id = topics.id"
+ # adapted from the usual scope defined in has_groups, since here visibility is set at the forum level
+ named_scope :visible_to, lambda { |reader|
+ conditions = "topics.id IS NULL OR forums.id IS NULL OR pp.group_id IS NULL"
+ if reader && reader.group_ids.any?
+ ids = reader.group_ids
+ conditions = ["#{conditions} OR pp.group_id IN(#{ids.map{"?"}.join(',')})", *ids]
+ end
+ {
+ :joins => "INNER JOIN topics on posts.topic_id = topics.id LEFT OUTER JOIN forums on topics.forum_id = forums.id LEFT OUTER JOIN permissions as pp on pp.permitted_id = forums.id AND pp.permitted_type = 'Forum'",
+ :conditions => conditions,
+ :group => column_names.map { |n| self.table_name + '.' + n }.join(','),
+ :readonly => false
+ }
+ }
+ named_scope :matching, lambda { |term|
+ {
+ :conditions => ["posts.search_text LIKE ?", "%#{stopped(term)}%"]
}
}
- # other extensions can attach chains here to limit access
- def self.visible_to(reader)
- self.scoped
- end
-
def self.in_forum(forum)
in_topics(forum.topics)
end
def holder
page || topic
end
+
+ def title
+ holder.title if holder
+ end
def comment?
!!page
end
+ def reply?
+ !comment? && !first?
+ end
+
def page_when_paginated
holder.page_for(self)
end
def forum
@@ -92,17 +108,25 @@
!editable_interval || Time.now - self.created_at < editable_interval
end
def editable_by?(reader=nil)
return false unless reader
- still_editable? && reader && (reader.id == reader_id)
+ still_editable? && reader.id == reader_id
end
def visible_to?(reader=nil)
- return true if reader || Radiant::Config['forum.public?']
+ if topic && !topic.visible_to?(reader)
+ false
+ elsif page && !page.visible_to?(reader)
+ false
+ elsif !reader && !Radiant::Config['forum.public?']
+ false
+ else
+ true
+ end
end
-
+
# so that page comments can be rendered from a radius tag
def body_html
if body
html = RedCloth.new(body, [ :hard_breaks, :filter_html ]).to_html(:textile, :smilies)
Sanitize.clean(html, Sanitize::Config::RELAXED)
@@ -127,8 +151,23 @@
holder.notice_creation_of(self)
end
def dom_id
"post_#{self.id}"
+ end
+
+private
+
+ # this is rather crude, but it's database-agnostic, doesn't require
+ # any external indexing, and works well enough for most purposes.
+ # for a more satisfactory search, tell sphinx to index the search_text field.
+
+ def update_search_text
+ self.search_text = self.class.stopped("#{self.title} #{self.body}")
+ end
+
+ def self.stopped(text="")
+ stops = I18n.t('forum_extension.stopwords').split.join('|')
+ text.downcase.gsub(/\b(#{stops})\b/, '').gsub(/(\W+)/, ' ')
end
end