radiant-comments-extension 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. data/.gitignore +3 -0
  2. data/CHANGELOG +40 -0
  3. data/HELP_admin.markdown +52 -0
  4. data/HELP_designer.markdown +36 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.rdoc +53 -0
  7. data/Rakefile +133 -0
  8. data/TODO +6 -0
  9. data/VERSION +1 -0
  10. data/app/controllers/admin/comments_controller.rb +130 -0
  11. data/app/controllers/comments_controller.rb +59 -0
  12. data/app/helpers/admin/comments_helper.rb +7 -0
  13. data/app/models/akismet_spam_filter.rb +37 -0
  14. data/app/models/comment.rb +121 -0
  15. data/app/models/comment_mailer.rb +24 -0
  16. data/app/models/mollom_spam_filter.rb +52 -0
  17. data/app/models/simple_spam_filter.rb +38 -0
  18. data/app/models/spam_filter.rb +43 -0
  19. data/app/views/admin/comments/_comment.rhtml +34 -0
  20. data/app/views/admin/comments/_form.rhtml +36 -0
  21. data/app/views/admin/comments/edit.rhtml +5 -0
  22. data/app/views/admin/comments/index.rhtml +55 -0
  23. data/app/views/admin/pages/_comments.rhtml +0 -0
  24. data/app/views/admin/pages/_edit_comments_enabled.rhtml +8 -0
  25. data/app/views/admin/pages/_index_head_view_comments.rhtml +1 -0
  26. data/app/views/admin/pages/_index_view_comments.rhtml +11 -0
  27. data/app/views/comment_mailer/comment_notification.rhtml +21 -0
  28. data/app/views/comments/_comment.rhtml +1 -0
  29. data/app/views/comments/_form.rhtml +23 -0
  30. data/app/views/comments/_new.rhtml +5 -0
  31. data/autotest/discover.rb +3 -0
  32. data/comments_extension.rb +81 -0
  33. data/cucumber.yml +1 -0
  34. data/db/migrate/001_create_comments.rb +29 -0
  35. data/db/migrate/002_create_snippets.rb +115 -0
  36. data/db/migrate/003_change_filter_id_from_integer_to_string.rb +10 -0
  37. data/db/migrate/004_add_approval_columns.rb +13 -0
  38. data/db/migrate/005_add_mollomid_column.rb +11 -0
  39. data/db/migrate/006_move_config_to_migrations.rb +22 -0
  40. data/db/migrate/007_add_preference_for_simple_spamcheck.rb +12 -0
  41. data/features/support/env.rb +16 -0
  42. data/features/support/paths.rb +16 -0
  43. data/lib/akismet.rb +134 -0
  44. data/lib/comment_page_extensions.rb +41 -0
  45. data/lib/comment_tags.rb +338 -0
  46. data/lib/mollom.rb +246 -0
  47. data/lib/radiant-comments-extension.rb +0 -0
  48. data/lib/tasks/comments_extension_tasks.rake +68 -0
  49. data/public/images/admin/accept.png +0 -0
  50. data/public/images/admin/comment_edit.png +0 -0
  51. data/public/images/admin/comments.png +0 -0
  52. data/public/images/admin/comments_delete.png +0 -0
  53. data/public/images/admin/delete.png +0 -0
  54. data/public/images/admin/email.png +0 -0
  55. data/public/images/admin/error.png +0 -0
  56. data/public/images/admin/link.png +0 -0
  57. data/public/images/admin/page_white_edit.png +0 -0
  58. data/public/images/admin/table_save.png +0 -0
  59. data/public/images/admin/tick.png +0 -0
  60. data/public/stylesheets/admin/comments.css +41 -0
  61. data/radiant-comments-extension.gemspec +133 -0
  62. data/spec/controllers/admin/comments_controller_spec.rb +57 -0
  63. data/spec/controllers/admin/comments_routing_spec.rb +43 -0
  64. data/spec/controllers/page_postback_spec.rb +51 -0
  65. data/spec/datasets/comments_dataset.rb +7 -0
  66. data/spec/models/akismet_spam_filter_spec.rb +61 -0
  67. data/spec/models/comment_spec.rb +148 -0
  68. data/spec/models/comment_tags_spec.rb +55 -0
  69. data/spec/models/mollom_spam_filter_spec.rb +103 -0
  70. data/spec/models/simple_spam_filter_spec.rb +44 -0
  71. data/spec/models/spam_filter_spec.rb +38 -0
  72. data/spec/spec.opts +6 -0
  73. data/spec/spec_helper.rb +36 -0
  74. data/test/fixtures/users.yml +6 -0
  75. data/test/integration/comment_enabling_test.rb +18 -0
  76. data/test/test_helper.rb +24 -0
  77. data/test/unit/comment_test.rb +52 -0
  78. metadata +177 -0
@@ -0,0 +1,5 @@
1
+ <h1>Edit Comment on "<%= escape_once(@comment.page.title) %>"</h1>
2
+
3
+ <% form_for [:admin, @comment] do |f| %>
4
+ <%= render :partial => "form", :locals => {:f => f} %>
5
+ <% end %>
@@ -0,0 +1,55 @@
1
+ <% content_for :page_scripts do -%>
2
+ document.observe('dom:loaded', function(){
3
+ Event.addBehavior({
4
+ 'tr.comment td.content': function(event){
5
+ $(this).observe('click', function(event){
6
+ if($(this).down('blockquote.expanded')){
7
+ $(this).down('blockquote.expanded').toggle();
8
+ $(this).down('blockquote.short').toggle();
9
+ }
10
+ event.stop();
11
+ });
12
+ }
13
+ });
14
+ });
15
+ <% end %>
16
+ <%- include_stylesheet 'admin/comments' %>
17
+ <h1>
18
+ <% if @page -%>
19
+ <%= @page.comments.count %> <%= "#{params[:status].titleize} " if params[:status] %><%= pluralize(@page.comments.count, 'Comment') %> on <%= link_to @page.title, edit_admin_page_path(@page) %>
20
+ <% else -%>
21
+ <%= params[:status].titleize if params[:status] %> Comments
22
+ <% end -%>
23
+ </h1>
24
+
25
+ <ul id="comment-nav">
26
+ <li class="all"><%= link_or_span_unless_current("All", :status => 'all', :page_id => params[:page_id]) %></li>
27
+ <li class="approved"><%= link_or_span_unless_current("Approved", :status => "approved", :page_id => params[:page_id]) %></li>
28
+ <li class="unapproved"><%= link_or_span_unless_current("Unapproved", :status => "unapproved", :page_id => params[:page_id]) %></li>
29
+ <li class="csv"><%= link_to "Download CSV", :format => :csv %></li>
30
+ </ul>
31
+
32
+ <%= will_paginate @comments %>
33
+
34
+ <table id="comments" class="index" border="0" cellspacing="0" cellpadding="0">
35
+ <thead>
36
+ <tr>
37
+ <th>Content</th>
38
+ <th>Date</th>
39
+ <th>Author</th>
40
+ <% unless @page %><th>Page</th><% end %>
41
+ <th>Actions</th>
42
+ </tr>
43
+ </thead>
44
+ <tbody>
45
+ <%= render(:partial => "comment", :collection => @comments) || %Q[<tr><td class="note" colspan="#{@page ? 4 : 5}">No comments</td></tr>] %>
46
+ </tbody>
47
+ </table>
48
+
49
+ <%= will_paginate @comments %>
50
+
51
+ <% form_tag destroy_unapproved_admin_comments_url, :method => :delete do %>
52
+ <p><button type="submit" class="delete-unapproved"><%= image_tag("admin/comments_delete.png") %> Delete All Unapproved</button></p>
53
+ <% end %>
54
+
55
+ <p><small class="notice"><%= Comment.spam_filter.message %></small></p>
File without changes
@@ -0,0 +1,8 @@
1
+ <p style="clear:left">
2
+ <label for="page_enable_comments">Allow Comments on this page?</label>
3
+ <%= check_box "page", "enable_comments" %>
4
+
5
+ <small>
6
+ <%= link_to "Currently #{@page.comments_count} &mdash; View comments", admin_page_comments_path(:page_id => @page.id) unless @page.new_record? or @page.comments_count < 1 %>
7
+ </small>
8
+ </p>
@@ -0,0 +1 @@
1
+ <th class="comments">Comments</th>
@@ -0,0 +1,11 @@
1
+ <td class="comment_link">
2
+ <% if page.respond_to?('enable_comments') %>
3
+ <small>
4
+ <% if page.enable_comments %>
5
+ <%= link_to "#{page.comments_count} comments", admin_page_comments_path(:page_id => page.id) %>
6
+ <% else %>
7
+ <%= link_to "Enable", admin_page_enable_comments_path(:page_id => page.id), :method => :put %>
8
+ <% end %>
9
+ </small>
10
+ <% end %>
11
+ </td>
@@ -0,0 +1,21 @@
1
+ A new <%= @comment.ap_status %> comment has been posted on the <%= @site_name %> article <%= @comment.page.title %> (<%= @page_url %>)
2
+
3
+ Author : <%= @comment.author %> (IP: <%= @comment.author_ip %>)
4
+ E-mail : <%= @comment.author_email %>
5
+ URL : <%= @comment.author_url %>
6
+ Whois : http://ws.arin.net/cgi-bin/whois.pl?queryinput=<%= @comment.author_ip %>
7
+ Comment:
8
+
9
+
10
+ <%= @comment.content %>
11
+
12
+
13
+
14
+ You can see all comments on this post here:
15
+ <%= admin_page_comments_url(@comment.page) %>;
16
+
17
+ Approve it:
18
+ <%= approve_admin_comment_url(@comment) %>
19
+
20
+ View all comments awaiting approval:
21
+ <%= admin_comments_url(:status => :unapproved) %>
@@ -0,0 +1 @@
1
+ <%= comment.inspect %>
@@ -0,0 +1,23 @@
1
+ <h1>Comment Form</h1>
2
+
3
+ <div id="comment_form_container">
4
+
5
+ <fieldset class="comment_form">
6
+
7
+ <a name="comment_form"></a>
8
+
9
+ <%= f.text_field :author, :label => "Your Name (as you'd like it to appear on this comment)", :class => "regular" %>
10
+
11
+ <%= f.text_field :author_url %>
12
+
13
+ <%= f.text_field :author_email %>
14
+
15
+ <%= f.text_area :content, :label => "Your comment", :rows => 5, :class => "regular" %>
16
+
17
+ <%= submit_tag("Save comment", :class => "button", :id => "comment_submit_button") %>
18
+
19
+ <%= f.hidden_field :page_id %>
20
+
21
+ </fieldset>
22
+
23
+ </div>
@@ -0,0 +1,5 @@
1
+ <h1>Comment Form</h1>
2
+
3
+ <% form_for :comment, @comment, :url => {:controller => :comments, :action => :create} do |f| %>
4
+ <%= render :partial => "comments/form", :locals => {:f => f} %>
5
+ <% end %>
@@ -0,0 +1,3 @@
1
+ Autotest.add_discovery do
2
+ "rails"
3
+ end
@@ -0,0 +1,81 @@
1
+ class CommentsExtension < Radiant::Extension
2
+ version "#{File.read(File.expand_path(File.dirname(__FILE__)) + '/VERSION')}"
3
+ description "Adds blog-like comments and comment functionality to pages."
4
+ url "http://github.com/saturnflyer/radiant-comments"
5
+
6
+ define_routes do |map|
7
+ map.namespace :admin do |admin|
8
+ admin.connect 'comments/:status', :controller => 'comments', :status => 'unapproved', :conditions => { :method => :get }, :requirements => { :status => /all|unapproved|approved/ }
9
+ admin.connect 'comments/:status.:format', :controller => 'comments', :status => /all|approved|unapproved/, :conditions => { :method => :get }
10
+ admin.resources :comments, :member => { :remove => :get, :approve => :put, :unapprove => :put }, :collection => {:destroy_unapproved => :delete}
11
+ admin.page_enable_comments '/pages/:page_id/comments/enable', :controller => 'comments', :action => 'enable', :conditions => {:method => :put}
12
+ end
13
+ map.with_options(:controller => 'admin/comments') do |comments|
14
+ comments.connect 'admin/pages/:page_id/comments/:status', :status => /all|approved|unapproved/, :conditions => { :method => :get }
15
+ comments.connect 'admin/pages/:page_id/comments/:status.:format', :status => /all|approved|unapproved/, :conditions => { :method => :get }
16
+ comments.admin_page_comments 'admin/pages/:page_id/comments/:action'
17
+ comments.admin_page_comment 'admin/pages/:page_id/comments/:id/:action'
18
+ end
19
+ # This needs to be last, otherwise it hoses the admin routes.
20
+ map.resources :comments, :name_prefix => "page_", :path_prefix => "*url", :controller => "comments"
21
+ end
22
+
23
+ def activate
24
+ require 'sanitize'
25
+
26
+ Dir["#{File.dirname(__FILE__)}/app/models/*_filter.rb"].each do |file|
27
+ require file
28
+ end
29
+
30
+ Page.class_eval do
31
+ include CommentPageExtensions
32
+ include CommentTags
33
+ end
34
+
35
+ if admin.respond_to? :page
36
+ admin.page.edit.add :parts_bottom, "edit_comments_enabled", :before => "edit_timestamp"
37
+ admin.page.index.add :sitemap_head, "index_head_view_comments"
38
+ admin.page.index.add :node, "index_view_comments"
39
+ end
40
+
41
+ if self.respond_to? :tab
42
+ tab "Content" do
43
+ add_item('Comments', '/admin/comments')
44
+ end
45
+ else
46
+ admin.tabs.add "Comments", "/admin/comments", :visibility => [:all]
47
+ end
48
+ require "fastercsv"
49
+
50
+ ActiveRecord::Base.class_eval do
51
+ def self.to_csv(*args)
52
+ find(:all).to_csv(*args)
53
+ end
54
+
55
+ def export_columns(format = nil)
56
+ self.class.content_columns.map(&:name) - ['created_at', 'updated_at']
57
+ end
58
+
59
+ def to_row(format = nil)
60
+ export_columns(format).map { |c| self.send(c) }
61
+ end
62
+ end
63
+
64
+ Array.class_eval do
65
+ def to_csv(options = {})
66
+ return "" if first.nil?
67
+ if all? { |e| e.respond_to?(:to_row) }
68
+ header_row = first.export_columns(options[:format]).to_csv
69
+ content_rows = map { |e| e.to_row(options[:format]) }.map(&:to_csv)
70
+ ([header_row] + content_rows).join
71
+ else
72
+ FasterCSV.generate_line(self, options)
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ def deactivate
79
+ end
80
+
81
+ end
data/cucumber.yml ADDED
@@ -0,0 +1 @@
1
+ default: --format progress features --tags ~@proposed,~@in_progress
@@ -0,0 +1,29 @@
1
+ class CreateComments < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :comments do |t|
4
+ t.column :page_id, :integer
5
+ t.column :author, :string
6
+ t.column :author_url, :string
7
+ t.column :author_email, :string
8
+ t.column :author_ip, :string
9
+ t.column :content, :text
10
+ t.column :content_html, :text
11
+ t.column :created_at, :datetime
12
+ t.column :updated_at, :datetime
13
+ t.column :filter_id, :integer
14
+ t.column :user_agent, :string
15
+ t.column :referrer, :string
16
+ end
17
+
18
+ add_column :pages, :enable_comments, :boolean, :default => false
19
+ add_column :pages, :comments_count, :integer, :default => 0
20
+ Page.reset_column_information
21
+ Page.update_all("comments_count = 0")
22
+ end
23
+
24
+ def self.down
25
+ drop_table :comments
26
+ remove_column :pages, :enable_comments
27
+ remove_column :pages, :comments_count
28
+ end
29
+ end
@@ -0,0 +1,115 @@
1
+ class CreateSnippets < ActiveRecord::Migration
2
+ def self.up
3
+
4
+ # This code _WILL_ override snippets with the name comments, comment and comment_form
5
+ # if they exists.
6
+
7
+ # Comments snippet
8
+ Snippet.new do |s|
9
+ s.name = "comments"
10
+ s.content = <<CONTENT
11
+ <r:if_comments>
12
+ <div class="comments">
13
+ <h2>Comments</h2>
14
+ <r:comments:each>
15
+ <r:snippet name="comment" />
16
+ </r:comments:each>
17
+ </div>
18
+ </r:if_comments>
19
+ <r:snippet name="comment_form" />
20
+ CONTENT
21
+ end.save
22
+
23
+ # Comment snippet
24
+ Snippet.new do |s|
25
+ s.name = "comment"
26
+ s.content = <<CONTENT
27
+ <r:comments:field>
28
+ <div class="comment" id="comment-<r:id/>">
29
+ <p class="author">
30
+ <r:if_author_url><a href="<r:author_url/>" title="Visit <r:author/>'s website"></r:if_author_url>
31
+ <r:author/>
32
+ <r:if_author_url></a></r:if_author_url>
33
+ said on <r:date/>:
34
+ </p>
35
+
36
+ <div class="content_html"><r:content_html /></div>
37
+
38
+ <r:if_selected><p><em>
39
+ <r:if_approved>Thanks for your comment!</r:if_approved>
40
+ <r:unless_approved>Thanks for your comment, it has gone into the moderation queue and will be dealt with shortly.</r:unless_approved>
41
+ </em></p></r:if_selected>
42
+ </div>
43
+ </r:comments:field>
44
+ CONTENT
45
+ end.save
46
+
47
+ # comment_spam_block snippet
48
+ Snippet.new do |s|
49
+ s.name = 'comment_spam_block'
50
+ s.content = <<CONTENT
51
+ <r:random>
52
+ <r:error on="spam_answer"><p style="color:red">Answer <r:message /></p></r:error>
53
+ <r:option>
54
+ <p><label for="comment_spam_answer">What day of the week has the letter "h" in it's name?</label> (required)<br />
55
+ <r:spam_answer_tag answer="Thursday" /></p>
56
+ </r:option>
57
+ <r:option>
58
+ <p><label for="comment_spam_answer">Yellow and blue together make what color?</label> (required)<br />
59
+ <r:spam_answer_tag answer="green" /></p>
60
+ </r:option>
61
+ <r:option>
62
+ <p><label for="comment_spam_answer">What is SPAM spelled backwards?</label> (required)<br />
63
+ <r:spam_answer_tag answer="MAPS" /></p>
64
+ </r:option>
65
+ </r:random>
66
+ CONTENT
67
+ end.save
68
+
69
+ # Comment_form snippet
70
+ Snippet.new do |s|
71
+ s.name = "comment_form"
72
+ s.content = <<CONTENT
73
+ <r:page>
74
+ <r:if_enable_comments>
75
+ <r:comments:form>
76
+ <h3>Post a comment</h3>
77
+ <r:error><p style="color:red">Please correct the errors below.</p></r:error>
78
+ <p><label for="comment_author">Your Name</label><br />
79
+ <r:error on="author"><p style="color:red">Name <r:message /></p></r:error>
80
+ <r:text_field_tag name="author" id="author" class="required" /></p>
81
+
82
+ <p><label for="comment_author_email">Your Email Address</label> (required, but not displayed)<br />
83
+ <r:error on="author_email"><p style="color:red">Email <r:message /></p></r:error>
84
+ <r:text_field_tag name="author_email" class="required" /></p>
85
+
86
+ <p><label for="comment_author_url">Your Web Address</label> (optional)<br />
87
+ <r:error on="author_url"><p style="color:red">Web Address <r:message /></p></r:error>
88
+ <r:text_field_tag name="author_url" /></p>
89
+
90
+ <p><label for="comment_content">Your Comment</label><br />
91
+ <r:error on="content"><p style="color:red">Comment <r:message /></p></r:error>
92
+ <label for="comment_filter_id">Filter: <r:filter_box_tag name="filter_id" value="Textile" /></label><br />
93
+ <r:text_area_tag name="content" class="required" rows="9" cols="40" /></p>
94
+
95
+ <r:if_comments_simple_spam_filter_enabled>
96
+ <r:snippet name="comment_spam_block" />
97
+ </r:if_comments_simple_spam_filter_enabled>
98
+
99
+ <r:submit_tag name="submit" value="Save Comment" />
100
+
101
+ </r:comments:form>
102
+ </r:if_enable_comments>
103
+ </r:page>
104
+ CONTENT
105
+ end.save
106
+ end
107
+
108
+ def self.down
109
+
110
+ ["comments", "comment", "comment_form", "comment_spam_block"].each do |snippet|
111
+ Snippet.find_by_name(snippet).destroy rescue p "Could not destroy snippet #{snippet}"
112
+ end
113
+
114
+ end
115
+ end
@@ -0,0 +1,10 @@
1
+ class ChangeFilterIdFromIntegerToString < ActiveRecord::Migration
2
+ def self.up
3
+ change_column "comments", "filter_id", :string, :limit => 25
4
+ end
5
+
6
+ def self.down
7
+ change_column "comments", "filter_id", :integer
8
+ end
9
+ end
10
+
@@ -0,0 +1,13 @@
1
+ # rake production radiant:extensions:comments:migrate
2
+ class AddApprovalColumns < ActiveRecord::Migration
3
+ def self.up
4
+ add_column :comments, :approved_at, :datetime
5
+ add_column :comments, :approved_by, :integer
6
+ end
7
+
8
+ def self.down
9
+ remove_column :comments, :approved_by
10
+ remove_column :comments, :approved_at
11
+ end
12
+ end
13
+
@@ -0,0 +1,11 @@
1
+ # rake production radiant:extensions:comments:migrate
2
+ class AddMollomidColumn < ActiveRecord::Migration
3
+ def self.up
4
+ add_column :comments, :mollom_id, :string
5
+ end
6
+
7
+ def self.down
8
+ remove_column :comments, :mollom_id
9
+ end
10
+ end
11
+
@@ -0,0 +1,22 @@
1
+ class MoveConfigToMigrations < ActiveRecord::Migration
2
+ def self.up
3
+ if Radiant::Config.table_exists?
4
+ { 'notification' => 'false',
5
+ 'notification_from' => '',
6
+ 'notification_to' => '',
7
+ 'notification_site_name' => '',
8
+ 'notify_creator' => 'true',
9
+ 'notify_updater' => 'false',
10
+ 'akismet_key' => '',
11
+ 'akismet_url' => '',
12
+ 'mollom_privatekey' => '',
13
+ 'mollom_publickey' => '',
14
+ 'filters_enabled' => 'true',
15
+ }.each{|k,v| Radiant::Config.create(:key => "comments.#{k}", :value => v) unless Radiant::Config["comments.#{k}"]}
16
+ end
17
+ end
18
+
19
+ def self.down
20
+ # not necessary
21
+ end
22
+ end