summaryrefslogtreecommitdiff
path: root/lib/chaos_importer.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chaos_importer.rb')
-rw-r--r--lib/chaos_importer.rb336
1 files changed, 336 insertions, 0 deletions
diff --git a/lib/chaos_importer.rb b/lib/chaos_importer.rb
new file mode 100644
index 00000000..3a307a35
--- /dev/null
+++ b/lib/chaos_importer.rb
@@ -0,0 +1,336 @@
1require 'iconv'
2require 'nokogiri'
3require 'lib/chaos_calendar/ical_occurrences'
4require 'digest/sha1'
5
6
7class ChaosXml
8 attr_reader :xml, :unique_name, :locale, :date, :slug
9
10 def initialize options = {}
11 options.each_pair do |key,value|
12 instance_variable_set "@#{key}", value
13 instance_eval("def #{key}; @#{key};end")
14 end
15 end
16end
17
18class ChaosImporter
19 include Enumerable
20
21 def initialize path
22 unless Node.root
23 Node.create!
24 end
25
26 @directory = path
27 @years = {}
28 end
29
30 # Iterates through all xml files within the @directory and yields ChaosXml
31 # objects with the parsed attributes. These attributes are the basic data
32 # needed for further processing / parsing.
33 def each
34 directories = Dir.glob("#{@directory}/*/*.xml{,.de,.en}")
35
36 directories.each do |path|
37 next if path =~ /index\.xml/
38
39 chaos_id = chaos_id_from_path( path )
40 options = {}
41 options[:xml] = Nokogiri::XML( File.new(path).read )
42 options[:locale] = lang_from_path( path )
43 options[:date] = options[:xml].at("//date").content.to_date
44 options[:slug] = chaos_id
45 options[:unique_name] = "updates/#{options[:date]}/#{options[:slug]}"
46 xml = ChaosXml.new options
47
48 yield xml
49 end
50 end
51
52 # Uses the each method to loop over the xml files and uses the attrubutes of
53 # the returned ChaosXml objects to do some further processing which is needed
54 # to create proper ActiveRecord records
55 def import_updates
56 unless @updates = Node.find_by_unique_name('updates')
57 @updates = Node.create!( :slug => 'updates' )
58 @updates.move_to_child_of Node.root
59 end
60
61 self.each do |update|
62 author = find_or_create_author( update )
63 node = find_or_create_node( update )
64 html = convert_to_html( update.xml )
65 page = fill_draft_with_content(node.draft, html, update.locale)
66
67 add_tags_to_page page, update.xml, "update"
68 add_event_to_node node, update.xml if page.tag_list.include?("event")
69 page.user = author
70 page.save
71 puts node.unique_name
72 end
73
74 Node.all.each {|node| node.publish_draft!}
75 end
76
77 def lang_from_path path
78 case path
79 when /\.de$/ then :de
80 when /\.en$/ then :en
81 else
82 :de
83 end
84 end
85
86 def chaos_id_from_path path
87 path.sub(@directory, "").split(/\//).last.split(/\./)[0]
88 end
89
90 def find_or_create_author update
91 login = update.xml.at("//author").content rescue "webmaster"
92 puts login
93
94 # password = Digest::SHA1.hexdigest("#{Time.now+rand(100).days}")
95 # unless author = User.find_by_login(login)
96 # author = User.create!(
97 # :login => login,
98 # :email => "#{login}@example.com",
99 # :password => password,
100 # :password_confirmation => password
101 # )
102 # end
103
104 # author
105
106
107 end
108
109 def find_or_create_node update
110 year = update.date.year
111
112 unique_name_array = update.unique_name.split("/")
113
114 unless @years[year] || (@years[year] = Node.find_by_unique_name("updates/#{year}"))
115 @years[year] = Node.create :slug => year
116 @years[year].move_to_child_of @updates
117 end
118
119 unless node = Node.find_by_unique_name(update.unique_name)
120 node = Node.create :slug => update.slug
121 node.move_to_child_of @years[year]
122 end
123
124 node
125 end
126
127 def fill_draft_with_content draft, html, lang
128 I18n.locale = lang
129
130 options = {
131 :title => html.xpath("//title")[0].content,
132 :abstract => html.xpath("//abstract")[0].content,
133 :body => extract_body(html)
134 }
135
136 draft.update_attributes options
137 draft
138 end
139
140 def extract_body html, excluded_tags=[]
141 default_excluded_tags = [
142 "DTSTART",
143 "DTEND",
144 "DURATION",
145 "LOCATION",
146 "GEO",
147 "SUMMARY",
148 "URL"
149 ]
150
151 excluded_tags = (default_excluded_tags + excluded_tags).uniq
152
153 body = ""
154 element = html.xpath("//abstract")[0].next_sibling
155
156 while element do
157 body << element.to_s unless excluded_tags.include? element.name
158 element = element.next_sibling
159 end
160
161 body
162 end
163
164 def add_tags_to_page page, chaospage, *custom_tags
165 tag_list = custom_tags
166
167 chaospage.xpath("//flags").each do |node|
168 node.each do |k,v|
169 case k
170 when "calendar"
171 tag_list << "event"
172 when "pm"
173 tag_list << "pressemitteilung"
174 end
175 end
176 end
177
178 # Getting rid of duplicate flags
179 tag_list.uniq!
180
181 page.tag_list = tag_list.join(",")
182 page.save
183 end
184
185 def add_event_to_node node, chaospage
186 rrule = get_rrule(chaospage)
187
188 event_options = {
189 :start_time => get_start_time(chaospage),
190 :end_time => get_end_time(chaospage),
191 :allday => is_allday?(chaospage),
192 :rrule => rrule,
193 :custom_rrule => is_custom_rrule?(rrule),
194 :location => get_location(chaospage),
195 :url => get_url(chaospage),
196 :latitude => get_latitude(chaospage),
197 :longitude => get_logitude(chaospage)
198 }
199
200 unless tmp_event = node.event
201 tmp_event = Event.create! event_options.merge({:node_id => node.id})
202 else
203 tmp_event.update_attributes event_options
204 end
205 end
206
207 def get_start_time chaospage
208 chaospage.at("//ical:DTSTART").content || raise("DTSTART not found")
209 end
210
211 def get_end_time chaospage
212 dtstart = chaospage.at("//ical:DTSTART")
213 dtend = chaospage.at("//ical:DTEND")
214 duration = chaospage.at("//ical:DURATION")
215
216 if dtend
217 return dtend.content
218 elsif duration
219 parsed_duration = Ical_occurrences.duration_to_fixnum(duration.content)
220 return (dtstart.content.to_time + parsed_duration)
221 else
222 raise("Neiter DTEND nor DURATION found")
223 end
224 end
225
226 def is_allday? chaospage
227 !chaospage.at("//ical:DTSTART").[]("VALUE").nil?
228 end
229
230 def get_rrule chaospage
231 if rrule = chaospage.at("//ical:RRULE")
232 rrtxt = ''
233 rrule.children.each do |subrule|
234 rule_name = subrule.name
235 rule_content = subrule.content.sub(/\W/,'')
236
237 next if rule_content.blank?
238
239 rrtxt += "#{rule_name}=#{rule_content};"
240 end
241 rrtxt.chomp!(';')
242 rrtxt
243 else
244 nil
245 end
246 end
247
248 def is_custom_rrule? rrule
249 default_rules = [
250 "FREQ=WEEKLY;INTERVAL=1",
251 "FREQ=MONTHLY;INTERVAL=1",
252 "FREQ=YEARLY;INTERVAL=1"
253 ]
254
255 rrule && !default_rules.include?(rrule) ? true : false
256 end
257
258 def get_location chaospage
259 location = chaospage.at("//ical:LOCATION")
260 location ? location.content : nil
261 end
262
263 def get_url chaospage
264 location = chaospage.at("//ical:LOCATION")
265 location.[]("ALTREP") if location
266 end
267
268 def get_latitude chaospage
269 geo = chaospage.at("//ical:GEO")
270 geo.text.split(";")[0] if geo
271 end
272
273 def get_logitude chaospage
274 geo = chaospage.at("//ical:GEO")
275 geo.text.split(";")[1] if geo
276 end
277
278 def convert_to_html chaospage
279
280 chaospage.xpath('//paragraph').each {|sub| sub.name = "p"}
281 chaospage.xpath('//quote').each {|sub| sub.name = "blockquote" }
282 chaospage.xpath('//subtitle').each {|sub| sub.name = "h3" }
283 chaospage.xpath('//strong').each {|sub| sub.name = "em" }
284 chaospage.xpath('//stronger').each {|sub| sub.name = "strong" }
285 chaospage.xpath('//chapter').each {|sub| sub.name = "h2" }
286
287 chaospage.xpath('//link').each do |sub|
288 sub.name = "a"
289 href = sub.[]("ref")
290 sub.remove_attribute("ref")
291 sub.[]=("href", href)
292 sub.remove_attribute("type")
293 end
294
295 chaospage.xpath('//list').each do |sub|
296 if !sub.css("row item").empty?
297 sub.name = "table"
298
299 sub.css("row").each {|x| x.name = "tr"}
300 sub.css("tr item").each {|x| x.name = "td"}
301 elsif !sub.css("item").empty?
302 sub.name = "ul"
303
304 sub.css("item").each {|x| x.name = "li"}
305 end
306 end
307
308 chaospage.xpath('//media').each do |sub|
309 sub.name = "img"
310 src = sub.[]("ref")
311 sub.remove_attribute("src")
312 sub.[]=("src", src)
313 unless sub.content
314 sub.[]=("alt", sub.content)
315 sub.xpath('//*').each {|x| x.remove}
316 end
317 end
318
319 chaospage.xpath('//name').each do |sub|
320 if sub.[]("email")
321 mail_href = "mailto:#{sub.[]('email')}"
322 sub.remove_attribute("email")
323 sub.[]=("href", mail_href)
324 end
325 sub.name = "a"
326
327 if href = sub.[]("ref")
328 sub.remove_attribute("ref")
329 sub.[]=("href", href)
330 end
331 end
332
333 chaospage
334
335 end
336end \ No newline at end of file