app/models/content.rb in typo-4.0.3 vs app/models/content.rb in typo-4.1
- old
+ new
@@ -9,14 +9,26 @@
validates_presence_of :blog_id
composed_of :state, :class_name => 'ContentState::Factory',
:mapping => %w{ state memento }
- has_and_belongs_to_many :notify_users, :class_name => 'User',
- :join_table => 'notifications', :foreign_key => 'notify_content_id',
- :association_foreign_key => 'notify_user_id', :uniq => true
+ has_many :notifications, :foreign_key => 'content_id'
+ has_many :notify_users, :through => :notifications,
+ :source => 'notify_user',
+ :uniq => true
+ def notify_users=(collection)
+ return notify_users.clear if collection.empty?
+ self.class.transaction do
+ self.notifications.clear
+ collection.uniq.each do |u|
+ self.notifications.build(:notify_user => u)
+ end
+ notify_users.target = collection
+ end
+ end
+
has_many :triggers, :as => :pending_item, :dependent => :delete_all
before_save :state_before_save
after_save :post_trigger, :state_after_save
@@ -28,66 +40,65 @@
def initialize(*args, &block)
super(*args, &block)
set_default_blog
end
+ def invalidates_cache?(on_destruction = false)
+ if on_destruction
+ just_changed_published_status? || published?
+ else
+ changed? && published? || just_changed_published_status?
+ end
+ end
+
def set_default_blog
if self.blog_id == nil or self.blog_id == 0
self.blog = Blog.default
end
end
class << self
+ # Quite a bit of this isn't needed anymore.
def content_fields(*attribs)
@@content_fields[self] = ((@@content_fields[self]||[]) + attribs).uniq
@@html_map[self] = nil
attribs.each do | field |
define_method("#{field}=") do | newval |
if self[field] != newval
changed
self[field] = newval
- if html_map(field)
- self[html_map(field)] = nil
- end
- notify_observers(self, field.to_sym)
end
self[field]
end
unless self.method_defined?("#{field}_html")
define_method("#{field}_html") do
- if blog.controller
- html(blog.controller, field.to_sym)
- else
- self["#{field}_html"]
- end
+ typo_deprecated "Use html(:#{field})"
+ html(field.to_sym)
end
end
end
end
def html_map(field=nil)
unless @@html_map[self]
@@html_map[self] = Hash.new
instance = self.new
@@content_fields[self].each do |attrib|
- @@html_map[self][attrib] = "#{attrib}_html"
+ @@html_map[self][attrib] = true
end
end
if field
@@html_map[self][field]
else
@@html_map[self]
end
end
def find_published(what = :all, options = {})
- options.reverse_merge!(:order => default_order)
- options[:conditions] = merge_conditions(['published = ?', true],
- options[:conditions])
- options[:include] ||= []
- options[:include] += [:blog]
- find(what, options)
+ with_scope(:find => {:order => default_order, :conditions => {:published => true}}) do
+ find what, options
+ end
end
def default_order
'published_at DESC'
end
@@ -101,82 +112,96 @@
at ||= options.delete(:at) || Time.now
with_scope(:find => { :conditions => ['published_at < ?', at]}) do
find_published(what, options)
end
end
+ end
- def merge_conditions(*conditions)
- conditions.compact.collect do |cond|
- '(' + sanitize_sql(cond) + ')'
- end.join(' AND ')
- end
+ def content_fields
+ @@content_fields[self.class]
end
def state_before_save
state.before_save(self)
end
def state_after_save
state.after_save(self)
end
- def html_map(field=nil); self.class.html_map(field); end
-
- def full_html
- unless blog.controller
- raise "full_html only works with an active controller"
- end
- html(blog.controller, :all)
+ def html_map(field=nil)
+ self.class.html_map(field)
end
- def populate_html_fields(controller)
- html_map.each do |field, html_field|
- if !self[field].blank? && self[html_field].blank?
- html = text_filter.filter_text_for_controller( self[field].to_s, controller, self, false )
- self[html_field] = self.send("#{html_field}_postprocess",
- html, controller)
- end
- end
+ def cache_key(field)
+ id ? "contents_html/#{id}/#{field}" : nil
end
- def html(controller,what = :all)
- populate_html_fields(controller)
-
- if what == :all
- self[:body_html].to_s + (self[:extended_html].to_s rescue '')
- elsif self.class.html_map(what)
- self[html_map(what)]
+ # Return HTML for some part of this object. It will be fetched from the
+ # cache if possible, or regenerated if needed.
+ def html(field = :all)
+ if field == :all
+ generate_html(:all, content_fields.map{|f| self[f].to_s}.join("\n\n"))
+ elsif self.class.html_map(field)
+ generate_html(field)
else
- raise "Unknown 'what' in article.html"
+ raise "Unknown field: #{field.inspect} in article.html"
end
end
- def method_missing(method, *args, &block)
- if method.to_s =~ /_postprocess$/
- args[0]
- else
- super(method, *args, &block)
- end
+ # Generate HTML for a specific field using the text_filter in use for this
+ # object. The HTML is cached in the fragment cache, using the +ContentCache+
+ # object in @@cache.
+ def generate_html(field, text = nil)
+ text ||= self[field].to_s
+ html = text_filter.filter_text_for_content(blog, text, self)
+ html ||= text # just in case the filter puked
+ html_postprocess(field,html).to_s
end
+ # Post-process the HTML. This is a noop by default, but Comment overrides it
+ # to enforce HTML sanity.
+ def html_postprocess(field,html)
+ html
+ end
+
def whiteboard
self[:whiteboard] ||= Hash.new
end
+ # The default text filter. Generally, this is the filter specified by blog.text_filter,
+ # but comments may use a different default.
+ def default_text_filter
+ blog.text_filter.to_text_filter
+ end
+ # Grab the text filter for this object. It's either the filter specified by
+ # self.text_filter_id, or the default specified in the blog object.
def text_filter
- self[:text_filter] ||= if self[:text_filter_id]
- TextFilter.find(self[:text_filter_id])
- else
- blog[default_text_filter_config_key].to_text_filter
- end
+ if self[:text_filter_id] && !self[:text_filter_id].zero?
+ TextFilter.find(self[:text_filter_id])
+ else
+ default_text_filter
+ end
end
+ # Set the text filter for this object.
def text_filter=(filter)
- self[:text_filter_id] = filter.to_text_filter.id
+ returning(filter.to_text_filter) { |tf| self.text_filter_id = tf.id }
end
+ # Changing the title flags the object as changed
+ def title=(new_title)
+ if new_title == self[:title]
+ self[:title]
+ else
+ self.changed
+ self[:title] = new_title
+ end
+ end
+
+ # FIXME -- this feels wrong.
def blog
self[:blog] ||= blog_id.to_i.zero? ? Blog.default : Blog.find(blog_id)
end
def state=(newstate)
@@ -222,10 +247,14 @@
def just_published?
state.just_published?
end
+ def just_changed_published_status?
+ state.just_changed_published_status?
+ end
+
def withdrawn?
state.withdrawn?
end
def publication_pending?
@@ -238,20 +267,33 @@
def after_save
state.after_save(self)
end
- def send_notification_to_user(controller, user)
- notify_user_via_email(controller, user)
- notify_user_via_jabber(controller, user)
+ def send_notification_to_user(user)
+ notify_user_via_email(user)
+ notify_user_via_jabber(user)
end
- def send_notifications(controller = nil)
- state.send_notifications(self, controller || blog.controller)
+ def send_notifications()
+ state.send_notifications(self)
end
+
+ # deprecated
+ def full_html
+ typo_deprecated "use .html instead"
+ html
+ end
+
end
class Object
def to_text_filter
TextFilter.find_by_name(self.to_s) || TextFilter.find_by_name('none')
end
end
+
+class ContentTextHelpers
+ include ActionView::Helpers::TagHelper
+ include ActionView::Helpers::TextHelper
+end
+