Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 111
- Log:
Renamed cookies with "typoapp_" prefix and corrected their paths.
Integrated with Hub, which includes removing support for the comment
author cookie; added a comment e-mail address cookie instead, to go
with the URL cookie that Typo already supports. Updated styles to
improve comment display and included e-mail address, where supplied,
in hex-encoded form after the author name.
- Author:
- adh
- Date:
- Mon Oct 23 21:30:52 +0100 2006
- Size:
- 8534 Bytes
1 | class ArticlesController < ContentController |
2 | |
3 | # We might expect to have to do the stuff below, but because the only |
4 | # method protected presently is 'comment' and that works by AJAX it has |
5 | # to take a different approach. The commented out code is left here in |
6 | # case other methods become protected in future - saves having to dig |
7 | # out reference code from some other controller to use as a template. |
8 | # |
9 | # # Action permissions for this class as a class variable, exposed |
10 | # # to the public through a class method. |
11 | # |
12 | # @@hubssolib_permissions = HubSsoLib::Permissions.new({ |
13 | # :comment => [ :admin, :webmaster, :privileged, :normal ] |
14 | # }) |
15 | # |
16 | # def ArticlesController.hubssolib_permissions |
17 | # @@hubssolib_permissions |
18 | # end |
19 | |
20 | before_filter :verify_config |
21 | |
22 | layout :theme_layout, :except => [:comment_preview, :trackback] |
23 | |
24 | cache_sweeper :blog_sweeper |
25 | |
26 | cached_pages = [:index, :read, :permalink, :category, :find_by_date, :archives, :view_page, :tag, :author] |
27 | # If you're really memory-constrained, then consider replacing |
28 | # caches_action_with_params with caches_page |
29 | caches_action_with_params *cached_pages |
30 | session :off, :only => cached_pages |
31 | |
32 | verify(:only => [:nuke_comment, :nuke_trackback], |
33 | :session => :user, :method => :post, |
34 | :render => { :text => 'Forbidden', :status => 403 }) |
35 | |
36 | def index |
37 | # On Postgresql, paginate's default count is *SLOW*, because it does a join against |
38 | # all of the eager-loaded tables. I've seen it take up to 7 seconds on my test box. |
39 | # |
40 | # So, we're going to use the older Paginator class and manually provide a count. |
41 | # This is a 100x speedup on my box. |
42 | count = Article.count(:conditions => ['published = ? AND contents.published_at < ? AND blog_id = ?', |
43 | true, Time.now, this_blog.id]) |
44 | @pages = Paginator.new self, count, this_blog.limit_article_display, @params[:page] |
45 | @articles = Article.find( :all, |
46 | :offset => @pages.current.offset, |
47 | :limit => @pages.items_per_page, |
48 | :order => "contents.published_at DESC", |
49 | :include => [:categories, :tags, :user, :blog], |
50 | :conditions => |
51 | ['published = ? AND contents.published_at < ? AND blog_id = ?', |
52 | true, Time.now, this_blog.id] |
53 | ) |
54 | end |
55 | |
56 | def search |
57 | @articles = this_blog.published_articles.search(params[:q]) |
58 | render_paginated_index("No articles found...") |
59 | end |
60 | |
61 | def comment_preview |
62 | if params[:comment].blank? or params[:comment][:body].blank? |
63 | render :nothing => true |
64 | return |
65 | end |
66 | |
67 | set_headers |
68 | @comment = this_blog.comments.build(params[:comment]) |
69 | @controller = self |
70 | end |
71 | |
72 | def archives |
73 | @articles = this_blog.published_articles |
74 | end |
75 | |
76 | def read |
77 | display_article { this_blog.published_articles.find(params[:id]) } |
78 | end |
79 | |
80 | def permalink |
81 | display_article(this_blog.published_articles.find_by_permalink(*params.values_at(:year, :month, :day, :title))) |
82 | end |
83 | |
84 | def find_by_date |
85 | @articles = this_blog.published_articles.find_all_by_date(params[:year], params[:month], params[:day]) |
86 | render_paginated_index |
87 | end |
88 | |
89 | def error(message = "Record not found...") |
90 | @message = message.to_s |
91 | render :action => 'error' |
92 | end |
93 | |
94 | def author |
95 | render_grouping(User) |
96 | end |
97 | |
98 | def category |
99 | render_grouping(Category) |
100 | end |
101 | |
102 | def tag |
103 | render_grouping(Tag) |
104 | end |
105 | |
106 | # Receive comments to articles |
107 | def comment |
108 | unless @request.xhr? || this_blog.sp_allow_non_ajax_comments |
109 | render_error("non-ajax commenting is disabled") |
110 | return |
111 | end |
112 | |
113 | # The Hub filter would catch this action if we let it, but because |
114 | # it is fetched by an AJAX mechanism we end up with the login page |
115 | # embedded inside the parent :-) - so take steps to prevent this. |
116 | |
117 | unless hubssolib_logged_in? |
118 | render_error("You are not logged in; you cannot comment on articles") |
119 | return |
120 | end |
121 | |
122 | if request.post? |
123 | begin |
124 | params[:comment].merge!({:ip => request.remote_ip, |
125 | :published => true }) |
126 | @article = this_blog.published_articles.find(params[:id]) |
127 | @comment = @article.comments.build(params[:comment]) |
128 | @comment.user = session[:user] |
129 | |
130 | spam_options = { |
131 | :user_agent => request.env['HTTP_USER_AGENT'], |
132 | :referrer => request.env['HTTP_REFERER'], |
133 | :permalink => this_blog.article_url(@article, false)} |
134 | |
135 | if @comment.is_spam? spam_options |
136 | STDERR.puts "Moderating comment as spam!" |
137 | @comment.withdraw |
138 | end |
139 | |
140 | @comment.save! |
141 | |
142 | add_to_cookies(:typoapp_url, @comment.url) |
143 | add_to_cookies(:typoapp_email, @comment.email) |
144 | |
145 | set_headers |
146 | render :partial => "comment", :object => @comment |
147 | rescue ActiveRecord::RecordInvalid |
148 | STDERR.puts @comment.errors.inspect |
149 | render_error(@comment) |
150 | end |
151 | end |
152 | end |
153 | |
154 | # Receive trackbacks linked to articles |
155 | def trackback |
156 | @error_message = catch(:error) do |
157 | if params[:__mode] == "rss" |
158 | # Part of the trackback spec... will implement later |
159 | # XXX. Should this throw an error? |
160 | elsif !(params.has_key?(:url) && params.has_key?(:id)) |
161 | throw :error, "A URL is required" |
162 | else |
163 | begin |
164 | settings = { :id => params[:id], |
165 | :url => params[:url], :blog_name => params[:blog_name], |
166 | :title => params[:title], :excerpt => params[:excerpt], |
167 | :ip => request.remote_ip, :published => true } |
168 | this_blog.ping_article!(settings) |
169 | rescue ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid |
170 | throw :error, "Article id #{params[:id]} not found." |
171 | rescue ActiveRecord::RecordInvalid |
172 | throw :error, "Trackback not saved" |
173 | end |
174 | end |
175 | nil |
176 | end |
177 | end |
178 | |
179 | def nuke_comment |
180 | Comment.find(params[:id]).destroy |
181 | render :nothing => true |
182 | end |
183 | |
184 | def nuke_trackback |
185 | Trackback.find(params[:id]).destroy |
186 | render :nothing => true |
187 | end |
188 | |
189 | def view_page |
190 | if(@page = Page.find_by_name(params[:name].to_a.join('/'))) |
191 | @page_title = @page.title |
192 | else |
193 | render :nothing => true, :status => 404 |
194 | end |
195 | end |
196 | |
197 | def markup_help |
198 | render :text => TextFilter.find(params[:id]).commenthelp |
199 | end |
200 | |
201 | private |
202 | |
203 | def add_to_cookies(name, value, path=nil, expires=nil) |
204 | cookies[name] = { :value => value, :path => path ? PATH_PREFIX + '/' + path : "#{PATH_PREFIX}/#{controller_name}", |
205 | :expires => 6.weeks.from_now } |
206 | end |
207 | |
208 | def verify_config |
209 | if User.count == 0 |
210 | redirect_to :controller => "accounts", :action => "signup" |
211 | elsif ! this_blog.is_ok? |
212 | redirect_to :controller => "admin/general", :action => "redirect" |
213 | else |
214 | return true |
215 | end |
216 | end |
217 | |
218 | def display_article(article = nil) |
219 | begin |
220 | @article = block_given? ? yield : article |
221 | @comment = Comment.new |
222 | @page_title = @article.title |
223 | auto_discovery_feed :type => 'article', :id => @article.id |
224 | render :action => 'read' |
225 | rescue ActiveRecord::RecordNotFound, NoMethodError => e |
226 | error("Post not found...") |
227 | end |
228 | end |
229 | |
230 | alias_method :rescue_action_in_public, :error |
231 | |
232 | def render_error(object = '', status = 500) |
233 | render(:text => (object.errors.full_messages.join(", ") rescue object.to_s), :status => status) |
234 | end |
235 | |
236 | def set_headers |
237 | @headers["Content-Type"] = "text/html; charset=utf-8" |
238 | end |
239 | |
240 | def list_groupings(klass) |
241 | @grouping_class = klass |
242 | @groupings = klass.find_all_with_article_counters(1000) |
243 | render :action => 'groupings' |
244 | end |
245 | |
246 | def render_grouping(klass) |
247 | return list_groupings(klass) unless params[:id] |
248 | |
249 | @page_title = "#{this_blog.blog_name} - #{klass.to_s.underscore} #{params[:id]}" |
250 | @articles = klass.find_by_permalink(params[:id]).articles.find_already_published rescue [] |
251 | auto_discovery_feed :type => klass.to_s.underscore, :id => params[:id] |
252 | render_paginated_index("Can't find posts with #{klass.to_prefix} '#{h(params[:id])}'") |
253 | end |
254 | |
255 | def render_paginated_index(on_empty = "No posts found...") |
256 | return error(on_empty) if @articles.empty? |
257 | |
258 | @pages = Paginator.new self, @articles.size, this_blog.limit_article_display, @params[:page] |
259 | start = @pages.current.offset |
260 | stop = (@pages.current.next.offset - 1) rescue @articles.size |
261 | # Why won't this work? @articles.slice!(start..stop) |
262 | @articles = @articles.slice(start..stop) |
263 | render :action => 'index' |
264 | end |
265 | end |