bcms_bmedia_feeds 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+ gem 'sqlite3'
5
+ gem "jquery-rails"
6
+
7
+ group :test do
8
+ gem 'mocha'
9
+ end
10
+
11
+
data/README.markdown ADDED
@@ -0,0 +1,27 @@
1
+ Feed Module
2
+ ==========
3
+
4
+ This is a fork of https://github.com/jonleighton/bcms_feeds which updates the module to work with BrowserCMS 3.5.x and later. It will be released as bcms_bmedia_feeds since the original gem is owned by jonleighton.
5
+
6
+ Overview
7
+ ========
8
+
9
+ This is a BrowserCMS module which fetches, caches and displays RSS/Atom feeds.
10
+
11
+ Installation
12
+ ============
13
+
14
+ For installation instructions see http://www.browsercms.org/doc/guides/html/installing_modules.html
15
+
16
+ $ gem install bcms_bmedia_feeds
17
+ $ rails g cms:install bcms_bmedia_feeds
18
+
19
+ To incorporate a feed in your page, add a Feed Portlet to a page. Specify the URL of the feed. You can use the code section to manipulate this data as necessary, and the template to format it. SimpleRSS [http://simple-rss.rubyforge.org/] is used for parsing, and a parsed version of the feed will be available in the @feed variable.
20
+
21
+ Feeds are cached in the database for 30 minutes. If there is a failure fetching a remote feed, the expiry time of the cached feed will be extended by 10 minutes. When fetching remote feeds, the timeout length is 10 seconds.
22
+
23
+ Issues
24
+ =====
25
+
26
+ * Escaping html - Feeds will often use HTML in their post bodies. If you decide the 3rd party site is 'trustworthy' enough to just render unescaped HTML from their site on, then you can unescape the XML. By default, its contents are shown as XML encoded bodies.
27
+ * Cached Pages - If a page with a feed portlet on it has been cached, it will not update with as much frequency as might be expected. You can solve this by turning off page caching for that page.
@@ -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,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,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,4 @@
1
+ module BcmsFeeds
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module BcmsFeeds
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,62 @@
1
+ require 'net/http'
2
+ require 'timeout'
3
+ require 'simple-rss'
4
+
5
+ module BcmsFeeds
6
+ class Feed < ActiveRecord::Base
7
+ TTL = 30.minutes
8
+ TTL_ON_ERROR = 10.minutes
9
+ TIMEOUT = 10 # In seconds
10
+
11
+ delegate :entries, :items, :to => :parsed_contents
12
+ attr_accessible :url, :contents, :expires_at
13
+
14
+ def parsed_contents
15
+ @parsed_contents ||= SimpleRSS.parse(contents)
16
+ end
17
+
18
+ def contents
19
+ if expires_at.nil? || expires_at < Time.now.utc
20
+ begin
21
+ self.expires_at = Time.now.utc + TTL
22
+ new_contents = remote_contents
23
+ SimpleRSS.parse(new_contents) # Check that we can actually parse it
24
+ write_attribute(:contents, new_contents)
25
+ save
26
+ rescue StandardError, Timeout::Error, SimpleRSSError => exception
27
+ logger.error("Loading feed #{url} failed with #{exception.inspect}")
28
+ self.expires_at = Time.now.utc + TTL_ON_ERROR
29
+ save
30
+ end
31
+ else
32
+ logger.info("Loading feed from cache: #{url}")
33
+ end
34
+ read_attribute(:contents)
35
+ end
36
+
37
+ def remote_contents
38
+ Timeout.timeout(TIMEOUT) {
39
+ simple_get(url)
40
+ }
41
+ end
42
+
43
+ private
44
+
45
+ def simple_get(url)
46
+ logger.info("Loading feed from remote: #{url}")
47
+ parsed_url = URI.parse(url)
48
+ http = Net::HTTP.start(parsed_url.host, parsed_url.port)
49
+ response = http.request_get(url, 'User-Agent' => "BrowserCMS bcms_feed extension")
50
+ if response.is_a?(Net::HTTPSuccess)
51
+ return response.body
52
+ elsif response.is_a?(Net::HTTPRedirection)
53
+ logger.info("#{url} returned a redirect. Following . . ")
54
+ simple_get(response.header['Location'])
55
+ else
56
+ logger.info("#{url} returned a redirect. Following . . ")
57
+ raise StandardError
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,17 @@
1
+ class FeedPortlet < Cms::Portlet
2
+ handler "erb"
3
+
4
+ enable_template_editor true
5
+
6
+ def render
7
+ raise ArgumentError, "No feed URL specified" if self.url.blank?
8
+ @feed = BcmsFeeds::Feed.find_or_create_by_url(self.url).parsed_contents
9
+ if @portlet.limit.to_i != 0
10
+ @items = @feed.items[0..(@portlet.limit.to_i - 1)]
11
+ else
12
+ @items = @feed.items
13
+ end
14
+ instance_eval(self.code) unless self.code.blank?
15
+ end
16
+
17
+ end
@@ -0,0 +1,11 @@
1
+ <%= f.cms_text_field :name %>
2
+ <%= f.cms_text_field :url %>
3
+ <%= f.cms_text_area :code %>
4
+ <%= f.cms_drop_down :limit,
5
+ [
6
+ ['Unlimited','0'],['1','1'],['2','2'],['3','3'],['4','4'],['5','5'],['6','6'],['7','7'],['8','8'],['9','9'],
7
+ ['10','10'],['11','11'],['12','12'],['13','13'],['14','14'],['15','15'],['16','16'],['17','17'],['18','18'],['19','19'],
8
+ ['20','20']
9
+ ], :instructions => 'Items are available in the @items array and will be limited to the number you select above. You can still access the items via @feed.items, but they will not have a limit applied to them for backwards compatibility.'
10
+ %>
11
+ <%= f.cms_template_editor :template %>
@@ -0,0 +1,12 @@
1
+ <div class="feed-list feed-number-<%= @portlet.id %>">
2
+ <h1><%= @feed.title %></h1>
3
+ <ul>
4
+ <% @items.each do |item| %>
5
+ <li>
6
+ <div class="title"><%= link_to item.title, item.link %></div>
7
+ <div class="description"><%= item.description %></div>
8
+ <div class="item-meta">by <%= item.dc_creator %> on <%= item.pubDate %></div>
9
+ </li>
10
+ <% end %>
11
+ </ul>
12
+ </div>
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ BcmsFeeds::Engine.routes.draw do
2
+ end
@@ -0,0 +1,13 @@
1
+ class AddFeeds < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :feeds do |f|
4
+ f.string :url
5
+ f.text :contents
6
+ f.datetime :expires_at
7
+ end
8
+ end
9
+
10
+ def self.down
11
+ drop_table :feeds
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ class ModifyFeedsTableToUseMediumtext < ActiveRecord::Migration
2
+ def self.up
3
+ if BcmsFeeds::Feed.connection.adapter_name == 'MySQL'
4
+ #The postgres text column suffices, and this syntax and column type don't work in pg.
5
+ execute "ALTER TABLE feeds MODIFY COLUMN contents MEDIUMTEXT"
6
+ end
7
+ end
8
+
9
+ def self.down
10
+ if BcmsFeeds::Feed.connection.adapter_name == 'MySQL'
11
+ #The postgres text column suffices, and this syntax and column type don't work in pg.
12
+ execute "ALTER TABLE feeds MODIFY COLUMN contents TEXT"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,7 @@
1
+ class BcmsFeedsV200 < ActiveRecord::Migration
2
+ def change
3
+ if table_exists?(:feeds) && !table_exists?(:bcms_feeds_feeds)
4
+ rename_table :feeds, :bcms_feeds_feeds
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ require "bcms_feeds/engine"
2
+
3
+ # This file name (bcms_bmedia_feeds) is different than bcms_feeds since we don't own the gem and need to publish it.
4
+ module BcmsFeeds
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'browsercms'
2
+ module BcmsFeeds
3
+ class Engine < ::Rails::Engine
4
+ isolate_namespace BcmsFeeds
5
+ include Cms::Module
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module BcmsFeeds
2
+ VERSION = "2.0.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ Installs bcms_feeds into a project. Typically invoked indirectly via:
2
+
3
+ rails generate cms:install bcms_feeds
@@ -0,0 +1,23 @@
1
+ require 'cms/module_installation'
2
+
3
+ module BcmsBmediaFeeds
4
+ end
5
+ class BcmsBmediaFeeds::InstallGenerator < Cms::ModuleInstallation
6
+ add_migrations_directory_to_source_root __FILE__
7
+
8
+
9
+ def copy_migrations
10
+ rake 'bcms_feeds:install:migrations'
11
+ end
12
+
13
+ # Uncomment to add module specific seed data to a project.
14
+ #def add_seed_data_to_project
15
+ # copy_file "../bcms_feeds.seeds.rb", "db/bcms_feeds.seeds.rb"
16
+ # append_to_file "db/seeds.rb", "load File.expand_path('../bcms_feeds.seeds.rb', __FILE__)\n"
17
+ #end
18
+
19
+ def add_routes
20
+ mount_engine(BcmsFeeds)
21
+ end
22
+
23
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :bcms_feeds do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bcms_bmedia_feeds
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Leighton
9
+ - BrowserMedia
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-07-10 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: browsercms
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - <
21
+ - !ruby/object:Gem::Version
22
+ version: 3.6.0
23
+ - - ! '>='
24
+ - !ruby/object:Gem::Version
25
+ version: 3.5.0
26
+ type: :runtime
27
+ prerelease: false
28
+ version_requirements: !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - <
32
+ - !ruby/object:Gem::Version
33
+ version: 3.6.0
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: 3.5.0
37
+ - !ruby/object:Gem::Dependency
38
+ name: simple-rss
39
+ requirement: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 1.2.3
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: !ruby/object:Gem::Requirement
48
+ none: false
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: 1.2.3
53
+ description: A BrowserCMS module which fetches, caches and displays RSS/Atom feeds
54
+ email: github@browsermedia.com
55
+ executables: []
56
+ extensions: []
57
+ extra_rdoc_files:
58
+ - README.markdown
59
+ files:
60
+ - app/assets/javascripts/application.js
61
+ - app/assets/javascripts/bcms_feeds/application.js
62
+ - app/assets/stylesheets/application.css
63
+ - app/assets/stylesheets/bcms_feeds/application.css
64
+ - app/controllers/bcms_feeds/application_controller.rb
65
+ - app/helpers/bcms_feeds/application_helper.rb
66
+ - app/models/bcms_feeds/feed.rb
67
+ - app/portlets/feed_portlet.rb
68
+ - app/views/portlets/feed/_form.html.erb
69
+ - app/views/portlets/feed/render.html.erb
70
+ - config/routes.rb
71
+ - db/migrate/20090813213104_add_feeds.rb
72
+ - db/migrate/20100115202209_modify_feeds_table_to_use_mediumtext.rb
73
+ - db/migrate/20120710201056_bcms_feeds_v2_0_0.rb
74
+ - lib/bcms_bmedia_feeds.rb
75
+ - lib/bcms_feeds/engine.rb
76
+ - lib/bcms_feeds/version.rb
77
+ - lib/generators/bcms_bmedia_feeds/install/install_generator.rb
78
+ - lib/generators/bcms_bmedia_feeds/install/USAGE
79
+ - lib/tasks/bcms_feeds_tasks.rake
80
+ - README.markdown
81
+ - Gemfile
82
+ homepage: http://www.github.com/browsermedia/bcms_feeds
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options:
86
+ - --charset=UTF-8
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ segments:
96
+ - 0
97
+ hash: -4420423868363560329
98
+ required_rubygems_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ segments:
105
+ - 0
106
+ hash: -4420423868363560329
107
+ requirements: []
108
+ rubyforge_project:
109
+ rubygems_version: 1.8.24
110
+ signing_key:
111
+ specification_version: 3
112
+ summary: Feeds in BrowserCMS
113
+ test_files: []