-
Notifications
You must be signed in to change notification settings - Fork 23
Copying pages from existing rucksacks
jamesu edited this page Sep 12, 2010
·
2 revisions
Got a load of stuff on an existing Rucksack that you want to copy over to a new one, and don’t want to spend hours manually cut + pasting content over?
Well here is the solution!
Using HTTParty, nokogiri, and a bit of XML i have come up with the following ruby script to copy pages from one Rucksack to another. It requires both HTTParty and nokogiri, so make sure you have both handy.
Ideally this could be extended for use in Rucksack itself, perhaps using something like RestClient. But for now, there is this.
To run, try something like the following:
require 'thescript'
RucksackDest.duplicate_page(RucksackSrc, 1)
Which duplicates all it can on page 1 to the destination Rucksack.
# Rucksack copy
require 'httparty'
require 'nokogiri'
RUCKSACK_ORIGIN = "http://source"
RUCKSACK_DEST = "http://destination"
# Username + Passwords
RUCKSACK_ORIGIN_USER = "admin"
RUCKSACK_ORIGIN_PASS = "password"
RUCKSACK_DEST_USER = "admin"
RUCKSACK_DEST_PASS = "password"
class Rucksack
def self.pages
Nokogiri::XML.parse(get("/pages.xml")).xpath("/pages/page")
end
def self.slots_for_page(id)
Nokogiri::XML.parse(get("/pages/#{id}.xml")).xpath('page/slots/slot')
end
def self.widget_path(widgetname)
case widgetname
when 'Note'
return 'notes'
when 'List'
return 'lists'
when 'Separator'
return 'separators'
when 'UploadedFile'
return 'uploaded_files'
when 'Email'
return 'emails'
when 'Album'
return 'albums'
end
end
def self.widgets_for_page(pid)
slots_for_page(pid).collect do |path|
id = path.xpath('rel-object-id').inner_text.to_i
widgetname = path.xpath('rel-object-type').inner_text
widgeturl = "/pages/#{pid}/#{widget_path(widgetname)}/#{id}.xml"
res = nil
begin
res = {:type => widgetname, :data => Nokogiri::XML.parse(get(widgeturl)).xpath('/')}
puts "GOT: #{widgeturl}"
rescue Exception => e
puts "Problem importing #{widgeturl} (#{e.to_s})"
end
res
end
end
def self.duplicate_page(src, pid)
page_str = Nokogiri::XML.parse(src.get("/pages/#{pid}.xml")).xpath('page').to_s
# Make page on destination RuckSack
new_page = Nokogiri::XML.parse(post("/pages.xml", {:headers => {'Content-Type' => 'text/xml'}, :body => page_str})).xpath('page')
new_page_id = new_page.xpath('id').inner_text.to_i
puts "New page id: #{new_page_id}"
# Process widgets (Note: needs to be done in reverse order!)
puts "Importing widgets..."
src.widgets_for_page(pid).compact.reverse.each do |widget|
widgetname = widget[:type]
case widgetname
when 'Note'
print "Note -> ... "
post("/pages/#{new_page_id}/#{widget_path(widgetname)}.xml",
{:headers => {'Content-Type' => 'text/xml'},
:body => widget[:data].xpath('note').to_s})
puts "Done"
when 'Separator'
print "Separator -> ..."
post("/pages/#{new_page_id}/#{widget_path(widgetname)}.xml",
{:headers => {'Content-Type' => 'text/xml'},
:body => widget[:data].xpath('separator').to_s})
puts "Done"
when 'List'
print "List => ..."
new_list = Nokogiri::XML.parse(post("/pages/#{new_page_id}/#{widget_path(widgetname)}.xml",
{:headers => {'Content-Type' => 'text/xml'},
:body => widget[:data].xpath('list').to_s}))
# Grab items for list
list_id = widget[:data].xpath('id').inner_text.to_i
new_list_id = new_list.xpath('list/id').inner_text.to_i
print " id:#{list_id} -> #{new_list_id}..."
Nokogiri::XML.parse(src.get("/pages/#{pid}/#{widget_path(widgetname)}/#{list_id}/items.xml")).xpath('list-items/list-item').each do |item|
post("/pages/#{new_page_id}/#{widget_path(widgetname)}/#{new_list_id}/items.xml",
{:headers => {'Content-Type' => 'text/xml'},
:body => item.to_s})
print "."
end
puts "Done"
when 'UploadedFile'
print "Skipping (file)"
when 'Email'
print "Skipping (email)"
next
when 'Album'
print "Skipping (album)"
end
end
end
def self.users
Nokogiri::XML.parse(get("/users.xml")).xpath("/pages/page")
end
end
class RucksackSrc < Rucksack
include HTTParty
base_uri RUCKSACK_ORIGIN
basic_auth RUCKSACK_ORIGIN_USER, RUCKSACK_ORIGIN_PASS
end
class RucksackDest < Rucksack
include HTTParty
base_uri RUCKSACK_DEST
basic_auth RUCKSACK_DEST_USER, RUCKSACK_DEST_PASS
end