/
rss_renderer.rb
173 lines (137 loc) · 5.56 KB
/
rss_renderer.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# Copyright (C) 2009 Pascal Rettig.
require 'rss/2.0'
class Feed::RssRenderer < ParagraphRenderer
paragraph :feed
paragraph :view_rss
paragraph :rss_auto_discovery, :cache => true
def feed
paragraph_data = (paragraph.data || {}).symbolize_keys
@handler_info = get_handler_info(:feed,:rss,paragraph_data[:feed_type])
if ! @handler_info
data_paragraph :text => 'Reconfigure RSS Feed'.t
return
end
handler_options_class = nil
begin
handler_options_class = "#{@handler_info[:class_name]}::Options".constantize
rescue
end
if handler_options_class.nil?
data_paragraph :text => 'Reconfigure RSS Feed'.t
return
end
@options = handler_options_class.new(paragraph_data)
@handler = @handler_info[:class].new(@options)
results = renderer_cache(nil, nil, :skip => @options.timeout <= 0, :expires => @options.timeout*60) do |cache|
data = @handler.get_feed
if @handler_info[:custom]
cache[:output] = render_to_string(:partial => @handler_info[:custom],:locals => { :data => data})
else
cache[:output] = render_to_string(:partial => '/feed/rss/feed',:locals => { :data => data })
end
end
headers['Content-Type'] = 'text/xml'
data_paragraph :text => results.output
end
feature :rss_feed_view, :default_feature => <<-FEATURE
<div class='rss_feed'>
<cms:feed>
<h2><cms:link><cms:title/></cms:link></h2>
<cms:description/>
<cms:items>
<cms:item>
<div class='rss_feed_item'>
<h3><cms:link><cms:title/></cms:link></h3>
<cms:content/>
</div>
</cms:item>
</cms:items>
</cms:feed>
<cms:no_feed>
No Feed
</cms:no_feed>
</div>
FEATURE
def rss_feed_view_feature(data)
webiva_feature(:rss_feed_view,data) do |c|
c.define_tag('feed') { |tag| data[:feed].blank? ? nil : tag.expand }
c.define_tag('no_feed') { |tag| data[:feed].blank? ? tag.expand : nil }
c.define_link_tag('feed:') { |t| data[:feed].channel.link }
c.define_value_tag('feed:title') { |tag| data[:feed].channel.title }
c.define_value_tag('feed:description') { |tag|
data[:feed].channel.description
}
c.define_tag('feed:no_items') { |tag| data[:feed].items.length == 0 ? tag.expand : nil }
c.define_tag('feed:items') { |tag| data[:feed].items.length > 0 ? tag.expand : nil }
c.define_tag('feed:items:item') do |tag|
result = ''
items = data[:feed].items
unless data[:category].blank?
items = items.find_all { |item| item.categories.detect { |cat| cat.content == data[:category] } }
end
items = items[0..(data[:items]-1)] if data[:items] > 0
items.each_with_index do |item,idx|
tag.locals.item = item
tag.locals.index = idx + 1
tag.locals.first = idx == 0
tag.locals.last = idx == data[:feed].items.length
result << tag.expand
end
result
end
c.define_value_tag('feed:items:item:content') { |tag|
if data[:read_more].blank?
txt = tag.locals.item.description
else
txt = tag.locals.item.description.to_s.sub(data[:read_more],"[<a href='#{tag.locals.item.link}'>Read More..</a>]")
end
}
c.define_link_tag('feed:items:item:') { |t| t.locals.item.link }
c.define_value_tag('feed:items:item:title') { |tag| tag.locals.item.title }
c.define_value_tag('feed:items:item:author') { |tag| tag.locals.item.author }
c.define_value_tag('feed:items:item:categories') { |tag| tag.locals.item.categories.map { |cat| cat.content }.join(", ") }
c.define_value_tag('feed:items:item:description') { |tag| tag.locals.item.description }
end
end
def view_rss
options = Feed::RssController::ViewRssOptions.new(paragraph.data || {})
if options.rss_url.blank?
render_paragraph :text => 'Configure Paragraph'
return
end
target_string = 'ViewRss'
display_string = "#{paragraph.id}"
feature_output = nil
valid_until,feature_output = DataCache.get_content("Feed",target_string,display_string) if !editor?
if !feature_output || Time.now > valid_until
begin
http = open(options.rss_url)
response = http.read
rss_feed = RSS::Parser.parse(response,false)
rescue Exception => e
valid_until = Time.now + 5.minutes
DataCache.put_content('Feed',target_string,display_string,[ valid_until, '' ]) if !editor?
render_paragraph :text => ''
return
end
data = { :feed => rss_feed, :items => options.items, :category => options.category, :read_more => options.read_more }
feature_output = rss_feed_view_feature(data)
valid_until = Time.now + options.cache_minutes.to_i.minutes
DataCache.put_content('Feed',target_string,display_string,[ valid_until, feature_output ]) if !editor?
end
render_paragraph :text => feature_output
end
def rss_auto_discovery
@options = paragraph.data || {}
if !@options[:module_node_id].blank? && @options[:module_node_id].to_i > 0
@nodes = [ SiteNode.find_by_id(@options[:module_node_id]) ]
else
@nodes = SiteNode.find(:all,:conditions => ['node_type = "M" AND module_name = "/feed/rss"' ],:include => :page_modifier)
end
output = @nodes.collect do |nd|
"<link rel='alternate' type='application/rss+xml' title='#{vh nd.page_modifier.modifier_data[:feed_title]}' href='#{vh nd.node_path}' />"
end.join("\n")
include_in_head(output)
render_paragraph :nothing => true
end
end