bcms_blog 1.2.0 → 1.3.0
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.
- data/Gemfile +10 -0
- data/README.markdown +10 -4
- data/app/assets/javascripts/bcms_blog/application.js +15 -0
- data/app/assets/stylesheets/bcms_blog/application.css +13 -0
- data/app/controllers/bcms_blog/blog_comments_controller.rb +5 -0
- data/app/controllers/bcms_blog/blog_posts_controller.rb +37 -0
- data/app/controllers/bcms_blog/blogs_controller.rb +13 -0
- data/app/controllers/bcms_blog/feeds_controller.rb +10 -0
- data/app/helpers/bcms_blog/blog_helper.rb +27 -0
- data/app/models/bcms_blog/blog.rb +99 -0
- data/app/models/bcms_blog/blog_comment.rb +36 -0
- data/app/models/bcms_blog/blog_group_membership.rb +6 -0
- data/app/models/bcms_blog/blog_observer.rb +141 -0
- data/app/models/bcms_blog/blog_post.rb +108 -0
- data/app/portlets/blog_post_portlet.rb +6 -6
- data/app/portlets/blog_posts_portlet.rb +4 -4
- data/app/views/bcms_blog/blog_comments/_form.html.erb +5 -0
- data/app/views/bcms_blog/blog_comments/render.html.erb +2 -0
- data/app/views/{cms → bcms_blog}/blog_posts/_form.html.erb +1 -1
- data/app/views/{cms → bcms_blog}/blog_posts/no_access.html.erb +0 -0
- data/app/views/{cms → bcms_blog}/blog_posts/render.html.erb +0 -0
- data/app/views/{cms → bcms_blog}/blogs/_form.html.erb +2 -2
- data/app/views/{cms → bcms_blog}/blogs/admin_only.html.erb +0 -0
- data/app/views/{cms → bcms_blog}/blogs/render.html.erb +0 -0
- data/app/views/{feeds → bcms_blog/feeds}/index.rss.builder +3 -3
- data/app/views/portlets/blog_post/_form.html.erb +1 -1
- data/app/views/portlets/blog_post/render.html.erb +3 -1
- data/app/views/portlets/blog_posts/_form.html.erb +1 -1
- data/config/routes.rb +5 -0
- data/db/bcms_blog.seeds.rb +4 -0
- data/db/migrate/20090415000000_create_blogs.rb +5 -6
- data/db/migrate/20090415000001_create_blog_posts.rb +1 -5
- data/db/migrate/20090415000002_create_blog_comments.rb +0 -2
- data/db/migrate/20120529184028_v130.rb +12 -0
- data/lib/bcms_blog/engine.rb +15 -1
- data/lib/bcms_blog/route_extensions.rb +8 -0
- data/lib/bcms_blog/version.rb +3 -0
- data/lib/bcms_blog.rb +5 -2
- data/lib/generators/bcms_blog/install/install_generator.rb +11 -11
- data/lib/tasks/bcms_blog_tasks.rake +4 -0
- data/test/bcms_blog_test.rb +7 -0
- data/test/functional/cms/blog_posts_controller_test.rb +47 -0
- data/test/functional/cms/blogs_controller_test.rb +27 -0
- data/test/integration/blog_controller_test.rb +63 -0
- data/test/integration/blog_post_test.rb +31 -0
- data/test/support/blog_test_helper.rb +71 -0
- data/test/support/factories.rb +54 -0
- data/test/support/factory_girl_support.rb +2 -0
- data/test/test_helper.rb +15 -0
- data/test/test_logging.rb +64 -0
- data/test/unit/blog_comment_test.rb +34 -0
- data/test/unit/blog_observer_test.rb +84 -0
- data/test/unit/blog_post_test.rb +45 -0
- data/test/unit/blog_test.rb +42 -0
- data/test/unit/helpers/feeds_helper_test.rb +4 -0
- metadata +83 -35
- data/app/controllers/cms/blog_comments_controller.rb +0 -3
- data/app/controllers/cms/blog_posts_controller.rb +0 -35
- data/app/controllers/cms/blogs_controller.rb +0 -11
- data/app/controllers/feeds_controller.rb +0 -8
- data/app/helpers/cms/blog_helper.rb +0 -20
- data/app/models/blog.rb +0 -95
- data/app/models/blog_comment.rb +0 -34
- data/app/models/blog_group_membership.rb +0 -4
- data/app/models/blog_observer.rb +0 -140
- data/app/models/blog_post.rb +0 -113
- data/app/views/cms/blog_comments/_form.html.erb +0 -5
- data/app/views/cms/blog_comments/render.html.erb +0 -2
- data/app/views/layouts/templates/default.html.erb +0 -17
- data/doc/README_FOR_APP +0 -2
- data/doc/migrate_to_20100427.rb +0 -77
- data/doc/release_notes.txt +0 -48
- data/lib/bcms_blog/routes.rb +0 -10
data/Gemfile
ADDED
data/README.markdown
CHANGED
@@ -15,18 +15,21 @@ A simple blog module that lets users create multiple blogs.
|
|
15
15
|
|
16
16
|
The blog module installs like most other BrowserCMS modules (http://guides.browsercms.org/installing_modules.html)
|
17
17
|
|
18
|
-
gem install bcms_blog
|
18
|
+
$ gem install bcms_blog
|
19
19
|
|
20
20
|
## Set up your application to use the module
|
21
21
|
|
22
22
|
### 1. Install the module
|
23
23
|
|
24
|
-
rails g cms:install bcms_blog
|
24
|
+
$ rails g cms:install bcms_blog
|
25
25
|
|
26
26
|
### 2. Run the following commands
|
27
27
|
|
28
|
-
rake db:migrate
|
29
|
-
|
28
|
+
$ rake db:migrate
|
29
|
+
$ rake db:seed
|
30
|
+
|
31
|
+
For projects with existing databases, you may need to comment out other lines in db/seeds.rb so only the blog seed data runs.
|
32
|
+
|
30
33
|
## Creating a Blog
|
31
34
|
|
32
35
|
* To get started, go to the Content Library and choose the Blog module in the left hand menu.
|
@@ -103,3 +106,6 @@ Special thanks to some amazing folks from the BrowserCMS community for their wor
|
|
103
106
|
* Notifications for Comments - Blogs should have an option to be notified when a new comment is created. This will allow for practical management of comments/spam.
|
104
107
|
* Messaging for Moderated comments - If moderation is turned on, users get no feedback about the comment they just left. Ideally, they would get some sort of javascript notice that their comment is awaiting notification.
|
105
108
|
|
109
|
+
## 3.5.x Todo
|
110
|
+
|
111
|
+
* Test and release
|
@@ -0,0 +1,15 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// the compiled file.
|
9
|
+
//
|
10
|
+
// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
|
11
|
+
// GO AFTER THE REQUIRES BELOW.
|
12
|
+
//
|
13
|
+
//= require jquery
|
14
|
+
//= require jquery_ujs
|
15
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
class BlogPostsController < Cms::ContentBlockController
|
3
|
+
before_filter :show_no_access_if_none_editable
|
4
|
+
|
5
|
+
def build_block
|
6
|
+
super
|
7
|
+
ensure_blog_editable
|
8
|
+
@block.author = current_user
|
9
|
+
end
|
10
|
+
|
11
|
+
def load_block
|
12
|
+
super
|
13
|
+
ensure_blog_editable
|
14
|
+
end
|
15
|
+
|
16
|
+
def load_blocks
|
17
|
+
super
|
18
|
+
@blocks.delete_if { |b| !b.editable_by?(current_user) }
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
# If the current user is not able to edit any blog, just show them a page saying so
|
24
|
+
def show_no_access_if_none_editable
|
25
|
+
if Blog.editable_by(current_user).empty?
|
26
|
+
render :action => "no_access"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Ensure the current user can actually edit the blog this blog post is associated with
|
31
|
+
def ensure_blog_editable
|
32
|
+
if @block.blog
|
33
|
+
raise Cms::Errors::AccessDenied unless @block.blog.editable_by?(current_user)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
module BlogHelper
|
3
|
+
# We can't call it 'blog_path' because that would conflict with the actual named route method if there's a blog named "Blog".
|
4
|
+
def _blog_path(blog, route_name, route_params)
|
5
|
+
send("#{blog.name_for_path}_#{route_name}_path", route_params)
|
6
|
+
end
|
7
|
+
|
8
|
+
def _blog_post_path(blog_post)
|
9
|
+
main_app.send("#{blog_post.route_name}_path", blog_post.route_params)
|
10
|
+
end
|
11
|
+
|
12
|
+
def feeds_link_tag_for(name)
|
13
|
+
blog = Blog.find_by_name(name)
|
14
|
+
auto_discovery_link_tag(:rss, main_app.blog_feeds_url(:blog_id => blog), :title => "#{blog.name}")
|
15
|
+
end
|
16
|
+
|
17
|
+
def new_comment_params(portlet)
|
18
|
+
{:url=> Cms::Engine.routes.url_helpers.portlet_handler_path(:id=>portlet.id, :handler=>'create_comment'),
|
19
|
+
:method=>'post'}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Cms::ViewContext doesn't expose this method correctly, so duplicating it here.
|
23
|
+
def main_app
|
24
|
+
Rails.application.routes.url_helpers
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
class Blog < ActiveRecord::Base
|
3
|
+
acts_as_content_block
|
4
|
+
|
5
|
+
has_many :posts, :class_name => "BlogPost", :conditions => { :published => true }, :order => "published_at desc"
|
6
|
+
has_many :blog_group_memberships
|
7
|
+
has_many :groups, :through => :blog_group_memberships, :class_name=>"Cms::Group"
|
8
|
+
|
9
|
+
attr_accessible :group_ids
|
10
|
+
|
11
|
+
validates_presence_of :name
|
12
|
+
validates_uniqueness_of :name
|
13
|
+
|
14
|
+
scope :editable_by, lambda { |user|
|
15
|
+
if user.able_to?(:administrate)
|
16
|
+
{ }
|
17
|
+
else
|
18
|
+
{ :include => :groups, :conditions => ["groups.id IN (?)", user.group_ids.join(",")] }
|
19
|
+
end
|
20
|
+
}
|
21
|
+
|
22
|
+
def self.default_template
|
23
|
+
template_file = ActionController::Base.view_paths.map do |vp|
|
24
|
+
path = vp.to_s.first == "/" ? vp.to_s : File.join(Rails.root, vp.to_s)
|
25
|
+
File.join(path, "bcms_blog/blogs/render.html.erb")
|
26
|
+
end.detect{|f| File.exists? f }
|
27
|
+
template_file ? open(template_file){|f| f.read } : ""
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.posts_finder(finder, options)
|
31
|
+
if options[:tag]
|
32
|
+
finder = finder.tagged_with(options[:tag])
|
33
|
+
end
|
34
|
+
if options[:exclude_tags]
|
35
|
+
finder = finder.not_tagged_with(options[:exclude_tags])
|
36
|
+
end
|
37
|
+
if options[:category] || options[:category_id]
|
38
|
+
category_type = Cms::CategoryType.named("Blog Post").first
|
39
|
+
category = category_type.categories.named(options[:category]).first if options[:category]
|
40
|
+
category = category_type.categories. find(options[:category_id]) if options[:category_id]
|
41
|
+
finder = finder.in_category(category)
|
42
|
+
end
|
43
|
+
finder
|
44
|
+
end
|
45
|
+
|
46
|
+
def render
|
47
|
+
@blog = self
|
48
|
+
finder = @blog.posts.published
|
49
|
+
finder = Blog.posts_finder(finder, params)
|
50
|
+
|
51
|
+
if params[:year] && params[:month] && params[:day]
|
52
|
+
@date = Date.new(params[:year].to_i, params[:month].to_i, params[:day].to_i)
|
53
|
+
finder = posts.published_between(@date, @date + 1.day)
|
54
|
+
elsif params[:year] && params[:month]
|
55
|
+
@date = Date.new(params[:year].to_i, params[:month].to_i)
|
56
|
+
finder = posts.published_between(@date, @date + 1.month)
|
57
|
+
elsif params[:year]
|
58
|
+
@date = Date.new(params[:year].to_i)
|
59
|
+
finder = posts.published_between(@date, @date + 1.year)
|
60
|
+
end
|
61
|
+
|
62
|
+
@blog_posts = finder.all(:limit => 25, :order => "published_at desc")
|
63
|
+
raise ActiveRecord::RecordNotFound.new("No posts found") if @blog_posts.empty?
|
64
|
+
|
65
|
+
if params[:category]
|
66
|
+
@page_title = "#{params[:category]}"
|
67
|
+
elsif params[:tag]
|
68
|
+
@page_title = "Posts tagged with #{params[:tag]}"
|
69
|
+
elsif params[:year] && params[:month] && params[:day]
|
70
|
+
@page_title = "Posts from #{@date.to_s(:long)}"
|
71
|
+
elsif params[:year] && params[:month]
|
72
|
+
@page_title = "Posts from #{Date::MONTHNAMES[@date.month]} #{@date.year}"
|
73
|
+
elsif params[:year]
|
74
|
+
@page_title = "Posts from #{@date.year}"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def inline_options
|
79
|
+
{:inline => self.template}
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.default_order
|
83
|
+
"name"
|
84
|
+
end
|
85
|
+
|
86
|
+
def editable_by?(user)
|
87
|
+
user.able_to?(:administrate) || !(group_ids & user.group_ids).empty?
|
88
|
+
end
|
89
|
+
|
90
|
+
def potential_authors
|
91
|
+
groups.map(&:users).flatten.uniq
|
92
|
+
end
|
93
|
+
|
94
|
+
def name_for_path
|
95
|
+
name.to_slug.gsub('-', '_')
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
class BlogComment < ActiveRecord::Base
|
3
|
+
acts_as_content_block :is_searachable => "body"
|
4
|
+
belongs_to :post, :class_name => "BlogPost", :counter_cache => "comments_count"
|
5
|
+
|
6
|
+
validates_presence_of :post_id, :author, :body
|
7
|
+
|
8
|
+
before_create :publish_if_comments_are_enabled
|
9
|
+
|
10
|
+
def publish_if_comments_are_enabled
|
11
|
+
self.published = true unless post.blog.moderate_comments?
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.default_order
|
15
|
+
"created_at desc"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.default_order_for_search
|
19
|
+
default_order
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.columns_for_index
|
23
|
+
[ {:label => "Comment", :method => :name, :order => "body" },
|
24
|
+
{:label => "Created At", :method => :formatted_created_at, :order => "created_at"} ]
|
25
|
+
end
|
26
|
+
|
27
|
+
def name
|
28
|
+
body ? body[0..50] : ""
|
29
|
+
end
|
30
|
+
|
31
|
+
def formatted_created_at
|
32
|
+
created_at.to_s(:date)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
class BlogObserver < ActiveRecord::Observer
|
3
|
+
|
4
|
+
def after_create(blog)
|
5
|
+
@blog = blog
|
6
|
+
create_section_pages_and_routes
|
7
|
+
end
|
8
|
+
|
9
|
+
def after_save(blog)
|
10
|
+
if blog.persisted?
|
11
|
+
blog.publish
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Can't use before_update since CMS callback stack is altered from normal callbacks.
|
16
|
+
def before_save(blog)
|
17
|
+
if blog.persisted?
|
18
|
+
update_section_pages_and_route(blog)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
# A section, two pages, 6 routes and a portlet are created alongside every blog.
|
25
|
+
# This structure provides sensible defaults so users can pretty much start adding
|
26
|
+
# posts right after creating a blog without having to worry about where to put
|
27
|
+
# their blog and portlets.
|
28
|
+
def create_section_pages_and_routes
|
29
|
+
create_blog_section
|
30
|
+
create_blog_block_page
|
31
|
+
create_post_portlet_page
|
32
|
+
reload_routes
|
33
|
+
end
|
34
|
+
|
35
|
+
# Every blog is created within a section with the same name.
|
36
|
+
# For example, if you create a blog named 'MyBlog', a section 'MyBlog' will be
|
37
|
+
# created. This section will hold two pages: one for the blog ContentBlock that
|
38
|
+
# will render the list of posts and one for the BlogPost portlet (ie the individual
|
39
|
+
# post view)
|
40
|
+
def create_blog_section
|
41
|
+
@section = Cms::Section.find_by_name(@blog.name) || (
|
42
|
+
@section = Cms::Section.create!(
|
43
|
+
:name => @blog.name,
|
44
|
+
:path => "/#{@blog.name_for_path}",
|
45
|
+
:parent => Cms::Section.root.first
|
46
|
+
)
|
47
|
+
@section.allow_groups = :all
|
48
|
+
@section.save!
|
49
|
+
@section
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Following with the above example, the first page that is created is named 'MyBlog' and
|
54
|
+
# holds the Blog ContentBlock directly, not a portlet. Together with the 5 created routes,
|
55
|
+
# this page and its ContentBlock handle different post listings (all posts, posts in year,
|
56
|
+
# month or day and posts by tag or category).
|
57
|
+
def create_blog_block_page
|
58
|
+
page = Cms::Page.find_by_name(@blog.name) || Cms::Page.create!(
|
59
|
+
:name => @blog.name,
|
60
|
+
:path => "/#{@blog.name_for_path}",
|
61
|
+
:section => @section,
|
62
|
+
:template_file_name => "default.html.erb",
|
63
|
+
:hidden => true
|
64
|
+
)
|
65
|
+
page.create_connector(@blog, 'main')
|
66
|
+
|
67
|
+
create_route(page, "#{@blog.name}: Posts In Day", "/#{@blog.name_for_path}/:year/:month/:day")
|
68
|
+
create_route(page, "#{@blog.name}: Posts In Month", "/#{@blog.name_for_path}/:year/:month")
|
69
|
+
create_route(page, "#{@blog.name}: Posts In Year", "/#{@blog.name_for_path}/:year")
|
70
|
+
create_route(page, "#{@blog.name}: Posts With Tag", "/#{@blog.name_for_path}/tag/:tag")
|
71
|
+
create_route(page, "#{@blog.name}: Posts In Category", "/#{@blog.name_for_path}/category/:category")
|
72
|
+
end
|
73
|
+
|
74
|
+
# The second page that is created holds the BlogPostPortlet and displays the individual
|
75
|
+
# post view, along with it's comments.
|
76
|
+
def create_post_portlet_page
|
77
|
+
page = Cms::Page.find_by_name(portlet_name = "#{@blog.name}: Post") || Cms::Page.create!(
|
78
|
+
:name => portlet_name,
|
79
|
+
:path => "/#{@blog.name_for_path}/post",
|
80
|
+
:section => @section,
|
81
|
+
:template_file_name => "default.html.erb",
|
82
|
+
:hidden => true)
|
83
|
+
page.publish
|
84
|
+
create_route(page, portlet_name, "/#{@blog.name_for_path}/:year/:month/:day/:slug")
|
85
|
+
create_portlet(page, portlet_name, BlogPostPortlet)
|
86
|
+
end
|
87
|
+
|
88
|
+
# When the name of a Blog block changes, we need to change the Post page route.
|
89
|
+
# We also change the *names* of the section and pages that hold the blog block and
|
90
|
+
# post portlet because presumably, by changing the name of the blog, the intention
|
91
|
+
# was to reflect this name change in breadcrumbs and menus.
|
92
|
+
#
|
93
|
+
# Note that no other routes or paths are updated. This is intentional to be consistent
|
94
|
+
# with how BrowserCMS behaves when a Section or Page names change: paths are not
|
95
|
+
# updated automatically.
|
96
|
+
def update_section_pages_and_route(blog)
|
97
|
+
if blog.name_changed?
|
98
|
+
old_blog_name = blog.name_was
|
99
|
+
|
100
|
+
Cms::Section.find_by_name(old_blog_name).update_attribute(:name, blog.name)
|
101
|
+
Cms::PageRoute.find_by_name("#{old_blog_name}: Post").update_attribute(:name, "#{blog.name}: Post")
|
102
|
+
|
103
|
+
page = Cms::Page.find_by_name("#{old_blog_name}: Post")
|
104
|
+
page.update_attribute(:name, "#{blog.name}: Post")
|
105
|
+
page.publish
|
106
|
+
|
107
|
+
page = Cms::Page.find_by_name(old_blog_name)
|
108
|
+
page.update_attribute(:name, blog.name)
|
109
|
+
page.publish
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def reload_routes
|
114
|
+
Cms::PageRoute.reload_routes
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_route(page, name, pattern)
|
118
|
+
route = page.page_routes.build(:name => name, :pattern => pattern, :code => "")
|
119
|
+
route.save!
|
120
|
+
route.add_condition(:method, "get").save
|
121
|
+
route.add_requirement(:year, '\d{4,}') if pattern.include?(":year")
|
122
|
+
route.add_requirement(:month, '\d{2,}') if pattern.include?(":month")
|
123
|
+
route.add_requirement(:day, '\d{2,}') if pattern.include?(":day")
|
124
|
+
route.requirements.each(&:save)
|
125
|
+
end
|
126
|
+
|
127
|
+
def create_portlet(page, name, portlet_class)
|
128
|
+
portlet_class.create!(
|
129
|
+
:name => "#{name} Portlet",
|
130
|
+
:blog_id => @blog.id,
|
131
|
+
:template => portlet_class.default_template,
|
132
|
+
:connect_to_page_id => page.id,
|
133
|
+
:connect_to_container => "main",
|
134
|
+
:publish_on_save => true)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
|
@@ -0,0 +1,108 @@
|
|
1
|
+
module BcmsBlog
|
2
|
+
class BlogPost < ActiveRecord::Base
|
3
|
+
acts_as_content_block :taggable => true
|
4
|
+
|
5
|
+
has_attachment :file
|
6
|
+
|
7
|
+
|
8
|
+
before_save :set_published_at
|
9
|
+
|
10
|
+
belongs_to :blog
|
11
|
+
belongs_to_category
|
12
|
+
belongs_to :author, :class_name => "Cms::User"
|
13
|
+
has_many :comments, :class_name => "BlogComment", :foreign_key => "post_id"
|
14
|
+
|
15
|
+
before_validation :set_slug
|
16
|
+
validates_presence_of :name, :slug, :blog_id, :author_id
|
17
|
+
|
18
|
+
scope :published_between, lambda { |start, finish|
|
19
|
+
{ :conditions => [
|
20
|
+
"#{table_name}.published_at >= ? AND #{table_name}.published_at < ?",
|
21
|
+
start, finish ] }
|
22
|
+
}
|
23
|
+
|
24
|
+
scope :not_tagged_with, lambda { |tag| {
|
25
|
+
:conditions => [
|
26
|
+
"#{table_name}.id not in (
|
27
|
+
SELECT taggings.taggable_id FROM taggings
|
28
|
+
JOIN tags ON tags.id = taggings.tag_id
|
29
|
+
WHERE taggings.taggable_type = 'BlogPost'
|
30
|
+
AND (tags.name = ?)
|
31
|
+
)",
|
32
|
+
tag
|
33
|
+
]
|
34
|
+
} }
|
35
|
+
|
36
|
+
INCORRECT_PARAMETERS = "Incorrect parameters. This is probably because you are trying to view the " +
|
37
|
+
"portlet through the CMS interface, and so we have no way of knowing what " +
|
38
|
+
"post(s) to show"
|
39
|
+
|
40
|
+
delegate :editable_by?, :to => :blog
|
41
|
+
|
42
|
+
def set_published_at
|
43
|
+
if !published_at && publish_on_save
|
44
|
+
self.published_at = Time.now
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# This is necessary because, oddly, the publish! method in the Publishing behaviour sends an update
|
49
|
+
# query directly to the database, bypassing callbacks, so published_at does not get set by our
|
50
|
+
# set_published_at callback.
|
51
|
+
def after_publish_with_set_published_at
|
52
|
+
if published_at.nil?
|
53
|
+
self.published_at = Time.now
|
54
|
+
self.save!
|
55
|
+
end
|
56
|
+
after_publish_without_set_published_at if respond_to? :after_publish_without_set_published_at
|
57
|
+
end
|
58
|
+
if instance_methods.map(&:to_s).include? 'after_publish'
|
59
|
+
alias_method_chain :after_publish, :set_published_at
|
60
|
+
else
|
61
|
+
alias_method :after_publish, :after_publish_with_set_published_at
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.default_order
|
65
|
+
"created_at desc"
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.columns_for_index
|
69
|
+
[ {:label => "Name", :method => :name, :order => "name" },
|
70
|
+
{:label => "Published At", :method => :published_label, :order => "published_at" } ]
|
71
|
+
end
|
72
|
+
|
73
|
+
def published_label
|
74
|
+
published_at ? published_at.to_s(:date) : nil
|
75
|
+
end
|
76
|
+
|
77
|
+
def set_slug
|
78
|
+
self.slug = name.to_slug
|
79
|
+
end
|
80
|
+
|
81
|
+
def path
|
82
|
+
send("#{blog.name_for_path}_post_path", route_params)
|
83
|
+
end
|
84
|
+
def route_name
|
85
|
+
"#{blog.name_for_path}_post"
|
86
|
+
end
|
87
|
+
def route_params
|
88
|
+
{:year => year, :month => month, :day => day, :slug => slug}
|
89
|
+
end
|
90
|
+
|
91
|
+
def year
|
92
|
+
published_at.strftime("%Y") unless published_at.blank?
|
93
|
+
end
|
94
|
+
|
95
|
+
def month
|
96
|
+
published_at.strftime("%m") unless published_at.blank?
|
97
|
+
end
|
98
|
+
|
99
|
+
def day
|
100
|
+
published_at.strftime("%d") unless published_at.blank?
|
101
|
+
end
|
102
|
+
|
103
|
+
# Return true if this model has an attachment
|
104
|
+
def attachment
|
105
|
+
!file.blank?
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
-
class BlogPostPortlet < Portlet
|
1
|
+
class BlogPostPortlet < Cms::Portlet
|
2
2
|
|
3
3
|
enable_template_editor false
|
4
4
|
|
5
5
|
def render
|
6
|
-
scope = Blog.find(self.blog_id).posts
|
6
|
+
scope = BcmsBlog::Blog.find(self.blog_id).posts
|
7
7
|
if params[:blog_post_id]
|
8
8
|
@blog_post = scope.find(params[:blog_post_id])
|
9
9
|
elsif params[:slug]
|
@@ -13,7 +13,7 @@ class BlogPostPortlet < Portlet
|
|
13
13
|
end
|
14
14
|
@blog_post = scope.find_by_slug!(params[:slug])
|
15
15
|
else
|
16
|
-
raise BlogPost::INCORRECT_PARAMETERS
|
16
|
+
raise BcmsBlog::BlogPost::INCORRECT_PARAMETERS
|
17
17
|
end
|
18
18
|
|
19
19
|
make_page_title_use_blog_post_name(@blog_post)
|
@@ -29,7 +29,7 @@ class BlogPostPortlet < Portlet
|
|
29
29
|
work_around_cms_3_3_bug_where_current_user_is_not_correctly_set
|
30
30
|
|
31
31
|
params[:blog_comment].merge! :ip => request.remote_ip
|
32
|
-
blog_comment = BlogComment.new(params[:blog_comment])
|
32
|
+
blog_comment = BcmsBlog::BlogComment.new(params[:blog_comment])
|
33
33
|
if blog_comment.valid? && blog_comment.save
|
34
34
|
url_for_success
|
35
35
|
else
|
@@ -42,10 +42,10 @@ class BlogPostPortlet < Portlet
|
|
42
42
|
private
|
43
43
|
|
44
44
|
def work_around_cms_3_3_bug_where_current_user_is_not_correctly_set
|
45
|
-
User.current = current_user
|
45
|
+
Cms::User.current = current_user
|
46
46
|
end
|
47
47
|
|
48
|
-
# This is a work around for a bug in bcms 3.3 where the Cms::
|
48
|
+
# This is a work around for a bug in bcms 3.3 where the Cms::PageHelper#page_title doesnt
|
49
49
|
# share state between the portlet view and the page view.
|
50
50
|
# When the portlet view (app/views/portlets/blog_post/render) calls 'page_title @post.name'
|
51
51
|
# that instance variable isn't shared back to the page template.
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class BlogPostsPortlet < Portlet
|
1
|
+
class BlogPostsPortlet < Cms::Portlet
|
2
2
|
|
3
3
|
after_initialize :build_permalink_code
|
4
4
|
|
@@ -22,9 +22,9 @@ class BlogPostsPortlet < Portlet
|
|
22
22
|
Rails.logger.debug "... BlogPostsPortlet#render(options=#{@options.inspect} #{@options.class})"
|
23
23
|
|
24
24
|
if @options[:blog_id]
|
25
|
-
finder = Blog.find(@options[:blog_id]).posts
|
25
|
+
finder = BcmsBlog::Blog.find(@options[:blog_id]).posts
|
26
26
|
elsif @options[:blog_name]
|
27
|
-
finder = Blog.find_by_name(@options[:blog_name]).posts
|
27
|
+
finder = BcmsBlog::Blog.find_by_name(@options[:blog_name]).posts
|
28
28
|
else
|
29
29
|
finder = BlogPost
|
30
30
|
end
|
@@ -35,7 +35,7 @@ class BlogPostsPortlet < Portlet
|
|
35
35
|
end
|
36
36
|
|
37
37
|
finder = finder.published
|
38
|
-
finder = Blog.posts_finder(finder, @options)
|
38
|
+
finder = BcmsBlog::Blog.posts_finder(finder, @options)
|
39
39
|
|
40
40
|
@blog_posts = finder.all(
|
41
41
|
:limit => @options[:limit] || 25,
|
@@ -7,5 +7,5 @@
|
|
7
7
|
<% end %>
|
8
8
|
<%= f.cms_drop_down :category_id, categories_for('Blog Post').map{|c| [c.path, c.id]}, :include_blank => true %>
|
9
9
|
<%= f.cms_tag_list %>
|
10
|
-
<%= f.cms_drop_down :blog_id, Blog.editable_by(current_user).map{|b| [b.name, b.id]} %>
|
10
|
+
<%= f.cms_drop_down :blog_id, BcmsBlog::Blog.editable_by(current_user).map{|b| [b.name, b.id]} %>
|
11
11
|
<%= f.cms_file_field :attachment_file, :label => "Image" %>
|
File without changes
|
File without changes
|