Skip to content

Instantly share code, notes, and snippets.

@Riduidel
Created December 30, 2009 09:25
Show Gist options
  • Save Riduidel/265942 to your computer and use it in GitHub Desktop.
Save Riduidel/265942 to your computer and use it in GitHub Desktop.
require 'yaml'
#DUMP_FILE = 'extract_dump_mysql.sql'
DUMP_FILE = 'wordpress_wp_20061231_000.sql'
DUMP_EXPORT_DIR = "dump"
CATEGORIES_STORE = 'categories_files.yaml'
# La lecture du fichier a été copiée de http://pleac.sourceforge.net/pleac_ruby/fileaccess.html
# Hash associant à leurs ids les catégories, sous forme elles aussi de hash
categories = Hash.new
def get_parameters(line, text_columns)
# Faudrait d'abord réussir à placer un post dans une tableau, pour ensuite traiter les différents arguments.
# Pour ça, pas compliqué : je prends dans la ligne le contenu entre la première '(' et la dernière ')'
inserted = line[line.index('(')+1 .. line.rindex(')')-1]
# Maintenant, on en fait un tableau, en découpant à chaque virgule ... enfin, presque, puisqu'il faut éviter
# celles qui sont dans des chaînes, et éviter les limites de chaînes échappées
parameters = Array.new
text_ended = false
text = ""
inserted.each(',') do |parameter|
parameter.gsub!("\\\'", "\'")
parameter.gsub!("\\r", "\r")
parameter.gsub!("\\n", "\n")
parameter.gsub!("\\t", "\t")
# Il y a du gros texte dans les quatrièmes et septièmes colonnes.
# Dans ces colonnes, la virgule qui compte est précédée (comme dernier caractère non blanc)
# par un ' qui n'est pas échappé
if text_columns.include? parameters.size
if parameter.size>3
text_ended = parameter[parameter.size-2,1]=="'" && parameter[parameter.size-3,1]!="\\"
elsif parameter.size>2
text_ended = parameter[parameter.size-2,1]=="'"
end
text << parameter
if text_ended
parameters << text[text.index("'")+1..text.rindex("'")-1].strip
text_ended = false
text = ""
end
else
if parameter[1..1]=="'"
parameters << parameter[2 .. parameter.size-3].strip
elsif parameter.index(",")==parameter.size-1
parameters << parameter[0, parameter.size-1].strip
else
parameters << parameter.strip
end
end
end
return parameters
end
def make_file_from_post(line, categories, categories_files)
# Tout ça, c'est juste un parsing de ligne, un peu compliqué, car c'est un statement MySQL.
# Est-ce que je ne pourrais pas plutôt le parser comme du SQl et en lire les arguments ?
# Ce serait malin. Helas, je n'ai pas trouvé de lib Ruby qui fasse le boulot pour moi.
# Donc tout à la main.
# Résumons-nous. La table wp_posts est faite comme ça :
# 0 `ID` bigint(20) unsigned NOT NULL auto_increment,
# 1 `post_author` bigint(20) NOT NULL default '0',
# 2 `post_date` datetime NOT NULL default '0000-00-00 00:00:00',
# 3 `post_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
# 4 `post_content` longtext NOT NULL,
# 5 `post_title` text NOT NULL,
# 6 `post_category` int(4) NOT NULL default '0',
# 7 `post_excerpt` text NOT NULL,
# 8 `post_status` enum('publish','draft','private','static','object','attachment') NOT NULL default 'publish',
# 9 `comment_status` enum('open','closed','registered_only') NOT NULL default 'open',
# 10 `ping_status` enum('open','closed') NOT NULL default 'open',
# 11 `post_password` varchar(20) NOT NULL default '',
# 12 `post_name` varchar(200) NOT NULL default '',
# 13 `to_ping` text NOT NULL,
# 14 `pinged` text NOT NULL,
# 15 `post_modified` datetime NOT NULL default '0000-00-00 00:00:00',
# 16 `post_modified_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
# 17 `post_content_filtered` text NOT NULL,
# 18 `post_parent` bigint(20) NOT NULL default '0',
# 19 `guid` varchar(255) NOT NULL default '',
# 20 `menu_order` int(11) NOT NULL default '0',
# 21 `post_type` varchar(100) NOT NULL default '',
# 22 `post_mime_type` varchar(100) NOT NULL default '',
# 23 `comment_count` bigint(20) NOT NULL default '0',
parameters = get_parameters(line, [4, 7])
# Maintenant, on a de quoi faire un fichier !
# post_content (champ 4) comme contenu
# psot_excerpt (7) pour mettre comme résumé (un deuxième bloc de texte)
# post_category (6) pour choisir le bon dossier et la catégorie utilisée dans le menu
# post_title (5)comme titre
# post_date (2)comme date de modif,
# post_name comme nom de fichier
# on recherche la bonne catégorie
category_array = categories.select do |cat_id, cat|
cat[6].include? parameters[0]
end
category = category_array.size>0 ? category_array[0][1] : nil
expected_file_name = ""
if category==nil
expected_file_name = DUMP_EXPORT_DIR+"\\"+"\\"+parameters[12]+".page"
else
expected_file_name = categories_files[category[2]]+"\\"+parameters[12]+".page"
end
# le fichier va être créé ou réinitialisé
export = File.open(expected_file_name, File::WRONLY|File::TRUNC|File::CREAT)
export << "---\n"
# Un petit hack pour éviter la création d'une section
export << "title: "+parameters[5].to_yaml.gsub("--- ","")
# Maintenant, on transforme la vieille date Wordpress en nouvelle date Ruby
# Et par convention, on prend la date locale
date = DateTime.strptime(parameters[2], "%Y-%m-%d %H:%M:%S")
export << "filemdate: "+date.to_yaml.gsub("--- ","")
export << "\n---\n"
export << parameters[4]
# Ca marche pas encore bien ce truc-là. je vais essayer de trouver la feinte !
# if parameters[7]!=nil && parameters[7].size>0
# export << "\n--- excerpt\n"
# export << parameters[7]
# end
puts "written "+expected_file_name
end
def create_hierarchy expected_dir
if !File.directory? expected_dir
puts "directory "+expected_dir+" does not exists yet."
parts = File.split(File.expand_path(expected_dir))
create_hierarchy parts[0]
Dir.mkdir expected_dir
end
end
def create_category_from(line, categories, categories_store)
# 0 `cat_ID` bigint(20) NOT NULL auto_increment,
# 1 `cat_name` varchar(55) NOT NULL default '',
# 2 `category_nicename` varchar(200) NOT NULL default '', faut pas se tromper, en fait, le nicename, c'est celui qu'on peut utiliser dans un nom de fichier
# 3 `category_description` longtext NOT NULL,
# 4 `category_parent` bigint(20) NOT NULL default '0',
# 5 `category_count` bigint(20) NOT NULL default '0',
parameters = get_parameters(line, [1, 2, 3])
# faut d'abord mettre la catégorie dans le hash des catégories
categories[parameters[0]]=parameters
# liste des identifiants de page dans la catégorie. C'est sale, mais ça peut marcher
# Le tableau sera à l'indice 6
parameters << []
# Maintenant, on a de quoi faire un fichier !
# post_content (champ 4) comme contenu
# psot_excerpt (7) pour mettre comme résumé (un deuxième bloc de texte)
# post_title (5)comme titre
# post_date (2)comme date de modif,
# post_name comme nom de fichier
expected_dir = ""
if categories_store.has_key?(parameters[2])
expected_dir = categories_store[parameters[2]]
else
expected_dir = DUMP_EXPORT_DIR+"\\"+parameters[2]
categories_store[parameters[2]] = expected_dir
end
create_hierarchy expected_dir
expected_file_name = expected_dir+"\\index.page"
# le fichier va être créé ou réinitialisé
export = File.open(expected_file_name, File::WRONLY|File::TRUNC|File::CREAT)
export << "---\n"
# Un petit hack pour éviter la création d'une section
export << "title: "+parameters[1].to_yaml.gsub("--- ","")
export << "\ninMenu: true"
# La catégorie est placée dans le menu de sa catégorie parente
# Mais alors ça, je sais pas du tout comment faire
export << "\n---\n"
export << "h1. "+parameters[1]+"\n\n"
export << parameters[3]
export << "\n\n{filelist:}"
puts "written "+parameters[2]
end
def link_post_id_to_category(line, categories, categories_files)
# 0 `rel_id` bigint(20) NOT NULL auto_increment,
# 1 `post_id` bigint(20) NOT NULL default '0',
# 2 `category_id` bigint(20) NOT NULL default '0',
parameters = get_parameters(line, [])
if categories.has_key? parameters[2]
categories[parameters[2]][6] << parameters[1]
end
end
def make_file_from_page(line, categories, categories_file)
end
if File.exist? CATEGORIES_STORE
categories_files = YAML.load_file(CATEGORIES_STORE)
else
categories_files = {}
end
# An IO object being Enumerable, we can use 'each' directly on it
File.open(DUMP_FILE).each do |line|
create_category_from(line, categories, categories_files) if line =~ /INSERT INTO `wp_categories`/
link_post_id_to_category(line, categories, categories_files) if line =~ /INSERT INTO `wp_post2cat`/
make_file_from_post(line, categories, categories_files) if line =~ /INSERT INTO `wp_posts`/
make_file_from_page(line, categories, categories_files) if line =~ /INSERT INTO `wp_posts`/
end
#puts categories.inspect
File.open( CATEGORIES_STORE, File::WRONLY|File::TRUNC|File::CREAT) do |out|
YAML.dump( categories_files, out )
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment