typo 3.99.3 → 3.99.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README +1 -39
- data/app/controllers/admin/feedback_controller.rb +71 -0
- data/app/controllers/articles_controller.rb +11 -0
- data/app/helpers/admin/feedback_helper.rb +9 -0
- data/app/helpers/application_helper.rb +5 -1
- data/app/models/article.rb +21 -1
- data/app/models/blog.rb +25 -1
- data/app/models/comment.rb +12 -2
- data/app/models/content.rb +63 -4
- data/app/models/ping.rb +3 -3
- data/app/models/text_filter.rb +1 -1
- data/app/models/trackback.rb +12 -1
- data/app/views/admin/content/_form.rhtml +2 -2
- data/app/views/admin/feedback/_item.rhtml +15 -0
- data/app/views/admin/feedback/list.rhtml +46 -0
- data/app/views/admin/general/index.rhtml +26 -0
- data/app/views/articles/_comment.rhtml +3 -0
- data/app/views/articles/read.rhtml +2 -2
- data/app/views/layouts/administration.rhtml +1 -0
- data/bin/typo +3 -23
- data/components/plugins/sidebars/archives_controller.rb +1 -1
- data/components/plugins/sidebars/xml_controller.rb +1 -1
- data/components/plugins/textfilters/flickr_controller.rb +1 -1
- data/components/plugins/textfilters/sparkline_controller.rb +3 -2
- data/components/plugins/textfilters/textile_controller.rb +6 -0
- data/config/mongrel.conf +2 -0
- data/db/converters/wordpress2.rb +291 -0
- data/db/migrate/022_superclass_trackbacks.rb +1 -0
- data/db/migrate/023_superclass_pages.rb +4 -3
- data/db/schema.rb +4 -4
- data/doc/Installer.txt +81 -6
- data/doc/typo-4.0-release-notes.txt +135 -0
- data/installer/rails-installer.rb +22 -3
- data/installer/rails-installer/commands.rb +27 -26
- data/installer/rails-installer/web-servers.rb +2 -0
- data/lib/sidebars/plugin.rb +10 -8
- data/lib/tasks/release.rake +1 -1
- data/lib/typo_version.rb +1 -1
- data/public/javascripts/dragdrop.js +252 -63
- data/public/javascripts/effects.js +15 -10
- data/public/javascripts/prototype.js +59 -38
- data/public/javascripts/typo.js +10 -0
- data/public/stylesheets/administration.css +111 -66
- data/test/functional/admin/feedback_controller_test.rb +24 -0
- data/test/mocks/test/http_mock.rb +2 -1
- data/test/unit/article_test.rb +6 -0
- data/test/unit/comment_test.rb +12 -9
- data/test/unit/ping_test.rb +1 -1
- data/test/unit/trackback_test.rb +3 -5
- data/themes/azure/stylesheets/azure.css +7 -0
- data/themes/scribbish/views/articles/_article.rhtml +1 -1
- data/themes/scribbish/views/articles/_comment_form.rhtml +1 -1
- data/vendor/akismet/Akismet.rb +36 -17
- data/vendor/plugins/expiring_action_cache/lib/actionparamcache.rb +3 -1
- metadata +11 -42
- data/installer/rails-installer/web-server.rb +0 -108
- data/tmp/cache/META/DATA/ACTION_PARAM/10.1.0.181/articles/index/.cache +0 -537
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/articles/index/.cache +0 -537
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/xml/feed/format=atom&type=feed.cache +0 -671
- data/tmp/cache/META/DATA/ACTION_PARAM/localhost/xml/feed/format=rss20&type=feed.cache +0 -401
- data/tmp/cache/META/META/ACTION_PARAM/10.1.0.181/articles/index/.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/articles/index/.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/xml/feed/format=atom&type=feed.cache +0 -2
- data/tmp/cache/META/META/ACTION_PARAM/localhost/xml/feed/format=rss20&type=feed.cache +0 -2
data/README
CHANGED
@@ -24,45 +24,7 @@ Currently you need all of those things to get typo to run:
|
|
24
24
|
Installation
|
25
25
|
============
|
26
26
|
|
27
|
-
|
28
|
-
|
29
|
-
Decide which database to use. We support Sqlite, MySQL, and Postgres,
|
30
|
-
but Sqlite doesn't have full support for database migrations in Rails
|
31
|
-
0.13.1.
|
32
|
-
|
33
|
-
* Create a database for typo. You can find schemas in the db/ folder.
|
34
|
-
* Create config/database.yml using database.yml.example to reflect your
|
35
|
-
newly created database configuration
|
36
|
-
* Run script/server -e production and see if it works
|
37
|
-
* Point your browser to http://your.domain.com:3000/ and follow the
|
38
|
-
install process
|
39
|
-
|
40
|
-
Typo, like all Rails apps, doesn't work well as a CGI. Seriously consider
|
41
|
-
using FastCGI instead. To deploy on FastCGI you will need to follow the setup
|
42
|
-
instructions on the typo page at http://www.typosphere.org/trac/wiki/FastCgi
|
43
|
-
|
44
|
-
By default, Typo runs in *development* mode. This is very useful for
|
45
|
-
developers, but it can cause horrible performance for users who aren't
|
46
|
-
changing Typo's code. Production mode can easily be 20x as fast as development
|
47
|
-
mode. To change the default, edit the second line of config/environment.rb and
|
48
|
-
change 'development' to 'production', or follow the directions on the FastCGI
|
49
|
-
configuration page on the Typo wiki.
|
50
|
-
|
51
|
-
Permissions
|
52
|
-
===========
|
53
|
-
|
54
|
-
Typo needs write access to several directories in order to function
|
55
|
-
correctly. These need to be writable by the user that runs the Typo
|
56
|
-
process--in a hosted environment this may be your user; on dedicated
|
57
|
-
systems it may be something like 'httpd' or 'www-data'.
|
58
|
-
|
59
|
-
The specific directories in question are 'log/' (and everything underneath
|
60
|
-
it), 'cache/', and 'public/'. Strictly speaking, Rails will continue to work
|
61
|
-
if public isn't writable, but Typo's page caching code will work properly and
|
62
|
-
this will cause Typo to be slower and use much more CPU time. For the security
|
63
|
-
conscious, Rails really only needs the ability to change a half-dozen files
|
64
|
-
and subdirectories under public/, ask on the Typo mailing list for more
|
65
|
-
details.
|
27
|
+
See doc/Installer.text and doc/typo-4.0-release-notes.txt.
|
66
28
|
|
67
29
|
Usage
|
68
30
|
======
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class Admin::FeedbackController < Admin::BaseController
|
2
|
+
def index
|
3
|
+
conditions = ["(contents.type = 'Comment' or contents.type = 'Trackback')"]
|
4
|
+
|
5
|
+
if params[:search]
|
6
|
+
search_sql = "%#{params[:search]}%"
|
7
|
+
conditions.first << ' and (url like ? or author like ? or title like ? or ip like ? or email like ?)'
|
8
|
+
5.times { conditions.push search_sql }
|
9
|
+
end
|
10
|
+
|
11
|
+
if params[:published] == 'f'
|
12
|
+
conditions.first << ' and (published = ?)'
|
13
|
+
conditions.push false
|
14
|
+
end
|
15
|
+
|
16
|
+
@pages, @feedback = paginate(:contents,
|
17
|
+
:order => 'contents.created_at desc',
|
18
|
+
:conditions => conditions,
|
19
|
+
:per_page => 40)
|
20
|
+
|
21
|
+
render_action 'list'
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete
|
25
|
+
if request.post?
|
26
|
+
feedback = Content.find(params[:id])
|
27
|
+
if feedback.kind_of? Comment or feedback.kind_of? Trackback
|
28
|
+
feedback.destroy
|
29
|
+
flash[:notice] = "Deleted"
|
30
|
+
else
|
31
|
+
flash[:notice] = "Not found"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
redirect_to :action => 'index', :page => params[:page], :search => params[:search]
|
35
|
+
end
|
36
|
+
|
37
|
+
def bulkops
|
38
|
+
STDERR.puts "Bulkops: #{params.inspect}"
|
39
|
+
|
40
|
+
ids = (params[:feedback_check]||{}).keys.map(&:to_i)
|
41
|
+
|
42
|
+
case params[:commit]
|
43
|
+
when 'Delete Checked Items'
|
44
|
+
count = 0
|
45
|
+
ids.each do |id|
|
46
|
+
count += Content.delete(id)
|
47
|
+
end
|
48
|
+
flash[:notice] = "Deleted #{count} item(s)"
|
49
|
+
when 'Publish Checked Items'
|
50
|
+
ids.each do |id|
|
51
|
+
feedback = Content.find(id)
|
52
|
+
feedback.attributes[:published] = true
|
53
|
+
feedback.set_spam(false)
|
54
|
+
feedback.save
|
55
|
+
end
|
56
|
+
flash[:notice]= "Published #{ids.size} item(s)"
|
57
|
+
when 'Unpublish Checked Items'
|
58
|
+
ids.each do |id|
|
59
|
+
feedback = Content.find(id)
|
60
|
+
feedback.withdraw!
|
61
|
+
feedback.set_spam(true)
|
62
|
+
feedback.save
|
63
|
+
end
|
64
|
+
flash[:notice]= "Unpublished #{ids.size} item(s)"
|
65
|
+
else
|
66
|
+
flash[:notice] = "Not implemented"
|
67
|
+
end
|
68
|
+
|
69
|
+
redirect_to :action => 'index', :page => params[:page], :search => params[:search]
|
70
|
+
end
|
71
|
+
end
|
@@ -99,6 +99,17 @@ class ArticlesController < ContentController
|
|
99
99
|
@article = this_blog.published_articles.find(params[:id])
|
100
100
|
@comment = @article.comments.build(params[:comment])
|
101
101
|
@comment.user = session[:user]
|
102
|
+
|
103
|
+
spam_options = {
|
104
|
+
:user_agent => request.env['HTTP_USER_AGENT'],
|
105
|
+
:referrer => request.env['HTTP_REFERER'],
|
106
|
+
:permalink => this_blog.article_url(@article, false)}
|
107
|
+
|
108
|
+
if @comment.is_spam? spam_options
|
109
|
+
STDERR.puts "Moderating comment as spam!"
|
110
|
+
@comment.withdraw
|
111
|
+
end
|
112
|
+
|
102
113
|
@comment.save!
|
103
114
|
add_to_cookies(:author, @comment.author)
|
104
115
|
add_to_cookies(:url, @comment.url)
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Admin::FeedbackHelper
|
2
|
+
def link_to_article_edit(article)
|
3
|
+
link_to truncate(article.title, 60), :controller => 'content', :action => 'edit', :id => article.id
|
4
|
+
end
|
5
|
+
|
6
|
+
def task_showmod(title)
|
7
|
+
content_tag :li, link_to(title, :published => 'f', :search => params[:search])
|
8
|
+
end
|
9
|
+
end
|
@@ -93,6 +93,10 @@ module ApplicationHelper
|
|
93
93
|
end
|
94
94
|
|
95
95
|
def markup_help_popup(markup, text)
|
96
|
-
|
96
|
+
if markup and markup.commenthelp.size > 1
|
97
|
+
"<a href=\"#{url_for :controller => '/articles', :action => 'markup_help', :id => markup.id}\" onClick=\"return popup(this, 'Typo Markup Help')\">#{text}</a>"
|
98
|
+
else
|
99
|
+
''
|
100
|
+
end
|
97
101
|
end
|
98
102
|
end
|
data/app/models/article.rb
CHANGED
@@ -120,7 +120,7 @@ class Article < Content
|
|
120
120
|
def keywords_to_tags
|
121
121
|
Article.transaction do
|
122
122
|
tags.clear
|
123
|
-
keywords.to_s.scan(/((['"]).*?\2
|
123
|
+
keywords.to_s.scan(/((['"]).*?\2|[\.\w]+)/).collect do |x|
|
124
124
|
x.first.tr("\"'", '')
|
125
125
|
end.uniq.each do |tagword|
|
126
126
|
tags << Tag.get(tagword)
|
@@ -146,15 +146,34 @@ class Article < Content
|
|
146
146
|
end
|
147
147
|
end
|
148
148
|
|
149
|
+
def comments_closed?
|
150
|
+
if self.allow_comments?
|
151
|
+
if !self.blog.sp_article_auto_close.zero? and self.created_at.to_i < self.blog.sp_article_auto_close.days.ago.to_i
|
152
|
+
return true
|
153
|
+
else
|
154
|
+
return false
|
155
|
+
end
|
156
|
+
else
|
157
|
+
return true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
149
161
|
protected
|
150
162
|
|
151
163
|
before_create :set_defaults, :create_guid, :add_notifications
|
164
|
+
before_save :set_published_at
|
152
165
|
after_save :keywords_to_tags
|
153
166
|
|
154
167
|
def correct_counts
|
155
168
|
self.comments_count = self.comments_count
|
156
169
|
self.trackbacks_count = self.trackbacks_count
|
157
170
|
end
|
171
|
+
|
172
|
+
def set_published_at
|
173
|
+
if self.published and self[:published_at].nil?
|
174
|
+
self[:published_at] = self.created_at || Time.now
|
175
|
+
end
|
176
|
+
end
|
158
177
|
|
159
178
|
def set_defaults
|
160
179
|
if self.attributes.include?("permalink") and self.permalink.blank?
|
@@ -168,6 +187,7 @@ class Article < Content
|
|
168
187
|
if blog && self.allow_pings.nil?
|
169
188
|
self.allow_pings = blog.default_allow_pings
|
170
189
|
end
|
190
|
+
|
171
191
|
true
|
172
192
|
end
|
173
193
|
|
data/app/models/blog.rb
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
# BlogRequest is a fake Request object, created so blog.url_for will work.
|
2
|
+
# This isn't enabled yet, but it will be soon...
|
3
|
+
class BlogRequest
|
4
|
+
include Reloadable
|
5
|
+
|
6
|
+
attr_accessor :protocol, :host_with_port, :path, :symbolized_path_parameters, :relative_url_root
|
7
|
+
|
8
|
+
def initialize(root)
|
9
|
+
@protocol = @host_with_port = @path = ''
|
10
|
+
@symbolized_path_parameters = {}
|
11
|
+
@relative_url_root = root.gsub(%r{/^},'')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
1
15
|
class Blog < ActiveRecord::Base
|
2
16
|
include ConfigManager
|
3
17
|
|
@@ -31,6 +45,7 @@ class Blog < ActiveRecord::Base
|
|
31
45
|
setting :sp_article_auto_close, :integer, 0
|
32
46
|
setting :sp_allow_non_ajax_comments, :boolean, true
|
33
47
|
setting :sp_url_limit, :integer, 0
|
48
|
+
setting :sp_akismet_key, :string, ''
|
34
49
|
|
35
50
|
# Podcasting
|
36
51
|
setting :itunes_explicit, :boolean, false
|
@@ -53,6 +68,7 @@ class Blog < ActiveRecord::Base
|
|
53
68
|
setting :show_extended_on_rss, :boolean, true
|
54
69
|
setting :theme, :string, 'azure'
|
55
70
|
setting :use_gravatar, :boolean, false
|
71
|
+
setting :global_pings_disable, :boolean, false
|
56
72
|
setting :ping_urls, :string, "http://rpc.technorati.com/rpc/ping\nhttp://ping.blo.gs/\nhttp://rpc.weblogs.com/RPC2"
|
57
73
|
setting :send_outbound_pings, :boolean, true
|
58
74
|
setting :email_from, :string, 'typo@example.com'
|
@@ -69,7 +85,14 @@ class Blog < ActiveRecord::Base
|
|
69
85
|
settings[:blog_id] = self.id
|
70
86
|
article_id = settings[:id]
|
71
87
|
settings.delete(:id)
|
72
|
-
published_articles.find(article_id).trackbacks.create!(settings)
|
88
|
+
trackback = published_articles.find(article_id).trackbacks.create!(settings)
|
89
|
+
|
90
|
+
if trackback.is_spam?
|
91
|
+
STDERR.puts "Moderating trackback as spam!"
|
92
|
+
trackback.withdraw!
|
93
|
+
end
|
94
|
+
|
95
|
+
trackback
|
73
96
|
end
|
74
97
|
|
75
98
|
|
@@ -156,6 +179,7 @@ class Blog < ActiveRecord::Base
|
|
156
179
|
private
|
157
180
|
|
158
181
|
def request
|
182
|
+
#BlogRequest.new(self.canonical_server_url)
|
159
183
|
controller.request rescue ActionController::TestRequest.new
|
160
184
|
end
|
161
185
|
end
|
data/app/models/comment.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require_dependency 'spam_protection'
|
2
2
|
require 'sanitize'
|
3
|
+
require 'timeout'
|
3
4
|
|
4
5
|
class Comment < Content
|
5
6
|
include TypoGuid
|
@@ -10,10 +11,10 @@ class Comment < Content
|
|
10
11
|
belongs_to :user
|
11
12
|
|
12
13
|
validates_presence_of :author, :body
|
13
|
-
validates_against_spamdb :body, :url, :ip
|
14
14
|
validates_age_of :article_id
|
15
15
|
validate_on_create :check_article_is_open_to_comments
|
16
16
|
|
17
|
+
|
17
18
|
def self.default_order
|
18
19
|
'created_at ASC'
|
19
20
|
end
|
@@ -50,7 +51,7 @@ class Comment < Content
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def body_html_postprocess(value, controller)
|
53
|
-
sanitize(controller.send(:auto_link, value),'a href, b, br, i, p, em, strong, pre, code')
|
54
|
+
sanitize(controller.send(:auto_link, value),'a href, b, br, i, p, em, strong, pre, code, ol, ul, li')
|
54
55
|
end
|
55
56
|
|
56
57
|
def default_text_filter_config_key
|
@@ -72,4 +73,13 @@ class Comment < Content
|
|
72
73
|
self.author = author.nofollowify
|
73
74
|
self.body_html = body_html.to_s.nofollowify
|
74
75
|
end
|
76
|
+
|
77
|
+
def akismet_options
|
78
|
+
{:user_ip => ip, :comment_type => 'comment', :comment_author => author, :comment_author_email => email,
|
79
|
+
:comment_author_url => url, :comment_content => body}
|
80
|
+
end
|
81
|
+
|
82
|
+
def spam_fields
|
83
|
+
[:body, :url, :ip]
|
84
|
+
end
|
75
85
|
end
|
data/app/models/content.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'observer'
|
2
2
|
require 'set'
|
3
|
+
require 'Akismet'
|
4
|
+
|
3
5
|
class Content < ActiveRecord::Base
|
4
6
|
include Observable
|
5
7
|
|
@@ -20,11 +22,11 @@ class Content < ActiveRecord::Base
|
|
20
22
|
|
21
23
|
@@content_fields = Hash.new
|
22
24
|
@@html_map = Hash.new
|
23
|
-
|
25
|
+
|
24
26
|
def initialize(*args)
|
25
27
|
super(*args)
|
26
|
-
|
27
|
-
#
|
28
|
+
|
29
|
+
#
|
28
30
|
if self.blog_id == nil or self.blog_id == 0
|
29
31
|
self.blog_id = Blog.default
|
30
32
|
end
|
@@ -170,7 +172,7 @@ class Content < ActiveRecord::Base
|
|
170
172
|
end
|
171
173
|
|
172
174
|
def text_filter=(filter)
|
173
|
-
self[:
|
175
|
+
self[:text_filter_id] = filter.to_text_filter.id
|
174
176
|
end
|
175
177
|
|
176
178
|
def blog
|
@@ -182,6 +184,16 @@ class Content < ActiveRecord::Base
|
|
182
184
|
self.save!
|
183
185
|
end
|
184
186
|
|
187
|
+
def withdraw
|
188
|
+
self.published = false
|
189
|
+
self.published_at = nil
|
190
|
+
end
|
191
|
+
|
192
|
+
def withdraw!
|
193
|
+
self.withdraw
|
194
|
+
self.save!
|
195
|
+
end
|
196
|
+
|
185
197
|
def published=(a_boolean)
|
186
198
|
self[:published] = a_boolean
|
187
199
|
state.change_published_state(self, a_boolean)
|
@@ -219,6 +231,53 @@ class Content < ActiveRecord::Base
|
|
219
231
|
def send_notifications(controller = nil)
|
220
232
|
state.send_notifications(self, controller || blog.controller)
|
221
233
|
end
|
234
|
+
|
235
|
+
# is_spam? checks to see if this is spam. This really belongs in a 'feedback' class
|
236
|
+
# that is the parent of Comment and Trackback, but we aren't going to build one right
|
237
|
+
# now.
|
238
|
+
#
|
239
|
+
# options are passed on to Akismet. Recommended options (when available) are:
|
240
|
+
#
|
241
|
+
# :permalink => the article's URL
|
242
|
+
# :user_agent => the poster's UserAgent string
|
243
|
+
# :referer => the poster's Referer string
|
244
|
+
#
|
245
|
+
def is_spam?(options={})
|
246
|
+
return false unless blog.sp_global
|
247
|
+
|
248
|
+
sp = SpamProtection.new(blog)
|
249
|
+
spam = false
|
250
|
+
|
251
|
+
# Check fields against the blacklist.
|
252
|
+
spam_fields.each do |field|
|
253
|
+
spam ||= sp.is_spam? self[field]
|
254
|
+
end
|
255
|
+
|
256
|
+
# Attempt to use Akismet. Timeout after 5 seconds if we can't contact them.
|
257
|
+
unless blog.sp_akismet_key.blank?
|
258
|
+
Timeout.timeout(5) do
|
259
|
+
akismet = Akismet.new(blog.sp_akismet_key,blog.canonical_server_url)
|
260
|
+
spam ||= akismet.commentCheck(akismet_options.merge(options))
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
spam == true
|
265
|
+
end
|
266
|
+
|
267
|
+
def set_spam(is_spam, options ={})
|
268
|
+
unless blog.sp_akismet_key.blank?
|
269
|
+
Timeout.timeout(5) do
|
270
|
+
akismet = Akismet.new(blog.sp_akismet_key,blog.canonical_server_url)
|
271
|
+
if is_spam
|
272
|
+
STDERR.puts "** submitting spam for #{id}"
|
273
|
+
akismet.submitSpam(akismet_options.merge(options))
|
274
|
+
else
|
275
|
+
STDERR.puts "** submitting ham for #{id}"
|
276
|
+
akismet.submitHam(akismet_options.merge(options))
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
222
281
|
end
|
223
282
|
|
224
283
|
class Object; def to_text_filter; TextFilter.find_by_name(self.to_s); end; end
|
data/app/models/ping.rb
CHANGED
@@ -97,10 +97,10 @@ class Ping < ActiveRecord::Base
|
|
97
97
|
t = Thread.start do
|
98
98
|
trackback_uri = URI.parse(trackback_url)
|
99
99
|
|
100
|
-
post = "title=#{
|
101
|
-
post << "&excerpt=#{
|
100
|
+
post = "title=#{CGI.escape(article.title)}"
|
101
|
+
post << "&excerpt=#{CGI.escape(article.body_html.strip_html[0..254])}"
|
102
102
|
post << "&url=#{origin_url}"
|
103
|
-
post << "&blog_name=#{
|
103
|
+
post << "&blog_name=#{CGI.escape(article.blog.blog_name)}"
|
104
104
|
|
105
105
|
Net::HTTP.start(trackback_uri.host, trackback_uri.port) do |http|
|
106
106
|
path = trackback_uri.path
|
data/app/models/text_filter.rb
CHANGED
data/app/models/trackback.rb
CHANGED
@@ -7,7 +7,6 @@ class Trackback < Content
|
|
7
7
|
content_fields :excerpt
|
8
8
|
|
9
9
|
validates_age_of :article_id
|
10
|
-
validates_against_spamdb :title, :excerpt, :ip, :url
|
11
10
|
validates_presence_of :title, :excerpt, :url
|
12
11
|
validate_on_create :article_is_pingable
|
13
12
|
|
@@ -43,9 +42,21 @@ class Trackback < Content
|
|
43
42
|
|
44
43
|
def article_is_pingable
|
45
44
|
return if article.nil?
|
45
|
+
if blog.global_pings_disable
|
46
|
+
errors.add(:article, "Pings are disabled")
|
47
|
+
end
|
46
48
|
unless article.allow_pings?
|
47
49
|
errors.add(:article, "Article is not pingable")
|
48
50
|
end
|
49
51
|
end
|
52
|
+
|
53
|
+
def akismet_options
|
54
|
+
{:user_ip => ip, :comment_type => 'trackback', :comment_author => blog_name, :comment_author_email => nil,
|
55
|
+
:comment_author_url => url, :comment_content => excerpt}
|
56
|
+
end
|
57
|
+
|
58
|
+
def spam_fields
|
59
|
+
[:title, :excerpt, :ip, :url]
|
60
|
+
end
|
50
61
|
end
|
51
62
|
|