bunto-import 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +21 -21
- data/README.markdown +33 -33
- data/lib/bunto-import.rb +49 -49
- data/lib/bunto-import/importer.rb +26 -26
- data/lib/bunto-import/importers.rb +10 -10
- data/lib/bunto-import/importers/behance.rb +80 -80
- data/lib/bunto-import/importers/blogger.rb +330 -264
- data/lib/bunto-import/importers/csv.rb +96 -96
- data/lib/bunto-import/importers/drupal6.rb +53 -139
- data/lib/bunto-import/importers/drupal7.rb +54 -111
- data/lib/bunto-import/importers/drupal_common.rb +157 -0
- data/lib/bunto-import/importers/easyblog.rb +96 -96
- data/lib/bunto-import/importers/enki.rb +74 -74
- data/lib/bunto-import/importers/ghost.rb +68 -68
- data/lib/bunto-import/importers/google_reader.rb +64 -64
- data/lib/bunto-import/importers/joomla.rb +92 -90
- data/lib/bunto-import/importers/joomla3.rb +91 -91
- data/lib/bunto-import/importers/jrnl.rb +125 -125
- data/lib/bunto-import/importers/marley.rb +72 -72
- data/lib/bunto-import/importers/mephisto.rb +99 -99
- data/lib/bunto-import/importers/mt.rb +257 -257
- data/lib/bunto-import/importers/posterous.rb +130 -130
- data/lib/bunto-import/importers/rss.rb +62 -62
- data/lib/bunto-import/importers/s9y.rb +60 -60
- data/lib/bunto-import/importers/s9y_database.rb +363 -0
- data/lib/bunto-import/importers/textpattern.rb +70 -70
- data/lib/bunto-import/importers/tumblr.rb +300 -289
- data/lib/bunto-import/importers/typo.rb +88 -88
- data/lib/bunto-import/importers/wordpress.rb +372 -372
- data/lib/bunto-import/importers/wordpressdotcom.rb +207 -207
- data/lib/bunto-import/util.rb +76 -76
- data/lib/bunto-import/version.rb +3 -3
- data/lib/bunto/commands/import.rb +79 -79
- metadata +84 -54
@@ -1,68 +1,68 @@
|
|
1
|
-
module BuntoImport
|
2
|
-
module Importers
|
3
|
-
class Ghost < Importer
|
4
|
-
|
5
|
-
def self.specify_options(c)
|
6
|
-
c.option 'dbfile', '--dbfile', 'Database file (default: ghost.db)'
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.require_deps
|
10
|
-
BuntoImport.require_with_fallback(%w[
|
11
|
-
rubygems
|
12
|
-
sequel
|
13
|
-
fileutils
|
14
|
-
safe_yaml
|
15
|
-
])
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.process(options)
|
19
|
-
posts = fetch_posts(options.fetch('dbfile', 'ghost.db'))
|
20
|
-
if !posts.empty?
|
21
|
-
FileUtils.mkdir_p("_posts")
|
22
|
-
FileUtils.mkdir_p("_drafts")
|
23
|
-
posts.each do |post|
|
24
|
-
write_post_to_file(post)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
def self.fetch_posts(dbfile)
|
31
|
-
db = Sequel.sqlite(dbfile)
|
32
|
-
query = "SELECT `title`, `slug`, `markdown`, `created_at`, `status` FROM posts"
|
33
|
-
db[query]
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.write_post_to_file(post)
|
37
|
-
# detect if the post is a draft
|
38
|
-
draft = post[:status].eql?('draft')
|
39
|
-
|
40
|
-
# Ghost saves the time in an weird format with 3 more numbers.
|
41
|
-
# But the time is correct when we remove the last 3 numbers.
|
42
|
-
date = Time.at(post[:created_at].to_i.to_s[0..-4].to_i)
|
43
|
-
|
44
|
-
# the directory where the file will be saved to. either _drafts or _posts
|
45
|
-
directory = draft ? "_drafts" : "_posts"
|
46
|
-
|
47
|
-
# the filename under which the post is stored
|
48
|
-
filename = File.join(directory, "#{date.strftime('%Y-%m-%d')}-#{post[:slug]}.markdown")
|
49
|
-
|
50
|
-
# the YAML FrontMatter
|
51
|
-
frontmatter = { 'layout' => 'post', 'title' => post[:title] }
|
52
|
-
frontmatter['date'] = date if !draft # only add the date to the frontmatter when the post is published
|
53
|
-
frontmatter.delete_if { |k,v| v.nil? || v == '' } # removes empty fields
|
54
|
-
|
55
|
-
# write the posts to disk
|
56
|
-
write_file(filename, frontmatter.to_yaml, post[:markdown])
|
57
|
-
end
|
58
|
-
|
59
|
-
def self.write_file(filename, frontmatter, content)
|
60
|
-
File.open(filename, "w") do |f|
|
61
|
-
f.puts frontmatter
|
62
|
-
f.puts "---"
|
63
|
-
f.puts content
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
1
|
+
module BuntoImport
|
2
|
+
module Importers
|
3
|
+
class Ghost < Importer
|
4
|
+
|
5
|
+
def self.specify_options(c)
|
6
|
+
c.option 'dbfile', '--dbfile', 'Database file (default: ghost.db)'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.require_deps
|
10
|
+
BuntoImport.require_with_fallback(%w[
|
11
|
+
rubygems
|
12
|
+
sequel
|
13
|
+
fileutils
|
14
|
+
safe_yaml
|
15
|
+
])
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.process(options)
|
19
|
+
posts = fetch_posts(options.fetch('dbfile', 'ghost.db'))
|
20
|
+
if !posts.empty?
|
21
|
+
FileUtils.mkdir_p("_posts")
|
22
|
+
FileUtils.mkdir_p("_drafts")
|
23
|
+
posts.each do |post|
|
24
|
+
write_post_to_file(post)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
def self.fetch_posts(dbfile)
|
31
|
+
db = Sequel.sqlite(dbfile)
|
32
|
+
query = "SELECT `title`, `slug`, `markdown`, `created_at`, `status` FROM posts"
|
33
|
+
db[query]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.write_post_to_file(post)
|
37
|
+
# detect if the post is a draft
|
38
|
+
draft = post[:status].eql?('draft')
|
39
|
+
|
40
|
+
# Ghost saves the time in an weird format with 3 more numbers.
|
41
|
+
# But the time is correct when we remove the last 3 numbers.
|
42
|
+
date = Time.at(post[:created_at].to_i.to_s[0..-4].to_i)
|
43
|
+
|
44
|
+
# the directory where the file will be saved to. either _drafts or _posts
|
45
|
+
directory = draft ? "_drafts" : "_posts"
|
46
|
+
|
47
|
+
# the filename under which the post is stored
|
48
|
+
filename = File.join(directory, "#{date.strftime('%Y-%m-%d')}-#{post[:slug]}.markdown")
|
49
|
+
|
50
|
+
# the YAML FrontMatter
|
51
|
+
frontmatter = { 'layout' => 'post', 'title' => post[:title] }
|
52
|
+
frontmatter['date'] = date if !draft # only add the date to the frontmatter when the post is published
|
53
|
+
frontmatter.delete_if { |k,v| v.nil? || v == '' } # removes empty fields
|
54
|
+
|
55
|
+
# write the posts to disk
|
56
|
+
write_file(filename, frontmatter.to_yaml, post[:markdown])
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.write_file(filename, frontmatter, content)
|
60
|
+
File.open(filename, "w") do |f|
|
61
|
+
f.puts frontmatter
|
62
|
+
f.puts "---"
|
63
|
+
f.puts content
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -1,64 +1,64 @@
|
|
1
|
-
module BuntoImport
|
2
|
-
module Importers
|
3
|
-
class GoogleReader < Importer
|
4
|
-
def self.validate(options)
|
5
|
-
if options['source'].nil?
|
6
|
-
abort "Missing mandatory option --source."
|
7
|
-
end
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.specify_options(c)
|
11
|
-
c.option 'source', '--source', 'Source XML file of Google Reader export'
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.require_deps
|
15
|
-
BuntoImport.require_with_fallback(%w[
|
16
|
-
rubygems
|
17
|
-
rss
|
18
|
-
fileutils
|
19
|
-
safe_yaml
|
20
|
-
open-uri
|
21
|
-
rexml/document
|
22
|
-
date
|
23
|
-
])
|
24
|
-
end
|
25
|
-
|
26
|
-
# Process the import.
|
27
|
-
#
|
28
|
-
# source - a URL or a local file String.
|
29
|
-
#
|
30
|
-
# Returns nothing.
|
31
|
-
def self.process(options)
|
32
|
-
source = options.fetch('source')
|
33
|
-
|
34
|
-
open(source) do |content|
|
35
|
-
feed = RSS::Parser.parse(content)
|
36
|
-
|
37
|
-
raise "There doesn't appear to be any RSS items at the source (#{source}) provided." unless feed
|
38
|
-
|
39
|
-
feed.items.each do |item|
|
40
|
-
title = item.title.content.to_s
|
41
|
-
formatted_date = Date.parse(item.published.to_s)
|
42
|
-
post_name = title.split(%r{ |!|/|:|&|-|$|,}).map do |i|
|
43
|
-
i.downcase if i != ''
|
44
|
-
end.compact.join('-')
|
45
|
-
name = "#{formatted_date}-#{post_name}"
|
46
|
-
|
47
|
-
header = {
|
48
|
-
'layout' => 'post',
|
49
|
-
'title' => title
|
50
|
-
}
|
51
|
-
|
52
|
-
FileUtils.mkdir_p("_posts")
|
53
|
-
|
54
|
-
File.open("_posts/#{name}.html", "w") do |f|
|
55
|
-
f.puts header.to_yaml
|
56
|
-
f.puts "---\n\n"
|
57
|
-
f.puts item.content.content.to_s
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
1
|
+
module BuntoImport
|
2
|
+
module Importers
|
3
|
+
class GoogleReader < Importer
|
4
|
+
def self.validate(options)
|
5
|
+
if options['source'].nil?
|
6
|
+
abort "Missing mandatory option --source."
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.specify_options(c)
|
11
|
+
c.option 'source', '--source', 'Source XML file of Google Reader export'
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.require_deps
|
15
|
+
BuntoImport.require_with_fallback(%w[
|
16
|
+
rubygems
|
17
|
+
rss
|
18
|
+
fileutils
|
19
|
+
safe_yaml
|
20
|
+
open-uri
|
21
|
+
rexml/document
|
22
|
+
date
|
23
|
+
])
|
24
|
+
end
|
25
|
+
|
26
|
+
# Process the import.
|
27
|
+
#
|
28
|
+
# source - a URL or a local file String.
|
29
|
+
#
|
30
|
+
# Returns nothing.
|
31
|
+
def self.process(options)
|
32
|
+
source = options.fetch('source')
|
33
|
+
|
34
|
+
open(source) do |content|
|
35
|
+
feed = RSS::Parser.parse(content)
|
36
|
+
|
37
|
+
raise "There doesn't appear to be any RSS items at the source (#{source}) provided." unless feed
|
38
|
+
|
39
|
+
feed.items.each do |item|
|
40
|
+
title = item.title.content.to_s
|
41
|
+
formatted_date = Date.parse(item.published.to_s)
|
42
|
+
post_name = title.split(%r{ |!|/|:|&|-|$|,}).map do |i|
|
43
|
+
i.downcase if i != ''
|
44
|
+
end.compact.join('-')
|
45
|
+
name = "#{formatted_date}-#{post_name}"
|
46
|
+
|
47
|
+
header = {
|
48
|
+
'layout' => 'post',
|
49
|
+
'title' => title
|
50
|
+
}
|
51
|
+
|
52
|
+
FileUtils.mkdir_p("_posts")
|
53
|
+
|
54
|
+
File.open("_posts/#{name}.html", "w") do |f|
|
55
|
+
f.puts header.to_yaml
|
56
|
+
f.puts "---\n\n"
|
57
|
+
f.puts item.content.content.to_s
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -1,90 +1,92 @@
|
|
1
|
-
module BuntoImport
|
2
|
-
module Importers
|
3
|
-
class Joomla < Importer
|
4
|
-
def self.validate(options)
|
5
|
-
%w[dbname user].each do |option|
|
6
|
-
if options[option].nil?
|
7
|
-
abort "Missing mandatory option --#{option}."
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.specify_options(c)
|
13
|
-
c.option 'dbname', '--dbname', 'Database name'
|
14
|
-
c.option 'user', '--user', 'Database user name'
|
15
|
-
c.option 'password', '--password', "Database user's password (default: '')"
|
16
|
-
c.option 'host', '--host', 'Database host name'
|
17
|
-
c.option 'section', '--section', 'Table prefix name'
|
18
|
-
c.option 'prefix', '--prefix', 'Table prefix name'
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.require_deps
|
22
|
-
BuntoImport.require_with_fallback(%w[
|
23
|
-
rubygems
|
24
|
-
sequel
|
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
|
-
if
|
57
|
-
|
58
|
-
|
59
|
-
slug = sluggify(post[:
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
'
|
71
|
-
'
|
72
|
-
'
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
f.puts
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
end
|
1
|
+
module BuntoImport
|
2
|
+
module Importers
|
3
|
+
class Joomla < Importer
|
4
|
+
def self.validate(options)
|
5
|
+
%w[dbname user].each do |option|
|
6
|
+
if options[option].nil?
|
7
|
+
abort "Missing mandatory option --#{option}."
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.specify_options(c)
|
13
|
+
c.option 'dbname', '--dbname', 'Database name'
|
14
|
+
c.option 'user', '--user', 'Database user name'
|
15
|
+
c.option 'password', '--password', "Database user's password (default: '')"
|
16
|
+
c.option 'host', '--host', 'Database host name'
|
17
|
+
c.option 'section', '--section', 'Table prefix name'
|
18
|
+
c.option 'prefix', '--prefix', 'Table prefix name'
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.require_deps
|
22
|
+
BuntoImport.require_with_fallback(%w[
|
23
|
+
rubygems
|
24
|
+
sequel
|
25
|
+
mysql2
|
26
|
+
fileutils
|
27
|
+
safe_yaml
|
28
|
+
mysql
|
29
|
+
])
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.process(options)
|
33
|
+
dbname = options.fetch('dbname')
|
34
|
+
user = options.fetch('user')
|
35
|
+
pass = options.fetch('password', '')
|
36
|
+
host = options.fetch('host', "localhost")
|
37
|
+
section = options.fetch('section', '1')
|
38
|
+
table_prefix = options.fetch('prefix', "jos_")
|
39
|
+
|
40
|
+
db = Sequel.mysql2(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
|
41
|
+
|
42
|
+
FileUtils.mkdir_p("_posts")
|
43
|
+
|
44
|
+
# Reads a MySQL database via Sequel and creates a post file for each
|
45
|
+
# post in wp_posts that has post_status = 'publish'. This restriction is
|
46
|
+
# made because 'draft' posts are not guaranteed to have valid dates.
|
47
|
+
query = "SELECT `title`, `alias`, CONCAT(`introtext`,`fulltext`) as content, `created`, `id` FROM #{table_prefix}content WHERE (state = '0' OR state = '1') AND sectionid = '#{section}'"
|
48
|
+
|
49
|
+
db[query].each do |post|
|
50
|
+
# Get required fields and construct Bunto compatible name.
|
51
|
+
title = post[:title]
|
52
|
+
date = post[:created]
|
53
|
+
content = post[:content]
|
54
|
+
id = post[:id]
|
55
|
+
|
56
|
+
# Construct a slug from the title if alias field empty.
|
57
|
+
# Remove illegal filename characters.
|
58
|
+
if !post[:alias] or post[:alias].empty?
|
59
|
+
slug = sluggify(post[:title])
|
60
|
+
else
|
61
|
+
slug = sluggify(post[:alias])
|
62
|
+
end
|
63
|
+
|
64
|
+
name = "%02d-%02d-%02d-%03d-%s.markdown" % [date.year, date.month, date.day,
|
65
|
+
id,slug]
|
66
|
+
|
67
|
+
# Get the relevant fields as a hash, delete empty fields and convert
|
68
|
+
# to YAML for the header.
|
69
|
+
data = {
|
70
|
+
'layout' => 'post',
|
71
|
+
'title' => title.to_s,
|
72
|
+
'joomla_id' => post[:id],
|
73
|
+
'joomla_url' => post[:alias],
|
74
|
+
'date' => date
|
75
|
+
}.delete_if { |k,v| v.nil? || v == '' }.to_yaml
|
76
|
+
|
77
|
+
# Write out the data and content to file
|
78
|
+
File.open("_posts/#{name}", "w") do |f|
|
79
|
+
f.puts data
|
80
|
+
f.puts "---"
|
81
|
+
f.puts content
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# Borrowed from the Wordpress importer
|
87
|
+
def self.sluggify( title )
|
88
|
+
title = title.downcase.gsub(/[^0-9A-Za-z]+/, " ").strip.gsub(" ", "-")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -1,91 +1,91 @@
|
|
1
|
-
module BuntoImport
|
2
|
-
module Importers
|
3
|
-
class Joomla3 < Importer
|
4
|
-
def self.validate(options)
|
5
|
-
%w[dbname user prefix].each do |option|
|
6
|
-
if options[option].nil?
|
7
|
-
abort "Missing mandatory option --#{option}."
|
8
|
-
end
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.specify_options(c)
|
13
|
-
c.option 'dbname', '--dbname', 'Database name'
|
14
|
-
c.option 'user', '--user', 'Database user name'
|
15
|
-
c.option 'password', '--password', "Database user's password (default: '')"
|
16
|
-
c.option 'host', '--host', 'Database host name'
|
17
|
-
c.option 'category', '--category', 'ID of the category'
|
18
|
-
c.option 'prefix', '--prefix', 'Table prefix name'
|
19
|
-
end
|
20
|
-
|
21
|
-
def self.require_deps
|
22
|
-
BuntoImport.require_with_fallback(%w[
|
23
|
-
rubygems
|
24
|
-
sequel
|
25
|
-
fileutils
|
26
|
-
safe_yaml
|
27
|
-
])
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.process(options)
|
31
|
-
dbname = options.fetch('dbname')
|
32
|
-
user = options.fetch('user')
|
33
|
-
pass = options.fetch('password', '')
|
34
|
-
host = options.fetch('host', "localhost")
|
35
|
-
cid = options.fetch('category', 0)
|
36
|
-
table_prefix = options.fetch('prefix', "jos_")
|
37
|
-
|
38
|
-
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
|
39
|
-
|
40
|
-
FileUtils.mkdir_p("_posts")
|
41
|
-
|
42
|
-
# Reads a MySQL database via Sequel and creates a post file for each
|
43
|
-
# post in #__content that is published.
|
44
|
-
query = "SELECT `cn`.`title`, `cn`.`alias`, `cn`.`introtext`, CONCAT(`cn`.`introtext`,`cn`.`fulltext`) AS `content`, "
|
45
|
-
query << "`cn`.`created`, `cn`.`id`, `ct`.`title` AS `category`, `u`.`name` AS `author` "
|
46
|
-
query << "FROM `#{table_prefix}content` AS `cn` JOIN `#{table_prefix}categories` AS `ct` ON `cn`.`catid` = `ct`.`id` "
|
47
|
-
query << "JOIN `#{table_prefix}users` AS `u` ON `cn`.`created_by` = `u`.`id` "
|
48
|
-
query << "WHERE (`cn`.`state` = '1' OR `cn`.`state` = '2') " # Only published and archived content items to be imported
|
49
|
-
|
50
|
-
if cid > 0
|
51
|
-
query << " AND `cn`.`catid` = '#{cid}' "
|
52
|
-
else
|
53
|
-
query << " AND `cn`.`catid` != '2' " #Filter out uncategorized content
|
54
|
-
end
|
55
|
-
|
56
|
-
db[query].each do |post|
|
57
|
-
# Get required fields and construct Bunto compatible name.
|
58
|
-
title = post[:title]
|
59
|
-
slug = post[:alias]
|
60
|
-
date = post[:created]
|
61
|
-
author = post[:author]
|
62
|
-
category = post[:category]
|
63
|
-
content = post[:content]
|
64
|
-
excerpt = post[:introtext]
|
65
|
-
name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day,
|
66
|
-
slug]
|
67
|
-
|
68
|
-
# Get the relevant fields as a hash, delete empty fields and convert
|
69
|
-
# to YAML for the header.
|
70
|
-
data = {
|
71
|
-
'layout' => 'post',
|
72
|
-
'title' => title.to_s,
|
73
|
-
'joomla_id' => post[:id],
|
74
|
-
'joomla_url' => slug,
|
75
|
-
'date' => date,
|
76
|
-
'author' => author,
|
77
|
-
'excerpt' => excerpt.strip.to_s,
|
78
|
-
'category' => category
|
79
|
-
}.delete_if { |k,v| v.nil? || v == '' }.to_yaml
|
80
|
-
|
81
|
-
# Write out the data and content to file
|
82
|
-
File.open("_posts/#{name}", "w") do |f|
|
83
|
-
f.puts data
|
84
|
-
f.puts "---"
|
85
|
-
f.puts content
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
1
|
+
module BuntoImport
|
2
|
+
module Importers
|
3
|
+
class Joomla3 < Importer
|
4
|
+
def self.validate(options)
|
5
|
+
%w[dbname user prefix].each do |option|
|
6
|
+
if options[option].nil?
|
7
|
+
abort "Missing mandatory option --#{option}."
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.specify_options(c)
|
13
|
+
c.option 'dbname', '--dbname', 'Database name'
|
14
|
+
c.option 'user', '--user', 'Database user name'
|
15
|
+
c.option 'password', '--password', "Database user's password (default: '')"
|
16
|
+
c.option 'host', '--host', 'Database host name'
|
17
|
+
c.option 'category', '--category', 'ID of the category'
|
18
|
+
c.option 'prefix', '--prefix', 'Table prefix name'
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.require_deps
|
22
|
+
BuntoImport.require_with_fallback(%w[
|
23
|
+
rubygems
|
24
|
+
sequel
|
25
|
+
fileutils
|
26
|
+
safe_yaml
|
27
|
+
])
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.process(options)
|
31
|
+
dbname = options.fetch('dbname')
|
32
|
+
user = options.fetch('user')
|
33
|
+
pass = options.fetch('password', '')
|
34
|
+
host = options.fetch('host', "localhost")
|
35
|
+
cid = options.fetch('category', 0)
|
36
|
+
table_prefix = options.fetch('prefix', "jos_")
|
37
|
+
|
38
|
+
db = Sequel.mysql(dbname, :user => user, :password => pass, :host => host, :encoding => 'utf8')
|
39
|
+
|
40
|
+
FileUtils.mkdir_p("_posts")
|
41
|
+
|
42
|
+
# Reads a MySQL database via Sequel and creates a post file for each
|
43
|
+
# post in #__content that is published.
|
44
|
+
query = "SELECT `cn`.`title`, `cn`.`alias`, `cn`.`introtext`, CONCAT(`cn`.`introtext`,`cn`.`fulltext`) AS `content`, "
|
45
|
+
query << "`cn`.`created`, `cn`.`id`, `ct`.`title` AS `category`, `u`.`name` AS `author` "
|
46
|
+
query << "FROM `#{table_prefix}content` AS `cn` JOIN `#{table_prefix}categories` AS `ct` ON `cn`.`catid` = `ct`.`id` "
|
47
|
+
query << "JOIN `#{table_prefix}users` AS `u` ON `cn`.`created_by` = `u`.`id` "
|
48
|
+
query << "WHERE (`cn`.`state` = '1' OR `cn`.`state` = '2') " # Only published and archived content items to be imported
|
49
|
+
|
50
|
+
if cid > 0
|
51
|
+
query << " AND `cn`.`catid` = '#{cid}' "
|
52
|
+
else
|
53
|
+
query << " AND `cn`.`catid` != '2' " #Filter out uncategorized content
|
54
|
+
end
|
55
|
+
|
56
|
+
db[query].each do |post|
|
57
|
+
# Get required fields and construct Bunto compatible name.
|
58
|
+
title = post[:title]
|
59
|
+
slug = post[:alias]
|
60
|
+
date = post[:created]
|
61
|
+
author = post[:author]
|
62
|
+
category = post[:category]
|
63
|
+
content = post[:content]
|
64
|
+
excerpt = post[:introtext]
|
65
|
+
name = "%02d-%02d-%02d-%s.markdown" % [date.year, date.month, date.day,
|
66
|
+
slug]
|
67
|
+
|
68
|
+
# Get the relevant fields as a hash, delete empty fields and convert
|
69
|
+
# to YAML for the header.
|
70
|
+
data = {
|
71
|
+
'layout' => 'post',
|
72
|
+
'title' => title.to_s,
|
73
|
+
'joomla_id' => post[:id],
|
74
|
+
'joomla_url' => slug,
|
75
|
+
'date' => date,
|
76
|
+
'author' => author,
|
77
|
+
'excerpt' => excerpt.strip.to_s,
|
78
|
+
'category' => category
|
79
|
+
}.delete_if { |k,v| v.nil? || v == '' }.to_yaml
|
80
|
+
|
81
|
+
# Write out the data and content to file
|
82
|
+
File.open("_posts/#{name}", "w") do |f|
|
83
|
+
f.puts data
|
84
|
+
f.puts "---"
|
85
|
+
f.puts content
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|