plugin_options = array();
add_action( 'init', array (&$this, 'init') ); // Hook on init
}
/**
* Initialize the plugin
*/
public function init() {
load_plugin_textdomain( 'fgj2wp', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
register_importer('fgj2wp', __('Joomla 1.5 (FG)', 'fgj2wp'), __('Import categories, articles and images from a Joomla 1.5 database into WordPress.', 'fgj2wp'), array ($this, 'dispatch'));
}
/**
* Display admin notice
*/
private function display_admin_notice( $message ) {
echo '
['.__CLASS__.'] '.$message.'
';
}
/**
* Display admin error
*/
private function display_admin_error( $message ) {
echo '['.__CLASS__.'] '.$message.'
';
}
/**
* Dispatch the actions
*/
public function dispatch() {
set_time_limit(7200);
// Default values
$this->plugin_options = array(
'url' => null,
'hostname' => 'localhost',
'port' => 3306,
'database' => null,
'username' => 'root',
'password' => '',
'prefix' => 'jos_',
'introtext_in_excerpt' => 1,
'skip_images' => 0,
);
$options = get_option('fgj2wp_options');
if ( is_array($options) ) {
$this->plugin_options = array_merge($this->plugin_options, $options);
}
if ( isset($_POST['action']) ) {
switch ( $_POST['action'] ) {
// Delete content
case 'empty':
if ( check_admin_referer( 'empty', 'fgj2wp_nonce' ) ) { // Security check
if ($this->empty_database()) { // Empty WP database
$this->display_admin_notice(__('Categories, posts and images deleted', 'fgj2wp'));
} else {
$this->display_admin_error(__('Couldn\'t delete content', 'fgj2wp'));
}
}
break;
// Import content
case 'import':
if ( check_admin_referer( 'import', 'fgj2wp_nonce' ) ) { // Security check
// Set database options
$this->plugin_options = array_merge($this->plugin_options, $this->validate_form_info());
update_option('fgj2wp_options', $this->plugin_options);
// Categories
$cat_count = $this->import_categories();
$this->display_admin_notice(sprintf(_n('%d category imported', '%d categories imported', $cat_count, 'fgj2wp'), $cat_count));
// Posts and images
$result = $this->import_posts();
$this->display_admin_notice(sprintf(_n('%d post imported', '%d posts imported', $result['posts_count'], 'fgj2wp'), $result['posts_count']));
$this->display_admin_notice(sprintf(_n('%d image imported', '%d images imported', $result['images_count'], 'fgj2wp'), $result['images_count']));
}
break;
}
}
$this->admin_build_page(); // Display the form
}
/**
* Build the option page
*
*/
private function admin_build_page() {
$posts_count = wp_count_posts('post');
$images_count = wp_count_posts('attachment');
$cat_count = count(get_categories(array('hide_empty' => 0)));
$data = $this->plugin_options;
$data['posts_count'] = $posts_count->publish + $posts_count->draft + $posts_count->future + $posts_count->pending;
$data['images_count'] = $images_count->inherit;
$data['cat_count'] = $cat_count;
include('admin_build_page.tpl.php');
}
/**
* Delete all posts, images and categories from the database
*
* @return boolean
*/
private function empty_database() {
global $wpdb;
$result = true;
$wpdb->show_errors();
$sql = <<commentmeta
WHERE comment_id IN
(
SELECT comment_ID FROM $wpdb->comments
WHERE comment_post_ID IN
(
SELECT ID FROM $wpdb->posts
WHERE post_type IN ('post', 'attachment', 'revision')
OR post_status = 'trash'
OR post_title = 'Brouillon auto'
)
);
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
$sql = <<comments
WHERE comment_post_ID IN
(
SELECT ID FROM $wpdb->posts
WHERE post_type IN ('post', 'attachment', 'revision')
OR post_status = 'trash'
OR post_title = 'Brouillon auto'
);
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
$sql = <<term_relationships
WHERE `object_id` IN
(
SELECT ID FROM $wpdb->posts
WHERE post_type IN ('post', 'attachment', 'revision')
OR post_status = 'trash'
OR post_title = 'Brouillon auto'
);
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
$sql = <<postmeta
WHERE post_id IN
(
SELECT ID FROM $wpdb->posts
WHERE post_type IN ('post', 'attachment', 'revision')
OR post_status = 'trash'
OR post_title = 'Brouillon auto'
);
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
$sql = <<posts
WHERE post_type IN ('post', 'attachment', 'revision')
OR post_status = 'trash'
OR post_title = 'Brouillon auto';
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
$sql = <<terms t, $wpdb->term_taxonomy tt
WHERE t.term_id = tt.term_id
AND t.term_id > 1 -- non-classe
AND tt.taxonomy = 'category'
SQL;
$result &= $wpdb->query($wpdb->prepare($sql));
// Reset the Joomla last imported post ID
update_option('fgj2wp_last_id', 0);
$this->optimize_database();
$wpdb->hide_errors();
return ($result !== false);
}
/**
* Optimize the database
*
*/
private function optimize_database() {
global $wpdb;
$sql = <<commentmeta` ,
`$wpdb->comments` ,
`$wpdb->options` ,
`$wpdb->postmeta` ,
`$wpdb->posts` ,
`$wpdb->terms` ,
`$wpdb->term_relationships` ,
`$wpdb->term_taxonomy`
SQL;
$wpdb->query($wpdb->prepare($sql));
}
/**
* Validate POST info
*
* @return array Form parameters
*/
private function validate_form_info() {
return array(
'url' => $_POST['url'],
'hostname' => $_POST['hostname'],
'port' => (int) $_POST['port'],
'database' => $_POST['database'],
'username' => $_POST['username'],
'password' => $_POST['password'],
'prefix' => $_POST['prefix'],
'introtext_in_excerpt' => !empty($_POST['introtext_in_excerpt']),
'skip_images' => !empty($_POST['skip_images']),
);
}
/**
* Import categories
*
* @return int Number of categories imported
*/
private function import_categories() {
$cat_count = 0;
$sections = $this->get_sections(); // Get the Joomla sections
$categories = $this->get_categories(); // Get the Joomla categories
$categories = array_merge($sections, $categories);
if ( is_array($categories) ) {
foreach ( $categories as $category ) {
//Parent category
$parent_id = 0;
if ( !empty($category['parent']) ) {
$idObj = get_category_by_slug($category['parent']);
$parent_id = $idObj->term_id;
}
// Insert the category
$new_category = array(
'cat_name' => $category['title'],
'category_description' => $category['description'],
'category_nicename' => $category['name'],
'category_parent' => $parent_id,
);
if ( wp_insert_category($new_category) ) {
$cat_count++;
}
}
// Update cache
delete_option("category_children");
_get_term_hierarchy('category');
}
return $cat_count;
}
/**
* Import posts
*
* @return int Number of posts imported
*/
private function import_posts() {
$posts_count = 0;
$images_count = 0;
$tab_categories = $this->tab_categories(); // Get the categories list
$posts = $this->get_posts(); // Get the Joomla posts
if ( is_array($posts) ) {
foreach ( $posts as $post ) {
// Images
if ( !$this->plugin_options['skip_images'] ) {
// Import images
list($post_images, $post_images_count) = $this->import_images($post['introtext'] . $post['fulltext'], $post['publish_up']);
$images_count += $post_images_count;
} else {
// Skip images
$post_images = array();
}
// Category ID
if ( array_key_exists($post['category'], $tab_categories) ) {
$cat_id = $tab_categories[$post['category']];
} else {
$cat_id = 1; // default category
}
// Define excerpt and post content
if ( empty($post['fulltext']) ) {
// Posts without a "Read more" link
$excerpt = '';
$content = $post['introtext'];
} else {
// Posts with a "Read more" link
if ( $this->plugin_options['introtext_in_excerpt'] ) {
// Introtext imported in excerpt
$excerpt = $post['introtext'];
$content = $post['fulltext'];
} else {
// Introtext imported in post content with a "Read more" tag
$excerpt = '';
$content = $post['introtext'] . "\n\n" . $post['fulltext'];
}
}
// Process content
$excerpt = $this->process_content($excerpt, $post_images);
$content = $this->process_content($content, $post_images);
// Status
$status = ($post['state'] == 1)? 'publish' : 'draft';
// Insert the post
$new_post = array(
'post_category' => array($cat_id),
'post_content' => $content,
'post_date' => $post['publish_up'],
'post_excerpt' => $excerpt,
'post_status' => $status,
'post_title' => $post['title'],
'post_name' => $post['alias'],
'post_type' => 'post',
);
$new_post_id = wp_insert_post($new_post);
if ( $new_post_id ) {
// Add links between the post and its images
$this->add_post_images($new_post_id, $new_post, $post_images);
// Increment the Joomla last imported post ID
update_option('fgj2wp_last_id', $post['id']);
$posts_count++;
}
}
}
return array(
'posts_count' => $posts_count,
'images_count' => $images_count,
);
}
/**
* Get Joomla sections
*
* @return array of Sections
*/
private function get_sections() {
$sections = array();
try {
$db = new PDO('mysql:host=' . $this->plugin_options['hostname'] . ';port=' . $this->plugin_options['port'] . ';dbname=' . $this->plugin_options['database'], $this->plugin_options['username'], $this->plugin_options['password'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT s.title, CONCAT('s', s.id, '-', IFNULL(s.alias, s.name)) AS name, s.description
FROM ${prefix}sections s
";
$query = $db->query($sql);
if ( is_object($query) ) {
foreach ( $query as $row ) {
$sections[] = $row;
}
}
$db = null;
} catch ( PDOException $e ) {
print "Erreur !: " . $e->getMessage() . "
";
die();
}
return $sections;
}
/**
* Get Joomla categories
*
* @return array of Categories
*/
private function get_categories() {
$categories = array();
try {
$db = new PDO('mysql:host=' . $this->plugin_options['hostname'] . ';port=' . $this->plugin_options['port'] . ';dbname=' . $this->plugin_options['database'], $this->plugin_options['username'], $this->plugin_options['password'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT c.title, CONCAT(c.id, '-', IFNULL(c.alias, c.name)) AS name, c.description, CONCAT('s', s.id, '-', IFNULL(s.alias, s.name)) AS parent
FROM ${prefix}categories c
INNER JOIN ${prefix}sections AS s ON s.id = c.section
";
$query = $db->query($sql);
if ( is_object($query) ) {
foreach ( $query as $row ) {
$categories[] = $row;
}
}
$db = null;
} catch ( PDOException $e ) {
print "Erreur !: " . $e->getMessage() . "
";
die();
}
return $categories;
}
/**
* Get Joomla posts
*
* @return array of Posts
*/
private function get_posts() {
$posts = array();
$last_id = (int)get_option('fgj2wp_last_id'); // to restore the import where it left
try {
$db = new PDO('mysql:host=' . $this->plugin_options['hostname'] . ';port=' . $this->plugin_options['port'] . ';dbname=' . $this->plugin_options['database'], $this->plugin_options['username'], $this->plugin_options['password'], array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'UTF8\''));
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT p.id, p.title, p.alias, p.introtext, p.fulltext, p.state, CONCAT(c.id, '-', IFNULL(c.alias, c.name)) AS category, p.modified, p.publish_up
FROM ${prefix}content p
LEFT JOIN ${prefix}categories AS c ON p.catid = c.id
WHERE p.state >= 0 -- don't get the trash
AND p.id > '$last_id'
ORDER BY p.id
";
$query = $db->query($sql);
if ( is_object($query) ) {
foreach ( $query as $row ) {
$posts[] = $row;
}
}
$db = null;
} catch ( PDOException $e ) {
print "Erreur !: " . $e->getMessage() . "
";
die();
}
return $posts;
}
/**
* Return an array with all the categories sorted by name
*
* @return array categoryname => id
*/
private function tab_categories() {
$tab_categories = array();
$categories = get_categories(array('hide_empty' => '0'));
if ( is_array($categories) ) {
foreach ( $categories as $category ) {
$tab_categories[$category->slug] = $category->term_id;
}
}
return $tab_categories;
}
/**
* Import images
*
* @param string $content post content
* @param date $post_date Post date (for storing image)
* @return array:
* array: Images imported
* int: Images count
*/
private function import_images($content, $post_date) {
$images = array();
$images_count = 0;
if ( preg_match_all('#
#', $content, $matches, PREG_SET_ORDER) > 0) {
if ( is_array($matches) ) {
foreach ($matches as $match ) {
$filename = $match[2];
$other_attributes = $match[1] . $match[3];
// Upload the file from the Joomla web site to WordPress upload dir
if ( preg_match('/^http/', $filename) ) {
if ( preg_match('#^' . $this->plugin_options['url'] . '#', $filename) ) {
$old_filename = $filename;
} else {
// Don't import external images
continue;
}
} else {
$old_filename = untrailingslashit($this->plugin_options['url']) . '/' . $filename;
}
$old_filename = str_replace(" ", "%20", $old_filename); // for filenames with spaces
$image_date = strftime('%Y/%m', strtotime($post_date));
$uploads = wp_upload_dir($image_date);
$new_upload_dir = $uploads['path'];
$new_filename = $new_upload_dir . '/' . basename($filename);
//print "Copy \"$old_filename\" => $new_filename
";
//*
if ( !@copy($old_filename, $new_filename) ) {
$this->display_admin_error("Can't copy $old_filename to $new_filename");
continue;
}
//*/
$post_name = preg_replace('/\.[^.]+$/', '', basename($filename));
// If the attachment does not exist yet, insert it in the database
$attachment = $this->get_attachment_from_name($post_name);
if ( !$attachment ) {
$wp_filetype = wp_check_filetype(basename($new_filename), null);
$attachment_data = array(
'post_mime_type' => $wp_filetype['type'],
'post_name' => $post_name,
'post_title' => $post_name,
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment($attachment_data, $new_filename);
$attachment = get_post($attach_id);
$post_name = $attachment->post_name; // Get the real post name
$images_count++;
}
$attach_id = $attachment->ID;
$images[$filename] = $post_name;
// you must first include the image.php file
// for the function wp_generate_attachment_metadata() to work
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $new_filename );
wp_update_attachment_metadata( $attach_id, $attach_data );
// Image Alt
if (preg_match('#alt="(.+?)"#', $other_attributes, $alt_matches) ) {
$image_alt = wp_strip_all_tags(stripslashes($alt_matches[1]), true);
update_post_meta($attach_id, '_wp_attachment_image_alt', addslashes($image_alt)); // update_meta expects slashed
}
}
}
}
return array($images, $images_count);
}
/**
* Check if the attachment exists in the database
*
* @param string $name
* @return object Post
*/
private function get_attachment_from_name($name) {
$name = preg_replace('/\.[^.]+$/', '', basename($name));
$r = array(
'name' => $name,
'post_type' => 'attachment',
'numberposts' => 1,
);
$posts_array = get_posts($r);
if ( is_array($posts_array) && (count($posts_array) > 0) ) {
return $posts_array[0];
}
else {
return false;
}
}
/**
* Process the post content
*
* @param string $content Post content
* @param array $images Images
* @return string Processed post content
*/
private function process_content($content, $images) {
if ( !empty($content) ) {
// Replace img links with the new links
$content = $this->process_content_img_links($content, $images);
}
return $content;
}
/**
* Replace img links with the new links
*
* @param string $content Post content
* @param array $post_images Images
* @return string Processed post content
*/
private function process_content_img_links($content, $post_images) {
if ( is_array($post_images) ) {
foreach ( $post_images as $old_filename => $post_image_name ) {
$attachment = $this->get_attachment_from_name($post_image_name);
if ( $attachment ) {
$image_url = wp_get_attachment_image_src($attachment->ID, 'medium');
$content = str_replace($old_filename, $image_url[0], $content);
}
}
}
return $content;
}
/**
* Add a link between an image and a post (parent id + thumbnail)
*
* @param int $post_id Post ID
* @param array $post_data Post data
* @param array $post_images Post images
*/
function add_post_images($post_id, $post_data, $post_images) {
$thumbnail_is_set = false;
if ( is_array($post_images) ) {
foreach ( $post_images as $old_filename => $post_image_name ) {
$attachment = $this->get_attachment_from_name($post_image_name);
$attachment->post_parent = $post_id; // Attach the post to the image
$attachment->post_date = $post_data['post_date'] ;// Define the image's date
wp_update_post($attachment);
// Set the thumbnail to be the first image
if ( !$thumbnail_is_set ) {
set_post_thumbnail($post_id, $attachment->ID);
$thumbnail_is_set = true;
}
}
}
}
}
?>