public
Description: A mirror of the mephisto code-base
Homepage: http://mephistoblog.com/
Clone URL: git://github.com/halorgium/mephisto.git
Search Repo:
mephisto / app / models / article.rb
100644 230 lines (192 sloc) 7.75 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
class Article < Content
  class CommentNotAllowed < StandardError; end
    
  validates_presence_of :title, :user_id, :site_id
 
  before_validation { |record| record.set_default_filter! }
  after_validation :convert_to_utc
  has_permalink :title
  after_save :save_assigned_sections
  after_update :reset_comment_attributes
 
  acts_as_versioned :if_changed => [:title, :body, :excerpt], :limit => 5 do
    def self.included(base)
      base.send :include, Mephisto::TaggableMethods
      base.belongs_to :updater, :class_name => '::User', :foreign_key => 'updater_id', :with_deleted => true
      [:year, :month, :day].each { |m| base.delegate m, :to => :published_at }
    end
 
    def published?
      !new_record? && !published_at.nil?
    end
 
    def pending?
      !published? || Time.now.utc < published_at
    end
    
    def status
      pending? ? :pending : :published
    end
  end
 
  has_many :assigned_sections, :dependent => :destroy
  has_many :sections, :through => :assigned_sections, :order => 'sections.name'
 
  has_many :events, :order => 'created_at desc', :dependent => :delete_all
  with_options :order => 'created_at', :class_name => 'Comment' do |comment|
    comment.has_many :comments, :conditions => ['contents.approved = ?', true] do
      def unapprove(id)
        returning find(id) do |comment|
          comment.approved = false
          comment.save
        end
      end
    end
    comment.has_many :unapproved_comments, :conditions => ['contents.approved = ?', false] do
      def approve(id)
        returning find(id) do |comment|
          comment.approved = true
          comment.save
        end
      end
    end
    comment.has_many :all_comments, :dependent => :delete_all
  end
  
  has_many :assigned_assets, :order => 'position', :dependent => :destroy
  has_many :assets, :through => :assigned_assets, :conditions => ['assigned_assets.active = ?', true], :select => 'assets.*, assigned_assets.label' do
    def add(asset, label = nil)
      returning AssignedAsset.find_or_create_by_article_id_and_asset_id(proxy_owner.id, asset.id) do |aa|
        aa.label = label
        aa.active = true
        aa.save!
      end
    end
    
    def remove(asset)
      AssignedAsset.update_all ['active = ?', false], ['article_id = ? AND asset_id = ?', proxy_owner.id, asset.id]
    end
  end
 
  class << self
    def with_published(&block)
      with_scope({:find => { :conditions => ['contents.published_at <= ? AND contents.published_at IS NOT NULL', Time.now.utc] } }, &block)
    end
 
    def find_by_date(options = {})
      with_published do
        find :all, {:order => 'contents.published_at desc'}.update(options)
      end
    end
    
    def find_all_in_month(year, month, options = {})
      find(:all, options.merge(:order => 'contents.published_at DESC', :conditions => ["contents.published_at <= ? AND contents.published_at BETWEEN ? AND ?",
        Time.now.utc, *Time.delta(year.to_i, month.to_i)]))
    end
    
    def find_all_by_tags(tag_names, limit = 15)
      find(:all, :order => 'contents.published_at DESC', :include => [:tags, :user], :limit => limit,
        :conditions => ['(contents.published_at <= ? AND contents.published_at IS NOT NULL) AND tags.name IN (?)', Time.now.utc, tag_names])
    end
    
    def permalink_for(str)
      PermalinkFu.escape(str)
    end
  end
 
  # AX
  def full_permalink
    published? && ['', published_at.year, published_at.month, published_at.day, permalink] * '/'
  end
 
  def has_section?(section)
    return @new_sections.include?(section.id.to_s) if !@new_sections.blank?
    (new_record? && section.home?) || sections.include?(section)
  end
 
  def section_ids=(new_sections)
    @new_sections = new_sections
  end
 
  def published_at=(value)
    @recently_published = published_at.nil? && value
    write_attribute :published_at, value
  end
  
  def recently_published?
    @recently_published
  end
 
  # :mode - single / list. Specifies whether the body is only the excerpt or not
  # :page - true / false. Specifies whether the article is the main section page.
  def to_liquid(options = {})
    ArticleDrop.new self, options
  end
 
  def filter=(new_filter)
    return if new_filter == read_attribute(:filter)
    @old_filter ||= read_attribute(:filter)
    write_attribute :filter, new_filter
  end
 
  # AX
  def hash_for_permalink(options = {})
    [:year, :month, :day, :permalink].inject(options) { |o, a| o.update a => send(a) }
  end
 
  def accept_comments?
    status == :published && (comment_age > -1) && (comment_age == 0 || comments_expired_at > Time.now.utc)
  end
 
  def comments_expired_at
    (published_at || Time.now.utc) + comment_age.days
  end
 
  def set_filter_from(filtered_object)
    self.filter = filtered_object.filter
  end
 
  def set_default_filter_from(filtered_object)
    set_filter_from(filtered_object) if filter.nil?
  end
 
  def set_default_filter!
    set_default_filter_from user
  end
 
  def add_xml(builder)
    add_podcast_xml(builder)
  end
 
  def next(section=nil)
    return nil if section && !sections.include?(section)
    section = sections[0] if (section.nil?)
    self.class.with_published do
      if section
        if section.paged?
          index = section.articles.index(self)
          (index <= section.articles.length-1) ? section.articles[index+1] : nil
          # article = section.articles.detect {|article| article.id == id }
        else
          site.articles.find :first, :conditions => ['published_at > ? and assigned_sections.section_id = ?', published_at, section.id],
            :joins => 'inner join assigned_sections on contents.id = assigned_sections.article_id',
            :order => 'published_at'
        end
      else
        site.articles.find :first, :conditions => ['published_at > ?', published_at], :order => 'published_at'
      end
    end
  end
 
  def previous(section=nil)
    return nil if section && !sections.include?(section)
    section = sections[0] if (section.nil?)
    self.class.with_published do
      if section
        if section.paged?
          index = section.articles.index(self)
          (index > 0) ? section.articles[index-1] : nil
          # article = section.articles.detect {|article| article.id == id }
        else
          site.articles.find :first, :conditions => ['published_at < ? and assigned_sections.section_id = ?', published_at, section.id],
            :joins => 'inner join assigned_sections on contents.id = assigned_sections.article_id',
            :order => 'published_at desc'
        end
      else
        site.articles.find :first, :conditions => ['published_at < ?', published_at], :order => 'published_at desc'
      end
    end
  end
 
 
  protected
    def convert_to_utc
      self.published_at = published_at.utc if published_at
    end
    
    def save_assigned_sections
      return if @new_sections.nil?
      assigned_sections.each do |assigned_section|
        @new_sections.delete(assigned_section.section_id.to_s) || assigned_section.destroy
      end
      
      if !@new_sections.blank?
        Section.find(:all, :conditions => ['id in (?)', @new_sections]).each { |section| assigned_sections.create :section => section }
        sections.reset
      end
    
      @new_sections = nil
    end
    
    def reset_comment_attributes
      Content.update_all ['title = ?, published_at = ?, permalink = ?', title, published_at, permalink], ['article_id = ?', id]
    end
    
    def add_podcast_xml(builder)
      if asset = assets.find(:first, :conditions => ['label = ?', 'podcast'], :select => 'assets.*')
        builder.link :rel => :enclosure, :type => asset.content_type, :length => asset.size, :href => asset.public_filename
      end
    end
end