radiant-comments-extension 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/CHANGELOG +40 -0
- data/HELP_admin.markdown +52 -0
- data/HELP_designer.markdown +36 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +53 -0
- data/Rakefile +133 -0
- data/TODO +6 -0
- data/VERSION +1 -0
- data/app/controllers/admin/comments_controller.rb +130 -0
- data/app/controllers/comments_controller.rb +59 -0
- data/app/helpers/admin/comments_helper.rb +7 -0
- data/app/models/akismet_spam_filter.rb +37 -0
- data/app/models/comment.rb +121 -0
- data/app/models/comment_mailer.rb +24 -0
- data/app/models/mollom_spam_filter.rb +52 -0
- data/app/models/simple_spam_filter.rb +38 -0
- data/app/models/spam_filter.rb +43 -0
- data/app/views/admin/comments/_comment.rhtml +34 -0
- data/app/views/admin/comments/_form.rhtml +36 -0
- data/app/views/admin/comments/edit.rhtml +5 -0
- data/app/views/admin/comments/index.rhtml +55 -0
- data/app/views/admin/pages/_comments.rhtml +0 -0
- data/app/views/admin/pages/_edit_comments_enabled.rhtml +8 -0
- data/app/views/admin/pages/_index_head_view_comments.rhtml +1 -0
- data/app/views/admin/pages/_index_view_comments.rhtml +11 -0
- data/app/views/comment_mailer/comment_notification.rhtml +21 -0
- data/app/views/comments/_comment.rhtml +1 -0
- data/app/views/comments/_form.rhtml +23 -0
- data/app/views/comments/_new.rhtml +5 -0
- data/autotest/discover.rb +3 -0
- data/comments_extension.rb +81 -0
- data/cucumber.yml +1 -0
- data/db/migrate/001_create_comments.rb +29 -0
- data/db/migrate/002_create_snippets.rb +115 -0
- data/db/migrate/003_change_filter_id_from_integer_to_string.rb +10 -0
- data/db/migrate/004_add_approval_columns.rb +13 -0
- data/db/migrate/005_add_mollomid_column.rb +11 -0
- data/db/migrate/006_move_config_to_migrations.rb +22 -0
- data/db/migrate/007_add_preference_for_simple_spamcheck.rb +12 -0
- data/features/support/env.rb +16 -0
- data/features/support/paths.rb +16 -0
- data/lib/akismet.rb +134 -0
- data/lib/comment_page_extensions.rb +41 -0
- data/lib/comment_tags.rb +338 -0
- data/lib/mollom.rb +246 -0
- data/lib/radiant-comments-extension.rb +0 -0
- data/lib/tasks/comments_extension_tasks.rake +68 -0
- data/public/images/admin/accept.png +0 -0
- data/public/images/admin/comment_edit.png +0 -0
- data/public/images/admin/comments.png +0 -0
- data/public/images/admin/comments_delete.png +0 -0
- data/public/images/admin/delete.png +0 -0
- data/public/images/admin/email.png +0 -0
- data/public/images/admin/error.png +0 -0
- data/public/images/admin/link.png +0 -0
- data/public/images/admin/page_white_edit.png +0 -0
- data/public/images/admin/table_save.png +0 -0
- data/public/images/admin/tick.png +0 -0
- data/public/stylesheets/admin/comments.css +41 -0
- data/radiant-comments-extension.gemspec +133 -0
- data/spec/controllers/admin/comments_controller_spec.rb +57 -0
- data/spec/controllers/admin/comments_routing_spec.rb +43 -0
- data/spec/controllers/page_postback_spec.rb +51 -0
- data/spec/datasets/comments_dataset.rb +7 -0
- data/spec/models/akismet_spam_filter_spec.rb +61 -0
- data/spec/models/comment_spec.rb +148 -0
- data/spec/models/comment_tags_spec.rb +55 -0
- data/spec/models/mollom_spam_filter_spec.rb +103 -0
- data/spec/models/simple_spam_filter_spec.rb +44 -0
- data/spec/models/spam_filter_spec.rb +38 -0
- data/spec/spec.opts +6 -0
- data/spec/spec_helper.rb +36 -0
- data/test/fixtures/users.yml +6 -0
- data/test/integration/comment_enabling_test.rb +18 -0
- data/test/test_helper.rb +24 -0
- data/test/unit/comment_test.rb +52 -0
- metadata +177 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
class AddPreferenceForSimpleSpamcheck < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
if Radiant::Config['comments.simple_spam_filter_required?'].blank?
|
4
|
+
Radiant::Config.create(:key => 'comments.simple_spam_filter_required?', :value => true)
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.down
|
9
|
+
# not necessary
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Sets up the Rails environment for Cucumber
|
2
|
+
ENV["RAILS_ENV"] = "test"
|
3
|
+
# Extension root
|
4
|
+
extension_env = File.expand_path(File.dirname(__FILE__) + '/../../../../../config/environment')
|
5
|
+
require extension_env+'.rb'
|
6
|
+
|
7
|
+
Dir.glob(File.join(RADIANT_ROOT, "features", "**", "*.rb")).each {|step| require step}
|
8
|
+
|
9
|
+
Cucumber::Rails::World.class_eval do
|
10
|
+
include Dataset
|
11
|
+
datasets_directory "#{RADIANT_ROOT}/spec/datasets"
|
12
|
+
Dataset::Resolver.default = Dataset::DirectoryResolver.new("#{RADIANT_ROOT}/spec/datasets", File.dirname(__FILE__) + '/../../spec/datasets', File.dirname(__FILE__) + '/../datasets')
|
13
|
+
self.datasets_database_dump_path = "#{Rails.root}/tmp/dataset"
|
14
|
+
|
15
|
+
# dataset :comments
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
def path_to(page_name)
|
2
|
+
case page_name
|
3
|
+
|
4
|
+
when /the homepage/i
|
5
|
+
root_path
|
6
|
+
|
7
|
+
when /login/i
|
8
|
+
login_path
|
9
|
+
|
10
|
+
when /comments/i
|
11
|
+
admin_comments_path
|
12
|
+
# Add more page name => path mappings here
|
13
|
+
else
|
14
|
+
raise "Can't find mapping from \"#{page_name}\" to a path."
|
15
|
+
end
|
16
|
+
end
|
data/lib/akismet.rb
ADDED
@@ -0,0 +1,134 @@
|
|
1
|
+
# Akismet
|
2
|
+
#
|
3
|
+
# Author:: David Czarnecki
|
4
|
+
# Copyright:: Copyright (c) 2005 - David Czarnecki
|
5
|
+
# License:: BSD
|
6
|
+
# Modified by Dieter Komendera, Sparkling Studios:
|
7
|
+
# append blog= to data string (Akismet said it is required)
|
8
|
+
# changed require 'net/HTTP' to require 'net/http' (to work for me unter GNU/Linux)
|
9
|
+
# Akismet Key - 4ebc7e35c512
|
10
|
+
class Akismet
|
11
|
+
|
12
|
+
require 'net/http'
|
13
|
+
require 'uri'
|
14
|
+
|
15
|
+
STANDARD_HEADERS = {
|
16
|
+
'User-Agent' => 'Akismet Ruby API/1.0',
|
17
|
+
'Content-Type' => 'application/x-www-form-urlencoded'
|
18
|
+
}
|
19
|
+
|
20
|
+
# Create a new instance of the Akismet class
|
21
|
+
#
|
22
|
+
# apiKey
|
23
|
+
# Your Akismet API key
|
24
|
+
# blog
|
25
|
+
# The blog associated with your api key
|
26
|
+
def initialize(apiKey, blog)
|
27
|
+
@apiKey = apiKey
|
28
|
+
@blog = blog
|
29
|
+
end
|
30
|
+
|
31
|
+
# Set proxy information
|
32
|
+
#
|
33
|
+
# proxyHost
|
34
|
+
# Hostname for the proxy to use
|
35
|
+
# proxyPort
|
36
|
+
# Port for the proxy
|
37
|
+
def setProxy(proxyHost, proxyPort)
|
38
|
+
@proxyPort = proxyPort
|
39
|
+
@proxyHost = proxyHost
|
40
|
+
end
|
41
|
+
|
42
|
+
def valid?
|
43
|
+
(!@apiKey.blank? && !@blog.blank? && verifyAPIKey)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Call to check and verify your API key.
|
47
|
+
def verifyAPIKey
|
48
|
+
http = Net::HTTP.new('rest.akismet.com', 80, @proxyHost, @proxyPort)
|
49
|
+
path = '/1.1/verify-key'
|
50
|
+
|
51
|
+
data="key=#{@apiKey}&blog=#{@blog}"
|
52
|
+
|
53
|
+
resp, data = http.post(path, data, STANDARD_HEADERS)
|
54
|
+
(data == "valid")
|
55
|
+
end
|
56
|
+
|
57
|
+
# Internal call to Akismet. Prepares the data for posting to the Akismet service.
|
58
|
+
#
|
59
|
+
# akismet_function
|
60
|
+
# The Akismet function that should be called
|
61
|
+
# user_ip (required)
|
62
|
+
# IP address of the comment submitter.
|
63
|
+
# user_agent (required)
|
64
|
+
# User agent information.
|
65
|
+
# referrer (note spelling)
|
66
|
+
# The content of the HTTP_REFERER header should be sent here.
|
67
|
+
# permalink
|
68
|
+
# The permanent location of the entry the comment was submitted to.
|
69
|
+
# comment_type
|
70
|
+
# May be blank, comment, trackback, pingback, or a made up value like "registration".
|
71
|
+
# comment_author
|
72
|
+
# Submitted name with the comment
|
73
|
+
# comment_author_email
|
74
|
+
# Submitted email address
|
75
|
+
# comment_author_url
|
76
|
+
# Commenter URL.
|
77
|
+
# comment_content
|
78
|
+
# The content that was submitted.
|
79
|
+
# Other server enviroment variables
|
80
|
+
# In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
|
81
|
+
def callAkismet(akismet_function, user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
82
|
+
http = Net::HTTP.new("#{@apiKey}.rest.akismet.com", 80, @proxyHost, @proxyPort)
|
83
|
+
path = "/1.1/#{akismet_function}"
|
84
|
+
|
85
|
+
data = "blog=#{@blog}&user_ip=#{user_ip}&user_agent=#{user_agent}&referrer=#{referrer}&permalink=#{permalink}&comment_type=#{comment_type}&comment_author=#{comment_author}&comment_author_email=#{comment_author_email}&comment_author_url=#{comment_author_url}&comment_content=#{comment_content}"
|
86
|
+
if (other != nil)
|
87
|
+
other.each_pair {|key, value| data.concat("&#{key}=#{value}")}
|
88
|
+
end
|
89
|
+
|
90
|
+
resp, data = http.post(path, data, STANDARD_HEADERS)
|
91
|
+
|
92
|
+
return (data != "false")
|
93
|
+
end
|
94
|
+
|
95
|
+
protected :callAkismet
|
96
|
+
|
97
|
+
# This is basically the core of everything. This call takes a number of arguments and characteristics about the submitted content and then returns a thumbs up or thumbs down. Almost everything is optional, but performance can drop dramatically if you exclude certain elements.
|
98
|
+
#
|
99
|
+
# user_ip (required)
|
100
|
+
# IP address of the comment submitter.
|
101
|
+
# user_agent (required)
|
102
|
+
# User agent information.
|
103
|
+
# referrer (note spelling)
|
104
|
+
# The content of the HTTP_REFERER header should be sent here.
|
105
|
+
# permalink
|
106
|
+
# The permanent location of the entry the comment was submitted to.
|
107
|
+
# comment_type
|
108
|
+
# May be blank, comment, trackback, pingback, or a made up value like "registration".
|
109
|
+
# comment_author
|
110
|
+
# Submitted name with the comment
|
111
|
+
# comment_author_email
|
112
|
+
# Submitted email address
|
113
|
+
# comment_author_url
|
114
|
+
# Commenter URL.
|
115
|
+
# comment_content
|
116
|
+
# The content that was submitted.
|
117
|
+
# Other server enviroment variables
|
118
|
+
# In PHP there is an array of enviroment variables called $_SERVER which contains information about the web server itself as well as a key/value for every HTTP header sent with the request. This data is highly useful to Akismet as how the submited content interacts with the server can be very telling, so please include as much information as possible.
|
119
|
+
def commentCheck(user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
120
|
+
return callAkismet('comment-check', user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
121
|
+
end
|
122
|
+
|
123
|
+
# This call is for submitting comments that weren't marked as spam but should have been. It takes identical arguments as comment check.
|
124
|
+
# The call parameters are the same as for the #commentCheck method.
|
125
|
+
def submitSpam(user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
126
|
+
callAkismet('submit-spam', user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
127
|
+
end
|
128
|
+
|
129
|
+
# This call is intended for the marking of false positives, things that were incorrectly marked as spam. It takes identical arguments as comment check and submit spam.
|
130
|
+
# The call parameters are the same as for the #commentCheck method.
|
131
|
+
def submitHam(user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
132
|
+
callAkismet('submit-ham', user_ip, user_agent, referrer, permalink, comment_type, comment_author, comment_author_email, comment_author_url, comment_content, other)
|
133
|
+
end
|
134
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module CommentPageExtensions
|
2
|
+
def self.included(base)
|
3
|
+
base.class_eval do
|
4
|
+
alias_method_chain :process, :comments
|
5
|
+
|
6
|
+
has_many :comments, :dependent => :delete_all, :order => "created_at ASC"
|
7
|
+
attr_accessor :last_comment
|
8
|
+
attr_accessor :selected_comment
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def has_visible_comments?
|
13
|
+
!(comments.approved.empty? && selected_comment.nil?)
|
14
|
+
end
|
15
|
+
|
16
|
+
def process_with_comments(request, response)
|
17
|
+
if Radiant::Config['comments.post_to_page?'] && request.post? && request.parameters[:comment]
|
18
|
+
begin
|
19
|
+
comment = self.comments.build(request.parameters[:comment])
|
20
|
+
comment.request = self.request = request
|
21
|
+
comment.save!
|
22
|
+
|
23
|
+
if Radiant::Config['comments.notification'] == "true"
|
24
|
+
if comment.approved? || Radiant::Config['comments.notify_unapproved'] == "true"
|
25
|
+
CommentMailer.deliver_comment_notification(comment)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
if comment.approved?
|
29
|
+
absolute_url = "#{request.protocol}#{request.host_with_port}#{relative_url_for(url, request)}#comment-#{comment.id}"
|
30
|
+
response.redirect(absolute_url, 303)
|
31
|
+
return
|
32
|
+
else
|
33
|
+
self.selected_comment = comment
|
34
|
+
end
|
35
|
+
rescue ActiveRecord::RecordInvalid
|
36
|
+
self.last_comment = comment
|
37
|
+
end
|
38
|
+
end
|
39
|
+
process_without_comments(request, response)
|
40
|
+
end
|
41
|
+
end
|
data/lib/comment_tags.rb
ADDED
@@ -0,0 +1,338 @@
|
|
1
|
+
module CommentTags
|
2
|
+
include Radiant::Taggable
|
3
|
+
|
4
|
+
desc "Provides tags and behaviors to support comments in Radiant."
|
5
|
+
|
6
|
+
desc %{
|
7
|
+
Renders the contained elements if comments are enabled on the page.
|
8
|
+
}
|
9
|
+
tag "if_enable_comments" do |tag|
|
10
|
+
tag.expand if (tag.locals.page.enable_comments?)
|
11
|
+
end
|
12
|
+
# makes more sense to me
|
13
|
+
tag "if_comments_enabled" do |tag|
|
14
|
+
tag.expand if (tag.locals.page.enable_comments?)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc %{
|
18
|
+
Renders the contained elements unless comments are enabled on the page.
|
19
|
+
}
|
20
|
+
tag "unless_enable_comments" do |tag|
|
21
|
+
tag.expand unless (tag.locals.page.enable_comments?)
|
22
|
+
end
|
23
|
+
|
24
|
+
# makes more sense to me
|
25
|
+
tag "unless_comments_enabled" do |tag|
|
26
|
+
tag.expand unless (tag.locals.page.enable_comments?)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc %{
|
30
|
+
Renders the contained elements if the page has comments.
|
31
|
+
}
|
32
|
+
tag "if_comments" do |tag|
|
33
|
+
tag.expand if tag.locals.page.has_visible_comments?
|
34
|
+
end
|
35
|
+
|
36
|
+
desc %{
|
37
|
+
Renders the contained elements unless the page has comments.
|
38
|
+
}
|
39
|
+
tag "unless_comments" do |tag|
|
40
|
+
tag.expand unless tag.locals.page.has_visible_comments?
|
41
|
+
end
|
42
|
+
|
43
|
+
desc %{
|
44
|
+
Renders the contained elements if the page has comments _or_ comment is enabled on it.
|
45
|
+
}
|
46
|
+
tag "if_comments_or_enable_comments" do |tag|
|
47
|
+
tag.expand if(tag.locals.page.has_visible_comments? || tag.locals.page.enable_comments?)
|
48
|
+
end
|
49
|
+
|
50
|
+
desc %{
|
51
|
+
Gives access to comment-related tags
|
52
|
+
}
|
53
|
+
tag "comments" do |tag|
|
54
|
+
comments = tag.locals.page.comments.approved
|
55
|
+
tag.expand
|
56
|
+
end
|
57
|
+
|
58
|
+
desc %{
|
59
|
+
Cycles through each comment and renders the enclosed tags for each.
|
60
|
+
}
|
61
|
+
tag "comments:each" do |tag|
|
62
|
+
page = tag.locals.page
|
63
|
+
comments = page.comments.approved.to_a
|
64
|
+
comments << page.selected_comment if page.selected_comment && page.selected_comment.unapproved?
|
65
|
+
result = []
|
66
|
+
comments.each_with_index do |comment, index|
|
67
|
+
tag.locals.comment = comment
|
68
|
+
tag.locals.index = index
|
69
|
+
result << tag.expand
|
70
|
+
end
|
71
|
+
result
|
72
|
+
end
|
73
|
+
|
74
|
+
desc %{
|
75
|
+
Gives access to the particular fields for each comment.
|
76
|
+
}
|
77
|
+
tag "comments:field" do |tag|
|
78
|
+
tag.expand
|
79
|
+
end
|
80
|
+
|
81
|
+
desc %{
|
82
|
+
Renders the index number for this comment.
|
83
|
+
}
|
84
|
+
tag 'comments:field:index' do |tag|
|
85
|
+
tag.locals.index + 1
|
86
|
+
end
|
87
|
+
|
88
|
+
%w(id author author_email author_url content content_html filter_id).each do |field|
|
89
|
+
desc %{ Print the value of the #{field} field for this comment. }
|
90
|
+
tag "comments:field:#{field}" do |tag|
|
91
|
+
options = tag.attr.dup
|
92
|
+
#options.inspect
|
93
|
+
value = tag.locals.comment.send(field)
|
94
|
+
value
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
desc %{
|
99
|
+
Renders the date a comment was created.
|
100
|
+
|
101
|
+
*Usage:*
|
102
|
+
<pre><code><r:date [format="%A, %B %d, %Y"] /></code></pre>
|
103
|
+
}
|
104
|
+
tag 'comments:field:date' do |tag|
|
105
|
+
comment = tag.locals.comment
|
106
|
+
format = (tag.attr['format'] || '%A, %B %d, %Y')
|
107
|
+
date = comment.created_at
|
108
|
+
date.strftime(format)
|
109
|
+
end
|
110
|
+
|
111
|
+
desc %{
|
112
|
+
Renders a link if there's an author_url, otherwise just the author's name.
|
113
|
+
}
|
114
|
+
tag "comments:field:author_link" do |tag|
|
115
|
+
if tag.locals.comment.author_url.blank?
|
116
|
+
tag.locals.comment.author
|
117
|
+
else
|
118
|
+
%(<a href="#{tag.locals.comment.author_url}">#{tag.locals.comment.author}</a>)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
desc %{
|
123
|
+
Renders the contained elements if the comment has an author_url specified.
|
124
|
+
}
|
125
|
+
tag "comments:field:if_author_url" do |tag|
|
126
|
+
tag.expand unless tag.locals.comment.author_url.blank?
|
127
|
+
end
|
128
|
+
|
129
|
+
desc %{
|
130
|
+
Renders the contained elements if the comment is selected - that is, if it is a comment
|
131
|
+
the user has just posted
|
132
|
+
}
|
133
|
+
tag "comments:field:if_selected" do |tag|
|
134
|
+
tag.expand if tag.locals.comment == tag.locals.page.selected_comment
|
135
|
+
end
|
136
|
+
|
137
|
+
desc %{
|
138
|
+
Renders the contained elements if the comment has been approved
|
139
|
+
}
|
140
|
+
tag "comments:field:if_approved" do |tag|
|
141
|
+
tag.expand if tag.locals.comment.approved?
|
142
|
+
end
|
143
|
+
|
144
|
+
desc %{
|
145
|
+
Renders the contained elements if the comment has not been approved
|
146
|
+
}
|
147
|
+
tag "comments:field:unless_approved" do |tag|
|
148
|
+
tag.expand unless tag.locals.comment.approved?
|
149
|
+
end
|
150
|
+
|
151
|
+
desc %{
|
152
|
+
Renders a Gravatar URL for the author of the comment.
|
153
|
+
}
|
154
|
+
tag "comments:field:gravatar_url" do |tag|
|
155
|
+
email = tag.locals.comment.author_email
|
156
|
+
size = tag.attr['size']
|
157
|
+
format = tag.attr['format']
|
158
|
+
rating = tag.attr['rating']
|
159
|
+
default = tag.attr['default']
|
160
|
+
md5 = Digest::MD5.hexdigest(email)
|
161
|
+
returning "http://www.gravatar.com/avatar/#{md5}" do |url|
|
162
|
+
url << ".#{format.downcase}" if format
|
163
|
+
if size || rating || default
|
164
|
+
attrs = []
|
165
|
+
attrs << "s=#{size}" if size
|
166
|
+
attrs << "d=#{default}" if default
|
167
|
+
attrs << "r=#{rating.downcase}" if rating
|
168
|
+
url << "?#{attrs.join('&')}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
desc %{
|
174
|
+
Renders a comment form.
|
175
|
+
|
176
|
+
*Usage:*
|
177
|
+
<r:comment:form [class="comments" id="comment_form"]>...</r:comment:form>
|
178
|
+
}
|
179
|
+
tag "comments:form" do |tag|
|
180
|
+
attrs = tag.attr.symbolize_keys
|
181
|
+
html_class, html_id = attrs[:class], attrs[:id]
|
182
|
+
r = %Q{ <form action="#{tag.locals.page.url}#{'comments' unless Radiant::Config['comments.post_to_page?']}}
|
183
|
+
r << %Q{##{html_id}} unless html_id.blank?
|
184
|
+
r << %{" method="post" } #comlpete the quotes for the action
|
185
|
+
r << %{ id="#{html_id}" } unless html_id.blank?
|
186
|
+
r << %{ class="#{html_class}" } unless html_class.blank?
|
187
|
+
r << '>' #close the form element
|
188
|
+
r << tag.expand
|
189
|
+
r << %{</form>}
|
190
|
+
r
|
191
|
+
end
|
192
|
+
|
193
|
+
tag 'comments:error' do |tag|
|
194
|
+
if comment = tag.locals.page.last_comment
|
195
|
+
if on = tag.attr['on']
|
196
|
+
if error = comment.errors.on(on)
|
197
|
+
tag.locals.error_message = error
|
198
|
+
tag.expand
|
199
|
+
end
|
200
|
+
else
|
201
|
+
tag.expand if !comment.valid?
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
tag 'comments:error:message' do |tag|
|
207
|
+
tag.locals.error_message
|
208
|
+
end
|
209
|
+
|
210
|
+
%w(text password hidden).each do |type|
|
211
|
+
desc %{Builds a #{type} form field for comments.}
|
212
|
+
tag "comments:#{type}_field_tag" do |tag|
|
213
|
+
attrs = tag.attr.symbolize_keys
|
214
|
+
r = %{<input type="#{type}"}
|
215
|
+
r << %{ id="comment_#{attrs[:name]}"}
|
216
|
+
r << %{ name="comment[#{attrs[:name]}]"}
|
217
|
+
r << %{ class="#{attrs[:class]}"} if attrs[:class]
|
218
|
+
if value = (tag.locals.page.last_comment ? tag.locals.page.last_comment.send(attrs[:name]) : attrs[:value])
|
219
|
+
r << %{ value="#{value}" }
|
220
|
+
end
|
221
|
+
r << %{ />}
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
%w(submit reset).each do |type|
|
226
|
+
desc %{Builds a #{type} form button for comments.}
|
227
|
+
tag "comments:#{type}_tag" do |tag|
|
228
|
+
attrs = tag.attr.symbolize_keys
|
229
|
+
r = %{<input type="#{type}"}
|
230
|
+
r << %{ id="#{attrs[:name]}"}
|
231
|
+
r << %{ name="#{attrs[:name]}"}
|
232
|
+
r << %{ class="#{attrs[:class]}"} if attrs[:class]
|
233
|
+
r << %{ value="#{attrs[:value]}" } if attrs[:value]
|
234
|
+
r << %{ />}
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
desc %{Builds a text_area form field for comments.}
|
239
|
+
tag "comments:text_area_tag" do |tag|
|
240
|
+
attrs = tag.attr.symbolize_keys
|
241
|
+
r = %{<textarea}
|
242
|
+
r << %{ id="comment_#{attrs[:name]}"}
|
243
|
+
r << %{ name="comment[#{attrs[:name]}]"}
|
244
|
+
r << %{ class="#{attrs[:class]}"} if attrs[:class]
|
245
|
+
r << %{ rows="#{attrs[:rows]}"} if attrs[:rows]
|
246
|
+
r << %{ cols="#{attrs[:cols]}"} if attrs[:cols]
|
247
|
+
r << %{>}
|
248
|
+
if content = (tag.locals.page.last_comment ? tag.locals.page.last_comment.send(attrs[:name]) : attrs[:content])
|
249
|
+
r << content
|
250
|
+
end
|
251
|
+
r << %{</textarea>}
|
252
|
+
end
|
253
|
+
|
254
|
+
desc %{Build a drop_box form field for the filters avaiable.}
|
255
|
+
tag "comments:filter_box_tag" do |tag|
|
256
|
+
attrs = tag.attr.symbolize_keys
|
257
|
+
value = attrs.delete(:value)
|
258
|
+
name = attrs.delete(:name)
|
259
|
+
r = %{<select name="comment[#{name}]"}
|
260
|
+
unless attrs.empty?
|
261
|
+
r << " "
|
262
|
+
r << attrs.map {|k,v| %Q(#{k}="#{v}") }.join(" ")
|
263
|
+
end
|
264
|
+
r << %{>}
|
265
|
+
|
266
|
+
TextFilter.descendants.each do |filter|
|
267
|
+
|
268
|
+
r << %{<option value="#{filter.filter_name}"}
|
269
|
+
r << %{ selected="selected"} if value == filter.filter_name
|
270
|
+
r << %{>#{filter.filter_name}</option>}
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
r << %{</select>}
|
275
|
+
end
|
276
|
+
|
277
|
+
desc %{Prints the number of comments. }
|
278
|
+
tag "comments:count" do |tag|
|
279
|
+
tag.locals.page.comments.approved.count
|
280
|
+
end
|
281
|
+
|
282
|
+
|
283
|
+
tag "recent_comments" do |tag|
|
284
|
+
tag.expand
|
285
|
+
end
|
286
|
+
|
287
|
+
desc %{Returns the last [limit] comments throughout the site.
|
288
|
+
|
289
|
+
*Usage:*
|
290
|
+
<pre><code><r:recent_comments:each [limit="10"]>...</r:recent_comments:each></code></pre>
|
291
|
+
}
|
292
|
+
tag "recent_comments:each" do |tag|
|
293
|
+
limit = tag.attr['limit'] || 10
|
294
|
+
comments = Comment.approved.recent.all(:limit => limit)
|
295
|
+
result = []
|
296
|
+
comments.each_with_index do |comment, index|
|
297
|
+
tag.locals.comment = comment
|
298
|
+
tag.locals.index = index
|
299
|
+
tag.locals.page = comment.page
|
300
|
+
result << tag.expand
|
301
|
+
end
|
302
|
+
result
|
303
|
+
end
|
304
|
+
|
305
|
+
desc %{
|
306
|
+
Use this to prevent spam bots from filling your site with spam.
|
307
|
+
|
308
|
+
*Usage:*
|
309
|
+
<pre><code>What day comes after Monday? <r:comments:spam_answer_tag answer="Tuesday" /></code></pre>
|
310
|
+
}
|
311
|
+
tag "comments:spam_answer_tag" do |tag|
|
312
|
+
attrs = tag.attr.symbolize_keys
|
313
|
+
valid_spam_answer = attrs[:answer] || 'hemidemisemiquaver'
|
314
|
+
md5_answer = Digest::MD5.hexdigest(valid_spam_answer.to_slug)
|
315
|
+
r = %{<input type="text" id="comment_spam_answer" name="comment[spam_answer]"}
|
316
|
+
r << %{ class="#{attrs[:class]}"} if attrs[:class]
|
317
|
+
if value = (tag.locals.page.last_comment ? tag.locals.page.last_comment.send(:spam_answer) : '')
|
318
|
+
r << %{ value="#{value}" }
|
319
|
+
end
|
320
|
+
r << %{ />}
|
321
|
+
r << %{<input type="hidden" name="comment[valid_spam_answer]" value="#{md5_answer}" />}
|
322
|
+
end
|
323
|
+
|
324
|
+
desc %{
|
325
|
+
Render the contained elements if using the simple spam filter.
|
326
|
+
}
|
327
|
+
tag "if_comments_simple_spam_filter_enabled" do |tag|
|
328
|
+
tag.expand if Comment.simple_spam_filter_enabled?
|
329
|
+
end
|
330
|
+
|
331
|
+
desc %{
|
332
|
+
Render the contained elements unless using the simple spam filter.
|
333
|
+
}
|
334
|
+
tag "unless_comments_simple_spam_filter_enabled" do |tag|
|
335
|
+
tag.expand unless Comment.simple_spam_filter_enabled?
|
336
|
+
end
|
337
|
+
|
338
|
+
end
|