wordpress/php-fpm/wordpress_files/plugins/fg-spip-to-wp/admin/class-fg-spip-to-wp-admin.php

3318 lines
102 KiB
PHP
Raw Normal View History

2020-05-22 03:40:23 +02:00
<?php
/**
* The admin-specific functionality of the plugin.
*
* @link https://wordpress.org/plugins/fg-spip-to-wp/
* @since 1.0.0
*
* @package FG_Spip_to_WordPress
* @subpackage FG_Spip_to_WordPress/admin
*/
if ( !class_exists('FG_Spip_to_WordPress_Admin', false) ) {
define('_RACCOURCI_TH_SPAN', '\s*(:?{{[^{}]+}}\s*)?|<'); // Pattern for table shortcodes replacement
/**
* The admin-specific functionality of the plugin.
*
* @package FG_Spip_to_WordPress
* @subpackage FG_Spip_to_WordPress/admin
* @author Frédéric GILLES
*/
class FG_Spip_to_WordPress_Admin extends WP_Importer {
const IMPORT_TIMEOUT = 7200; // Timeout = 2 hours
/**
* The ID of this plugin.
*
* @since 1.0.0
* @access private
* @var string $plugin_name The ID of this plugin.
*/
private $plugin_name;
/**
* The version of this plugin.
*
* @since 1.0.0
* @access private
* @var string $version The current version of this plugin.
*/
private $version;
public $spip_version; // SPIP version
public $spip_charset; // SPIP characters set
public $plugin_options; // Plug-in options
public $progressbar;
public $imported_categories = array();
public $chunks_size = 10;
public $posts_count = 0; // Number of imported posts
public $pages_count = 0; // Number of imported pages
public $media_count = 0; // Number of imported medias
public $media_path;
public $post_type = 'post'; // post or page
protected $faq_url; // URL of the FAQ page
protected $notices = array(); // Error or success messages
protected $cat_prefix = 'spip_cat_';
private $log_file;
private $log_file_url;
private $test_antiduplicate = false;
/**
* Initialize the class and set its properties.
*
* @since 1.0.0
* @param string $plugin_name The name of this plugin.
* @param string $version The version of this plugin.
*/
public function __construct( $plugin_name, $version ) {
$this->plugin_name = $plugin_name;
$this->version = $version;
$this->faq_url = 'https://wordpress.org/plugins/fg-spip-to-wp/faq/';
$upload_dir = wp_upload_dir();
$this->log_file = $upload_dir['basedir'] . '/' . $this->plugin_name . '.logs';
$this->log_file_url = $upload_dir['baseurl'] . '/' . $this->plugin_name . '.logs';
// Replace the protocol if the WordPress address is wrong in the WordPress General settings
if ( is_ssl() ) {
$this->log_file_url = preg_replace('/^https?/', 'https', $this->log_file_url);
}
// Progress bar
$this->progressbar = new FG_Spip_to_WordPress_ProgressBar($this);
}
/**
* The name of the plugin used to uniquely identify it within the context of
* WordPress and to define internationalization functionality.
*
* @since 1.0.0
* @return string The name of the plugin.
*/
public function get_plugin_name() {
return $this->plugin_name;
}
/**
* Register the stylesheets for the admin area.
*
* @since 1.0.0
*/
public function enqueue_styles() {
wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/fg-spip-to-wp-admin.css', array(), $this->version, 'all' );
}
/**
* Register the JavaScript for the admin area.
*
* @since 1.0.0
*/
public function enqueue_scripts() {
wp_enqueue_script( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'js/fg-spip-to-wp-admin.js', array( 'jquery', 'jquery-ui-progressbar' ), $this->version, false );
wp_localize_script( $this->plugin_name, 'objectL10n', array(
'delete_imported_data_confirmation_message' => __( 'All previously imported data will be deleted from WordPress.', 'fg-spip-to-wp' ),
'delete_all_confirmation_message' => __( 'All content will be deleted from WordPress.', 'fg-spip-to-wp' ),
'delete_no_answer_message' => __( 'Please select a remove option.', 'fg-spip-to-wp' ),
'import_completed' => __( 'IMPORT COMPLETED', 'fg-spip-to-wp' ),
'content_removed_from_wordpress' => __( 'Content removed from WordPress', 'fg-spip-to-wp' ),
'settings_saved' => __( 'Settings saved', 'fg-spip-to-wp' ),
'importing' => __( 'Importing…', 'fg-spip-to-wp' ),
'import_stopped_by_user' => __( 'IMPORT STOPPED BY USER', 'fg-spip-to-wp' ),
'internal_links_modified' => __( 'Internal links modified', 'fg-spip-to-wp' ),
) );
wp_localize_script( $this->plugin_name, 'objectPlugin', array(
'log_file_url' => $this->log_file_url,
'progress_url' => $this->progressbar->get_url(),
));
}
/**
* Initialize the plugin
*/
public function init() {
register_importer('fg-spip-to-wp', __('SPIP', 'fg-spip-to-wp'), __('Import categories, articles, news and images from a SPIP database into WordPress', 'fg-spip-to-wp'), array($this, 'importer'));
}
/**
* Display the stored notices
*
* @since 2.0.0
*/
public function display_notices() {
foreach ( $this->notices as $notice ) {
echo '<div class="' . $notice['level'] . '"><p>[' . $this->plugin_name . '] ' . $notice['message'] . "</p></div>\n";
}
}
/**
* Write a message in the log file
*
* @since 2.0.0
*
* @param string $message
*/
public function log($message) {
file_put_contents($this->log_file, "$message\n", FILE_APPEND);
}
/**
* Store an admin notice
*/
public function display_admin_notice( $message ) {
$this->notices[] = array('level' => 'updated', 'message' => $message);
error_log('[INFO] [' . $this->plugin_name . '] ' . $message);
$this->log($message);
}
/**
* Store an admin error
*/
public function display_admin_error( $message ) {
$this->notices[] = array('level' => 'error', 'message' => $message);
error_log('[ERROR] [' . $this->plugin_name . '] ' . $message);
$this->log('[ERROR] ' . $message);
}
/**
* Store an admin warning
*/
public function display_admin_warning( $message ) {
$this->notices[] = array('level' => 'error', 'message' => $message);
error_log('[WARNING] [' . $this->plugin_name . '] ' . $message);
$this->log('[WARNING] ' . $message);
}
/**
* Run the importer
*
* @since 2.0.0
*/
public function importer() {
$feasible_actions = array(
'empty',
'save',
'test_database',
'import',
'modify_links',
);
$action = '';
foreach ( $feasible_actions as $potential_action ) {
if ( isset($_POST[$potential_action]) ) {
$action = $potential_action;
break;
}
}
$this->dispatch($action);
$this->display_admin_page(); // Display the admin page
}
/**
* Import triggered by AJAX
*
* @since 2.0.0
*/
public function ajax_importer() {
$current_user = wp_get_current_user();
if ( !empty($current_user) && $current_user->has_cap('import') ) {
$action = filter_input(INPUT_POST, 'plugin_action', FILTER_SANITIZE_STRING);
if ( $action == 'update_wordpress_info') {
// Update the WordPress database info
echo $this->get_database_info();
} else {
ini_set('display_errors', true); // Display the errors that may happen (ex: Allowed memory size exhausted)
// Empty the log file if we empty the WordPress content
if ( ($action == 'empty') || (($action == 'import') && filter_input(INPUT_POST, 'automatic_empty', FILTER_VALIDATE_BOOLEAN)) ) {
file_put_contents($this->log_file, '');
}
$time_start = date('Y-m-d H:i:s');
$this->display_admin_notice("=== START $action $time_start ===");
$result = $this->dispatch($action);
if ( !empty($result) ) {
echo json_encode($result); // Send the result to the AJAX caller
}
$time_end = date('Y-m-d H:i:s');
$this->display_admin_notice("=== END $action $time_end ===\n");
}
}
wp_die();
}
/**
* Dispatch the actions
*
* @param string $action Action
* @return object Result to return to the caller
*/
public function dispatch($action) {
set_time_limit(self::IMPORT_TIMEOUT);
// Set the time zone
$timezone = get_option('timezone_string');
if ( !empty($timezone) ) {
date_default_timezone_set($timezone);
}
// Suspend the cache during the migration to avoid exhausted memory problem
wp_suspend_cache_addition(true);
wp_suspend_cache_invalidation(true);
// Default values
$this->plugin_options = array(
'automatic_empty' => 0,
'driver' => 'mysql',
'hostname' => 'localhost',
'port' => 3306,
'database' => null,
'username' => 'root',
'password' => '',
'sqlite_file' => '',
'prefix' => 'spip_',
'introtext' => 'in_content',
'archived_posts' => 'not_imported',
'skip_media' => 0,
'media_import_method' => 'http',
'url' => null,
'root_directory' => null,
'logo' => 'as_featured',
'import_external' => 0,
'import_duplicates' => 0,
'force_media_import' => 0,
'import_as_pages' => 0,
'timeout' => 5,
'logger_autorefresh' => 1,
);
$options = get_option('fgs2wp_options');
if ( is_array($options) ) {
$this->plugin_options = array_merge($this->plugin_options, $options);
}
// Check if the upload directory is writable
$upload_dir = wp_upload_dir();
if ( !is_writable($upload_dir['basedir']) ) {
$this->display_admin_error(__('The wp-content directory must be writable.', 'fg-spip-to-wp'));
}
// Requires at least WordPress 4.4
if ( version_compare(get_bloginfo('version'), '4.4', '<') ) {
$this->display_admin_error(sprintf(__('WordPress 4.4+ is required. Please <a href="%s">update WordPress</a>.', 'fg-spip-to-wp'), admin_url('update-core.php')));
}
elseif ( !empty($action) ) {
switch($action) {
// Delete content
case 'empty':
if ( check_admin_referer( 'empty', 'fgs2wp_nonce' ) ) { // Security check
if ($this->empty_database($_POST['empty_action'])) { // Empty WP database
$this->display_admin_notice(__('WordPress content removed', 'fg-spip-to-wp'));
} else {
$this->display_admin_error(__('Couldn\'t remove content', 'fg-spip-to-wp'));
}
wp_cache_flush();
}
break;
// Save database options
case 'save':
if ( check_admin_referer( 'parameters_form', 'fgs2wp_nonce' ) ) { // Security check
$this->save_plugin_options();
$this->display_admin_notice(__('Settings saved', 'fg-spip-to-wp'));
}
break;
// Test the database connection
case 'test_database':
if ( check_admin_referer( 'parameters_form', 'fgs2wp_nonce' ) ) { // Security check
// Save database options
$this->save_plugin_options();
if ( $this->test_database_connection() ) {
return array('status' => 'OK', 'message' => __('Connection successful', 'fg-spip-to-wp'));
} else {
return array('status' => 'Error', 'message' => __('Connection failed', 'fg-spip-to-wp') . '<br />' . __('See the errors in the log below', 'fg-spip-to-wp'));
}
}
break;
// Run the import
case 'import':
if ( check_admin_referer( 'parameters_form', 'fgs2wp_nonce' ) ) { // Security check
// Save database options
$this->save_plugin_options();
if ( $this->test_database_connection() ) {
// Automatic empty
if ( $this->plugin_options['automatic_empty'] ) {
if ($this->empty_database('all')) {
$this->display_admin_notice(__('WordPress content removed', 'fg-spip-to-wp'));
} else {
$this->display_admin_error(__('Couldn\'t remove content', 'fg-spip-to-wp'));
}
wp_cache_flush();
}
// Import content
$this->import();
}
}
break;
// Stop the import
case 'stop_import':
if ( check_admin_referer( 'parameters_form', 'fgs2wp_nonce' ) ) { // Security check
$this->stop_import();
}
break;
// Modify internal links
case 'modify_links':
if ( check_admin_referer( 'modify_links', 'fgs2wp_nonce' ) ) { // Security check
$result = $this->modify_links();
$this->display_admin_notice(sprintf(_n('%d internal link modified', '%d internal links modified', $result['links_count'], 'fg-spip-to-wp'), $result['links_count']));
}
break;
default:
// Do other actions
do_action('fgs2wp_dispatch', $action);
}
}
}
/**
* Display the admin page
*
*/
private function display_admin_page() {
$data = $this->plugin_options;
$data['title'] = __('Import SPIP', 'fg-spip-to-wp');
$data['description'] = __('This plugin will import categories, articles, news and images from a SPIP database into WordPress.<br />Compatible with SPIP from 1.8 to 3.2.', 'fg-spip-to-wp');
$data['description'] .= "<br />\n" . sprintf(__('For any issue, please read the <a href="%s" target="_blank">FAQ</a> first.', 'fg-spip-to-wp'), $this->faq_url);
$data['database_info'] = $this->get_database_info();
// Hook for modifying the admin page
$data = apply_filters('fgs2wp_pre_display_admin_page', $data);
// Load the CSS and Javascript
$this->enqueue_styles();
$this->enqueue_scripts();
include plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/admin-display.php';
// Hook for doing other actions after displaying the admin page
do_action('fgs2wp_post_display_admin_page');
}
/**
* Get the WordPress database info
*
* @return string Database info
*/
private function get_database_info() {
$posts_count = $this->count_posts('post');
$pages_count = $this->count_posts('page');
$media_count = $this->count_posts('attachment');
$cat_count = wp_count_terms('category', array('hide_empty' => 0));
$database_info =
sprintf(_n('%d category', '%d categories', $cat_count, 'fg-spip-to-wp'), $cat_count) . "<br />" .
sprintf(_n('%d post', '%d posts', $posts_count, 'fg-spip-to-wp'), $posts_count) . "<br />" .
sprintf(_n('%d page', '%d pages', $pages_count, 'fg-spip-to-wp'), $pages_count) . "<br />" .
sprintf(_n('%d media', '%d medias', $media_count, 'fg-spip-to-wp'), $media_count) . "<br />";
$database_info = apply_filters('fgs2wp_get_database_info', $database_info);
return $database_info;
}
/**
* Count the number of posts for a post type
* @param string $post_type
*/
public function count_posts($post_type) {
$count = 0;
$excluded_status = array('trash', 'auto-draft');
$tab_count = wp_count_posts($post_type);
foreach ( $tab_count as $key => $value ) {
if ( !in_array($key, $excluded_status) ) {
$count += $value;
}
}
return $count;
}
/**
* Add an help tab
*
*/
public function add_help_tab() {
$screen = get_current_screen();
$screen->add_help_tab(array(
'id' => 'fgs2wp_help_instructions',
'title' => __('Instructions', 'fg-spip-to-wp'),
'content' => '',
'callback' => array($this, 'help_instructions'),
));
$screen->add_help_tab(array(
'id' => 'fgs2wp_help_options',
'title' => __('Options', 'fg-spip-to-wp'),
'content' => '',
'callback' => array($this, 'help_options'),
));
$screen->set_help_sidebar('<a href="' . $this->faq_url . '" target="_blank">' . __('FAQ', 'fg-spip-to-wp') . '</a>');
}
/**
* Instructions help screen
*
* @return string Help content
*/
public function help_instructions() {
include plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/help-instructions.tpl.php';
}
/**
* Options help screen
*
* @return string Help content
*/
public function help_options() {
include plugin_dir_path( dirname( __FILE__ ) ) . 'admin/partials/help-options.tpl.php';
}
/**
* Open the connection on Spip database
*
* return boolean Connection successful or not
*/
protected function spip_connect() {
global $spip_db;
if ( !class_exists('PDO') ) {
$this->display_admin_error(__('PDO is required. Please enable it.', 'fg-spip-to-wp'));
return false;
}
try {
switch ( $this->plugin_options['driver'] ) {
case 'mysql':
// MySQL
$spip_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\''));
break;
case 'sqlite':
// SQLite
if ( !file_exists($this->plugin_options['sqlite_file']) ) {
$this->display_admin_error(__("Couldn't read the SPIP database SQLite file: ", 'fg-spip-to-wp') . $this->plugin_options['sqlite_file']);
return false;
}
$spip_db = new PDO('sqlite:' . $this->plugin_options['sqlite_file']);
break;
}
if ( defined('WP_DEBUG') && WP_DEBUG ) {
$spip_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Display SQL errors
}
} catch ( PDOException $e ) {
$this->display_admin_error(__('Couldn\'t connect to the SPIP database. Please check your parameters. And be sure the WordPress server can access the SPIP database.', 'fg-spip-to-wp') . "<br />\n" . $e->getMessage() . "<br />\n" . sprintf(__('Please read the <a href="%s" target="_blank">FAQ for the solution</a>.', 'fg-spip-to-wp'), $this->faq_url));
return false;
}
$this->spip_version = $this->get_spip_version();
$this->spip_charset = $this->get_spip_meta('charset');
$this->blob_encoding = $this->is_text_encoded_as_blob() ;
return true;
}
/**
* Execute a SQL query on the Spip database
*
* @param string $sql SQL query
* @return array Query result
*/
public function spip_query($sql) {
global $spip_db;
$result = array();
try {
$query = $spip_db->query($sql, PDO::FETCH_ASSOC);
if ( is_object($query) ) {
foreach ( $query as $row ) {
$result[] = $row;
}
}
} catch ( PDOException $e ) {
$this->display_admin_error(__('Error:', 'fg-spip-to-wp') . $e->getMessage());
}
return $result;
}
/**
* Delete all posts, medias and categories from the database
*
* @param string $action imported = removes only new imported posts
* all = removes all
* @return boolean
*/
private function empty_database($action) {
global $wpdb;
$result = true;
$wpdb->show_errors();
// Hook for doing other actions before emptying the database
do_action('fgs2wp_pre_empty_database', $action);
$sql_queries = array();
if ( $action == 'all' ) {
// Remove all content
$sql_queries[] = "TRUNCATE $wpdb->commentmeta";
$sql_queries[] = "TRUNCATE $wpdb->comments";
$sql_queries[] = "TRUNCATE $wpdb->term_relationships";
$sql_queries[] = "TRUNCATE $wpdb->termmeta";
$sql_queries[] = "TRUNCATE $wpdb->postmeta";
$sql_queries[] = "TRUNCATE $wpdb->posts";
$sql_queries[] = <<<SQL
-- Delete Terms
DELETE FROM $wpdb->terms
WHERE term_id > 1 -- non-classe
SQL;
$sql_queries[] = <<<SQL
-- Delete Terms taxonomies
DELETE FROM $wpdb->term_taxonomy
WHERE term_id > 1 -- non-classe
SQL;
$sql_queries[] = "ALTER TABLE $wpdb->terms AUTO_INCREMENT = 2";
$sql_queries[] = "ALTER TABLE $wpdb->term_taxonomy AUTO_INCREMENT = 2";
} else {
// (Re)create a temporary table with the IDs to delete
$sql_queries[] = <<<SQL
DROP TEMPORARY TABLE IF EXISTS {$wpdb->prefix}fg_data_to_delete;
SQL;
$sql_queries[] = <<<SQL
CREATE TEMPORARY TABLE IF NOT EXISTS {$wpdb->prefix}fg_data_to_delete (
`id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
SQL;
// Insert the imported posts IDs in the temporary table
$sql_queries[] = <<<SQL
INSERT IGNORE INTO {$wpdb->prefix}fg_data_to_delete (`id`)
SELECT post_id FROM $wpdb->postmeta
WHERE meta_key LIKE '_fgs2wp_%'
SQL;
// Delete the imported posts and related data
$sql_queries[] = <<<SQL
-- Delete Comments and Comment metas
DELETE c, cm
FROM $wpdb->comments c
LEFT JOIN $wpdb->commentmeta cm ON cm.comment_id = c.comment_ID
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE c.comment_post_ID = del.id;
SQL;
$sql_queries[] = <<<SQL
-- Delete Term relashionships
DELETE tr
FROM $wpdb->term_relationships tr
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE tr.object_id = del.id;
SQL;
$sql_queries[] = <<<SQL
-- Delete Posts Children and Post metas
DELETE p, pm
FROM $wpdb->posts p
LEFT JOIN $wpdb->postmeta pm ON pm.post_id = p.ID
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE p.post_parent = del.id
AND p.post_type != 'attachment'; -- Don't remove the old medias attached to posts
SQL;
$sql_queries[] = <<<SQL
-- Delete Posts and Post metas
DELETE p, pm
FROM $wpdb->posts p
LEFT JOIN $wpdb->postmeta pm ON pm.post_id = p.ID
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE p.ID = del.id;
SQL;
// Truncate the temporary table
$sql_queries[] = <<<SQL
TRUNCATE {$wpdb->prefix}fg_data_to_delete;
SQL;
// Insert the imported terms IDs in the temporary table
$sql_queries[] = <<<SQL
INSERT IGNORE INTO {$wpdb->prefix}fg_data_to_delete (`id`)
SELECT term_id FROM $wpdb->termmeta
WHERE meta_key LIKE '_fgs2wp_%'
SQL;
// Delete the imported terms and related data
$sql_queries[] = <<<SQL
-- Delete Terms, Term taxonomies and Term metas
DELETE t, tt, tm
FROM $wpdb->terms t
LEFT JOIN $wpdb->term_taxonomy tt ON tt.term_id = t.term_id
LEFT JOIN $wpdb->termmeta tm ON tm.term_id = t.term_id
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE t.term_id = del.id;
SQL;
// Truncate the temporary table
$sql_queries[] = <<<SQL
TRUNCATE {$wpdb->prefix}fg_data_to_delete;
SQL;
// Insert the imported comments IDs in the temporary table
$sql_queries[] = <<<SQL
INSERT IGNORE INTO {$wpdb->prefix}fg_data_to_delete (`id`)
SELECT comment_id FROM $wpdb->commentmeta
WHERE meta_key LIKE '_fgs2wp_%'
SQL;
// Delete the imported comments and related data
$sql_queries[] = <<<SQL
-- Delete Comments and Comment metas
DELETE c, cm
FROM $wpdb->comments c
LEFT JOIN $wpdb->commentmeta cm ON cm.comment_id = c.comment_ID
INNER JOIN {$wpdb->prefix}fg_data_to_delete del
WHERE c.comment_ID = del.id;
SQL;
}
// Execute SQL queries
if ( count($sql_queries) > 0 ) {
foreach ( $sql_queries as $sql ) {
$result &= $wpdb->query($sql);
}
}
// Hook for doing other actions after emptying the database
do_action('fgs2wp_post_empty_database', $action);
// Drop the temporary table
$wpdb->query("DROP TEMPORARY TABLE IF EXISTS {$wpdb->prefix}fg_data_to_delete;");
// Reset the SPIP import counters
update_option('fgs2wp_last_spip_article_id', 0);
update_option('fgs2wp_last_spip_news_id', 0);
update_option('fgs2wp_last_category_id', 0);
// Re-count categories and tags items
$this->terms_count();
// Update cache
$this->clean_cache();
delete_transient('wc_count_comments');
$this->optimize_database();
$this->progressbar->set_total_count(0);
$wpdb->hide_errors();
return ($result !== false);
}
/**
* Optimize the database
*
*/
protected function optimize_database() {
global $wpdb;
$sql = <<<SQL
OPTIMIZE TABLE
`$wpdb->commentmeta` ,
`$wpdb->comments` ,
`$wpdb->options` ,
`$wpdb->postmeta` ,
`$wpdb->posts` ,
`$wpdb->terms` ,
`$wpdb->term_relationships` ,
`$wpdb->term_taxonomy`,
`$wpdb->termmeta`
SQL;
$wpdb->query($sql);
}
/**
* Test the database connection
*
* @return boolean
*/
function test_database_connection() {
global $spip_db;
if ( $this->spip_connect() ) {
// Test that the "articles" table exists
if ( $this->table_exists('articles') ) {
$this->display_admin_notice(__('Connected with success to the SPIP database', 'fg-spip-to-wp'));
do_action('fgs2wp_post_test_database_connection');
return true;
} else {
$this->display_admin_error(__('Couldn\'t connect to the SPIP database. Please check your parameters. And be sure the WordPress server can access the SPIP database.', 'fg-spip-to-wp') . "<br />\n");
}
}
$spip_db = null;
return false;
}
/**
* Get some Spip information
*
*/
public function get_spip_info() {
$message = __('Spip data found:', 'fg-spip-to-wp') . "\n";
// Categories
$cat_count = $this->get_categories_count();
$message .= sprintf(_n('%d section', '%d sections', $cat_count, 'fg-spip-to-wp'), $cat_count) . "\n";
// Articles
$articles_count = $this->get_articles_count();
$message .= sprintf(_n('%d article', '%d articles', $articles_count, 'fg-spip-to-wp'), $articles_count) . "\n";
// News
$news_count = $this->get_news_count();
$message .= sprintf(_n('%d news', '%d news', $news_count, 'fg-spip-to-wp'), $news_count) . "\n";
$message = apply_filters('fgs2wp_pre_display_spip_info', $message);
$this->display_admin_notice($message);
}
/**
* Get the number of Spip categories
*
* @return int Number of categories
*/
private function get_categories_count() {
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT COUNT(*) AS nb
FROM ${prefix}rubriques r
";
$result = $this->spip_query($sql);
$cat_count = isset($result[0]['nb'])? $result[0]['nb'] : 0;
return $cat_count;
}
/**
* Get the number of Spip articles
*
* @return int Number of articles
*/
private function get_articles_count() {
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT COUNT(*) AS nb
FROM ${prefix}articles a
WHERE a.statut IN ('publie', 'prepa', 'prop')
";
$result = $this->spip_query($sql);
$articles_count = isset($result[0]['nb'])? $result[0]['nb'] : 0;
return $articles_count;
}
/**
* Get the number of Spip news
*
* @return int Number of news
*/
private function get_news_count() {
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT COUNT(*) AS nb
FROM ${prefix}breves b
WHERE b.statut IN ('publie', 'prepa', 'prop')
";
$result = $this->spip_query($sql);
$news_count = isset($result[0]['nb'])? $result[0]['nb'] : 0;
return $news_count;
}
/**
* Save the plugin options
*
*/
private function save_plugin_options() {
$this->plugin_options = array_merge($this->plugin_options, $this->validate_form_info());
update_option('fgs2wp_options', $this->plugin_options);
// Hook for doing other actions after saving the options
do_action('fgs2wp_post_save_plugin_options');
}
/**
* Validate POST info
*
* @return array Form parameters
*/
private function validate_form_info() {
// Add http:// before the URL if it is missing
$url = esc_url(filter_input(INPUT_POST, 'url', FILTER_SANITIZE_URL));
if ( !empty($url) && (preg_match('#^https?://#', $url) == 0) ) {
$url = 'http://' . $url;
}
return array(
'automatic_empty' => filter_input(INPUT_POST, 'automatic_empty', FILTER_VALIDATE_BOOLEAN),
'driver' => filter_input(INPUT_POST, 'driver', FILTER_SANITIZE_STRING),
'hostname' => filter_input(INPUT_POST, 'hostname', FILTER_SANITIZE_STRING),
'port' => filter_input(INPUT_POST, 'port', FILTER_SANITIZE_NUMBER_INT),
'database' => filter_input(INPUT_POST, 'database', FILTER_SANITIZE_STRING),
'username' => filter_input(INPUT_POST, 'username'),
'password' => filter_input(INPUT_POST, 'password'),
'sqlite_file' => filter_input(INPUT_POST, 'sqlite_file', FILTER_SANITIZE_STRING),
'prefix' => filter_input(INPUT_POST, 'prefix', FILTER_SANITIZE_STRING),
'introtext' => filter_input(INPUT_POST, 'introtext', FILTER_SANITIZE_STRING),
'archived_posts' => filter_input(INPUT_POST, 'archived_posts', FILTER_SANITIZE_STRING),
'skip_media' => filter_input(INPUT_POST, 'skip_media', FILTER_VALIDATE_BOOLEAN),
'media_import_method' => filter_input(INPUT_POST, 'media_import_method', FILTER_SANITIZE_STRING),
'url' => $url,
'root_directory' => filter_input(INPUT_POST, 'root_directory', FILTER_SANITIZE_STRING),
'logo' => filter_input(INPUT_POST, 'logo', FILTER_SANITIZE_STRING),
'import_external' => filter_input(INPUT_POST, 'import_external', FILTER_VALIDATE_BOOLEAN),
'import_duplicates' => filter_input(INPUT_POST, 'import_duplicates', FILTER_VALIDATE_BOOLEAN),
'force_media_import' => filter_input(INPUT_POST, 'force_media_import', FILTER_VALIDATE_BOOLEAN),
'import_as_pages' => filter_input(INPUT_POST, 'import_as_pages', FILTER_VALIDATE_BOOLEAN),
'timeout' => filter_input(INPUT_POST, 'timeout', FILTER_SANITIZE_NUMBER_INT),
'logger_autorefresh' => filter_input(INPUT_POST, 'logger_autorefresh', FILTER_VALIDATE_BOOLEAN),
);
}
/**
* Import
*
*/
private function import() {
if ( $this->spip_connect() ) {
$time_start = microtime(true);
define('WP_IMPORTING', true);
update_option('fgs2wp_stop_import', false, false); // Reset the stop import action
// To solve the issue of links containing ":" in multisite mode
kses_remove_filters();
// Check prerequesites before the import
$do_import = apply_filters('fgs2wp_pre_import_check', true);
if ( !$do_import) {
return;
}
$total_elements_count = $this->get_total_elements_count();
$this->progressbar->set_total_count($total_elements_count);
$this->post_type = ($this->plugin_options['import_as_pages'] == 1) ? 'page' : 'post';
$this->media_path = $this->get_image_path();
// Hook for doing other actions before the import
do_action('fgs2wp_pre_import');
// Categories
if ( !isset($this->premium_options['skip_categories']) || !$this->premium_options['skip_categories'] ) {
$cat_count = $this->import_categories();
$this->display_admin_notice(sprintf(_n('%d category imported', '%d categories imported', $cat_count, 'fg-spip-to-wp'), $cat_count));
}
// Set the list of previously imported categories
$this->imported_categories = $this->get_term_metas_by_metakey('_fgs2wp_old_category_id');
// Articles and medias
if ( !isset($this->premium_options['skip_articles']) || !$this->premium_options['skip_articles'] ) {
$this->import_articles();
}
// News
if ( !isset($this->premium_options['skip_news']) || !$this->premium_options['skip_news'] ) {
$this->import_news();
}
$this->display_admin_notice(sprintf(_n('%d post imported', '%d posts imported', $this->posts_count, 'fg-spip-to-wp'), $this->posts_count));
if ( $this->pages_count > 0 ) {
$this->display_admin_notice(sprintf(_n('%d page imported', '%d pages imported', $this->pages_count, 'fg-spip-to-wp'), $this->pages_count));
}
$this->display_admin_notice(sprintf(_n('%d media imported', '%d medias imported', $this->media_count, 'fg-spip-to-wp'), $this->media_count));
if ( !$this->import_stopped() ) {
// Hook for doing other actions after the import
do_action('fgs2wp_post_import');
}
// Hook for other notices
do_action('fgs2wp_import_notices');
// Debug info
if ( defined('WP_DEBUG') && WP_DEBUG ) {
$this->display_admin_notice(sprintf("Memory used: %s bytes<br />\n", number_format(memory_get_usage())));
$time_end = microtime(true);
$this->display_admin_notice(sprintf("Duration: %d sec<br />\n", $time_end - $time_start));
}
$this->display_admin_notice(__("Don't forget to modify internal links.", 'fg-spip-to-wp'));
$this->display_admin_notice("IMPORT COMPLETED");
wp_cache_flush();
}
}
/**
* Actions to do before the import
*
* @param bool $import_doable Can we start the import?
* @return bool Can we start the import?
*/
public function pre_import_check($import_doable) {
if ( $import_doable ) {
if ( !$this->plugin_options['skip_media'] ) {
if ( ($this->plugin_options['media_import_method'] == 'http') && empty($this->plugin_options['url']) ) {
$this->display_admin_error(__('The URL field is required to import the media.', 'fg-spip-to-wp'));
$import_doable = false;
} elseif ( ($this->plugin_options['media_import_method'] == 'local') && empty($this->plugin_options['root_directory']) ) {
$this->display_admin_error(__('The root directory field is required to import the media.', 'fg-spip-to-wp'));
$import_doable = false;
}
}
}
return $import_doable;
}
/**
* Get the number of elements to import
*
* @return int Number of elements to import
*/
private function get_total_elements_count() {
$count = 0;
// Categories
if ( !isset($this->premium_options['skip_categories']) || !$this->premium_options['skip_categories'] ) {
$count += $this->get_categories_count();
}
// Articles
if ( !isset($this->premium_options['skip_articles']) || !$this->premium_options['skip_articles'] ) {
$count += $this->get_articles_count();
}
// News
if ( !isset($this->premium_options['skip_news']) || !$this->premium_options['skip_news'] ) {
$count += $this->get_news_count();
}
$count = apply_filters('fgs2wp_get_total_elements_count', $count);
return $count;
}
/**
* Import categories
*
* @return int Number of categories imported
*/
private function import_categories() {
$imported_categories_count = 0;
$all_categories = array();
if ( $this->import_stopped() ) {
return 0;
}
$this->log(__('Importing categories...', 'fg-spip-to-wp'));
// Hook before importing the categories
do_action('fgs2wp_pre_import_categories');
do {
if ( $this->import_stopped() ) {
break;
}
$categories = $this->get_categories($this->chunks_size); // Get the Spip categories
$categories_count = count($categories);
if ( ($categories != null) && (count($categories) > 0) ) {
$all_categories = array_merge($all_categories, $categories);
// Insert the categories
$imported_categories_count += $this->insert_categories($categories);
}
} while ( ($categories != null) && ($categories_count > 0) );
$all_categories = apply_filters('fgs2wp_import_categories', $all_categories);
// Update the categories with their parent ids
// We need to do it in a second step because the children categories
// may have been imported before their parent
$this->update_parent_categories($all_categories);
if ( !$this->import_stopped() ) {
// Hook after importing all the categories
do_action('fgs2wp_post_import_categories', $all_categories);
}
return $imported_categories_count;
}
/**
* Insert a list of categories in the database
*
* @param array $categories List of categories
* @param string $taxonomy Taxonomy
* @param string $last_category_metakey Last category meta key
* @return int Number of inserted categories
*/
public function insert_categories($categories, $taxonomy='category', $last_category_metakey='fgs2wp_last_category_id') {
$cat_count = 0;
$processed_cat_count = count($categories);
$term_metakey = '_fgs2wp_old_category_id';
// Set the list of previously imported categories
$this->imported_categories = $this->get_term_metas_by_metakey($term_metakey);
$terms = array();
if ( $taxonomy == 'category') {
$terms[] = '1'; // unclassified category
}
foreach ( $categories as $category ) {
$category_id = $category['id_rubrique'];
$category['texte'] = $this->convert_spip1_longblob($category['texte']); // SPIP 1.x LONGBLOB
// Check if the category is already imported
if ( array_key_exists($category_id, $this->imported_categories) ) {
continue; // Do not import already imported category
}
// Store the last ID to resume the import where it left off
update_option($last_category_metakey, $category_id);
$parent_id = isset($this->imported_categories[$category['id_parent']])? $this->imported_categories[$category['id_parent']]: 0;
$new_cat_id = $this->insert_category($category, $term_metakey, $parent_id);
if ( is_wp_error($new_cat_id) ) {
continue;
}
$cat_count++;
$terms[] = $new_cat_id;
$this->imported_categories[$category_id] = $new_cat_id;
// Hook after importing the category
do_action('fgs2wp_post_import_category', $new_cat_id, $category);
}
$this->progressbar->increment_current_count($processed_cat_count);
// Update cache
if ( !empty($terms) ) {
wp_update_term_count_now($terms, $taxonomy);
$this->clean_cache($terms, $taxonomy);
}
return $cat_count;
}
/**
* Insert a category in the database
*
* @since 2.5.0
*
* @param array $category Category
* @param string $term_metakey Term meta_key
* @param int $parent_id Category parent ID
* @return int Category ID
*/
public function insert_category($category, $term_metakey, $parent_id=0) {
$category_id = $category['id_rubrique'];
$category['titre'] = $this->remove_id($category['titre']);
$category['titre'] = FG_Spip_to_WordPress_Tools::fix_encoding($category['titre']);
$category_slug = sanitize_title($category['titre']);
$category['texte'] = FG_Spip_to_WordPress_Tools::fix_encoding($category['texte']);
// Insert the category
$new_category = array(
'cat_name' => $category['titre'],
'category_description' => $this->spip_format($category['texte']),
'category_nicename' => $category_slug,
'category_parent' => $parent_id,
);
// Hook before inserting the category
$new_category = apply_filters('fgs2wp_pre_insert_category', $new_category, $category);
$new_cat_id = wp_insert_category($new_category, true);
if ( !is_wp_error($new_cat_id) ) {
// Store the Spip category ID
add_term_meta($new_cat_id, $term_metakey, $category_id, true);
// Hook after inserting the category
do_action('fgs2wp_post_insert_category', $new_cat_id, $category);
} else {
if ( isset($new_cat_id->error_data['term_exists']) ) {
// Store the Spip category ID
add_term_meta($new_cat_id->error_data['term_exists'], $term_metakey, $category_id, false);
}
}
return $new_cat_id;
}
/**
* Update the parent categories
*
* @param array $categories Categories
* @param string $taxonomy Taxonomy
*/
public function update_parent_categories($categories, $taxonomy='category') {
foreach ( $categories as $category ) {
// Parent category
if ( isset($this->imported_categories[$category['id_rubrique']]) && !empty($category['id_parent']) && isset($this->imported_categories[$category['id_parent']]) ) {
$cat_id = $this->imported_categories[$category['id_rubrique']];
$parent_cat_id = $this->imported_categories[$category['id_parent']];
wp_update_term($cat_id, $taxonomy, array('parent' => $parent_cat_id));
}
}
}
/**
* Convert SPIP format to HTML
*
* @param string $text SPIP text
* @return string HTML text
*/
public function spip_format($text) {
$text = str_replace('{{{', '<h2>', $text);
$text = str_replace('}}}', '</h2>', $text);
$text = str_replace('{{', '<strong>', $text);
$text = str_replace('}}', '</strong>', $text);
$text = str_replace('{', '<em>', $text);
$text = str_replace('}', '</em>', $text);
$text = preg_replace('#\[\->(.+?)\]#', "<a href=\"$1\">$1</a>", $text); // hyperlink with no anchor text, eg: [->http://www.spip.net]
$text = preg_replace('#\[([^[]+?)\->(.+?)\]#', "<a href=\"$2\">$1</a>", $text); // hyperlink, eg: [SPIP->http://www.spip.net]
$text = preg_replace('#\[([^[]*?)<-\]#', "<a name=\"$1\"></a>", $text); // anchor, eg: [anchor<-]
// Quote
$text = preg_replace('#<quote>(.*)</quote>#', '<blockquote>$1</blockquote>', $text);
$text = preg_replace('#<quote\|title=(.*?)(\|.*)?>#', '<blockquote>$1</blockquote>', $text);
// Line feeds
$text = preg_replace(",\r\n?,S", "\n", $text);
$text = preg_replace(",<p[>[:space:]],iS", "\n\n\\0", $text);
$text = preg_replace(",</p[>[:space:]],iS", "\\0\n\n", $text);
// Tables
$text = preg_replace(",^\n?[|],S", "\n\n|", $text);
$text = preg_replace(",\n\n+[|],S", "\n\n\n\n|", $text);
$text = preg_replace(",[|](\n\n+|\n?$),S", "|\n\n\n\n", $text);
$regs = array();
if (preg_match_all(',[^|](\n[|].*[|]\n)[^|],UmsS', $text, $regs, PREG_SET_ORDER)) {
foreach ($regs as $t) {
$text = str_replace($t[1], $this->process_table_shortcodes($t[1]), $text);
}
}
// Ordered and unordered lists
if ( (strpos($text, "\n-*") !== false) || (strpos($text, "\n-#") !== false) ) {
$text = $this->process_lists_shortcodes($text);
}
// Row starts
$text = $this->process_row_starts($text);
return $text;
}
/**
* Convert the unordered and ordered lists SPIP shortcodes
*
* @param string $text Text
* @return string Text
*/
private function process_lists_shortcodes($text) {
$parags = preg_split(",\n[[:space:]]*\n,S", $text);
$text = '';
$regs = array();
$pile_li = array();
$pile_type = array();
foreach ( $parags as $para ) {
$niveau = 0;
$lignes = explode("\n-", "\n" . $para);
$type = '';
$first_item = true;
foreach ( $lignes as $item ) {
if ( $first_item ) {
$text .= $item;
$first_item = false;
continue;
}
if ( preg_match(",^([*]*|[#]*)([^*#].*)$,sS", $item, $regs) ) {
$profond = strlen($regs[1]);
if ( $profond > 0 ) {
$ajout='';
$nouv_type = (substr($item,0,1) == '*') ? 'ul' : 'ol';
$change_type = ($type AND ($type <> $nouv_type) AND ($profond == $niveau)) ? 1 : 0;
$type = $nouv_type;
while ( $niveau > $profond - $change_type ) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
if (!$change_type) {
unset ($pile_li[$niveau]);
}
$niveau --;
}
if ( $niveau == $profond && !$change_type ) {
$ajout .= $pile_li[$niveau];
}
while ( $niveau < $profond ) {
if ( $niveau == 0 ) {
$ajout .= "\n\n";
}
$niveau ++;
$ajout .= "<$type>";
$pile_type[$niveau] = "</$type>";
}
$ajout .= "<li>";
$pile_li[$profond] = "</li>";
}
else {
$ajout = "\n-";
}
$text .= $ajout . $regs[2];
}
}
$ajout = '';
while ( $niveau > 0 ) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
$niveau --;
}
$text .= $ajout;
$text .= "\n\n";
}
return substr($text, 0, -2);
}
/**
* Convert the SPIP table shorcodes to HTML
*
* @since 2.14.0
*
* @param string $text Text
* @return string Text
*/
private function process_table_shortcodes($text) {
$regs = array();
$thead = array();
$cols = array();
preg_match_all(',([|].*)[|]\n,UmsS', $text, $regs, PREG_PATTERN_ORDER);
$lignes = array();
$debut_table = $summary = '';
$l = 0;
$numeric = true;
$reg_line1 = ',^(\|(' . _RACCOURCI_TH_SPAN . '))+$,sS';
$reg_line_all = ',^' . _RACCOURCI_TH_SPAN . '$,sS';
foreach ($regs[1] as $ligne) {
$l++;
if ($l == 1) {
$cap = array();
if (preg_match(',^\|\|([^|]*)(\|(.*))?$,sS', rtrim($ligne,'|'), $cap)) {
$l = 0;
$caption = trim($cap[1]);
if ( !empty($caption) ) {
$debut_table .= "<caption>".$caption."</caption>\n";
}
$summary = isset($cap[3])? ' summary="'.esc_html(trim($cap[3])).'"' : '';
}
else if ( preg_match($reg_line1, $ligne, $thead) ) {
preg_match_all('/\|([^|]*)/S', $ligne, $cols);
$ligne = '';
$cols = $cols[1];
$colspan = 1;
for ( $c = count($cols)-1; $c >= 0; $c-- ) {
$attr = '';
if ( $cols[$c] == '<' ) {
$colspan++;
} else {
if ( $colspan > 1 ) {
$attr = " colspan='$colspan'";
$colspan = 1;
}
$ligne = "<th scope='col'$attr>$cols[$c]</th>$ligne";
}
}
$debut_table .= "<thead><tr class='row_first'>" . $ligne."</tr></thead>\n";
$l = 0;
}
}
if ($l) {
if ( strpos($ligne,"\n-*") !== false OR strpos($ligne,"\n-#") !== false ) {
$ligne = $this->process_lists_shortcodes($ligne);
}
$ligne = preg_replace("/\n{2,}/", "<br />\n", $ligne);
preg_match_all('/\|([^|]*)/S', $ligne, $cols);
$lignes[] = $cols[1];
}
}
$rowspans = $numeric = array();
$n = count($lignes[0]);
$k = count($lignes);
for ( $i = 0; $i < $n; $i++ ) {
$align = true;
for ( $j = 0; $j < $k; $j++ ) {
$rowspans[$j][$i] = 1;
}
for ( $j = 0; $j < $k; $j++ ) {
$cell = trim($lignes[$j][$i]);
if ( preg_match($reg_line_all, $cell) ) {
$r = array();
if ( !preg_match('/^\d+([.,]?)\d*$/', $cell, $r) ) {
$align = '';
break;
}
elseif ($r[1]) {
$align = $r[1];
}
}
}
$numeric[$i] = !$align ? '' :
(" style='text-align: " .
(/* $align !== true ?"\"$align\"" : */ 'right') .
"'");
}
$html = '';
for ( $l = count($lignes)-1; $l >= 0; $l-- ) {
$cols = $lignes[$l];
$colspan = 1;
$ligne = '';
for ( $c = count($cols)-1; $c >= 0; $c-- ) {
$attr = isset($numeric[$c])? $numeric[$c] : '';
$cell = trim($cols[$c]);
if ( $cell == '<' ) {
$colspan++;
} elseif( $cell == '^' ) {
$rowspans[$l-1][$c] += $rowspans[$l][$c];
} else {
if( $colspan>1 ) {
$attr .= " colspan='$colspan'";
$colspan = 1;
}
if ( isset($rowspans[$l][$c]) && ($x=$rowspans[$l][$c]) > 1 ) {
$attr .= " rowspan='$x'";
}
$ligne = "\n<td" . $attr . '>' . $cols[$c] . '</td>' . $ligne;
}
}
$class = $this->alternate($l+1, 'even', 'odd');
$html = "<tr class='row_$class'>$ligne</tr>\n$html";
}
return "\n\n<table" . $summary . ">\n"
. $debut_table
. "<tbody>\n"
. $html
. "</tbody>\n"
. "</table>\n\n";
}
/**
* Filter |alternate
*
* @param int $i Row number
* @return mixed
*/
private function alternate($i) {
$num = func_num_args();
$args = func_get_args();
if ( $num == 2 && is_array($args[1]) ) {
$args = $args[1];
array_unshift($args,'');
$num = count($args);
}
return $args[(intval($i)-1)%($num-1)+1];
}
/**
* Replace the starts of the rows
*
* @since 2.14.0
*
* @param string $text Text
* @return string Text
*/
private function process_row_starts($text) {
$text = preg_replace(
array(
"/\n(----+|____+)/S",
"/\n-- */S",
"/\n_ +/S"
),
array(
"\n\n<hr />\n\n",
"\n<br />&mdash;&nbsp;",
"\n<br />"
),
$text
);
return $text;
}
/**
* Clean the cache
*
*/
public function clean_cache($terms = array()) {
delete_option("category_children");
clean_term_cache($terms, 'category');
}
/**
* Import articles
*
* @return bool Import successful or not
*/
private function import_articles() {
$this->log(__('Importing articles...', 'fg-spip-to-wp'));
// Anti-duplicate
$this->test_antiduplicate = false;
// Hook for doing other actions before the import
do_action('fgs2wp_pre_import_articles');
do {
if ( $this->import_stopped() ) {
break;
}
$posts = $this->get_articles($this->chunks_size); // Get the Spip articles
$posts_count = count($posts);
if ( is_array($posts) ) {
foreach ( $posts as $post ) {
$new_post_id = $this->import_article($post);
if ( $new_post_id === false ) {
return false;
}
// Hook for doing other actions after importing the post
do_action('fgs2wp_post_import_post', $new_post_id, $post, 'article');
}
}
$this->progressbar->increment_current_count($posts_count);
} while ( ($posts != null) && ($posts_count > 0) );
if ( !$this->import_stopped() ) {
// Hook for doing other actions after the import
do_action('fgs2wp_post_import_articles');
}
return true;
}
/**
* Import an article
*
* @since 2.0.0
*
* @param array $post Post data
* @return int new post ID | false | WP_Error
*/
public function import_article($post) {
$object_type = 'article';
$post['titre'] = FG_Spip_to_WordPress_Tools::fix_encoding($post['titre']);
$post['texte'] = $this->convert_spip1_longblob($post['texte']); // SPIP 1.x LONGBLOB
$post['texte'] = FG_Spip_to_WordPress_Tools::fix_encoding($post['texte']);
$post['chapo'] = FG_Spip_to_WordPress_Tools::fix_encoding($post['chapo']);
// Anti-duplicate
if ( !$this->test_antiduplicate ) {
sleep(2);
$test_post_id = $this->get_wp_post_id_from_spip_article_id($post['id']);
if ( !empty($test_post_id) ) {
$this->display_admin_error(__('The import process is still running. Please wait before running it again.', 'fg-spip-to-wp'));
return false;
}
$this->test_antiduplicate = true;
}
$post['titre'] = $this->remove_id($post['titre']); // Remove the ID from the title
// Hook for modifying the Spip post before processing
$post = apply_filters('fgs2wp_pre_process_post', $post, $object_type);
// Date
$post_date = $this->sanitize_date($post['date']);
$content = $post['texte'];
$chapo = $post['chapo'];
// Medias
if ( !$this->plugin_options['skip_media'] ) {
// Featured image
$featured_image = $this->get_featured_image($post['id'], $object_type);
list($featured_image, $post) = apply_filters('fgs2wp_pre_import_media', array($featured_image, $post));
$img_featured_image = '';
if ( !empty($featured_image) ) {
$img_featured_image = '<img src="' . $featured_image . '" />';
}
// Replace documents shortcodes
$chapo = $this->replace_document_shortcodes($chapo);
$content = $this->replace_document_shortcodes($content);
// Import media
$result = $this->import_media_from_content($img_featured_image . $chapo . $content, $post_date);
$post_media = $result['media'];
$this->media_count += $result['media_count'];
// Add the logo into the content
if ( ($this->plugin_options['logo'] != 'as_featured') && !empty($img_featured_image) ) {
$content = '<p>' . $img_featured_image . '</p>' . $content;
}
} else {
// Skip media
$post_media = array();
}
// Category
$categories_ids = array();
$category_id = $post['id_rubrique'];
if ( array_key_exists($category_id, $this->imported_categories) ) {
$categories_ids[] = $this->imported_categories[$category_id];
}
if ( count($categories_ids) == 0 ) {
$categories_ids[] = 1; // default category
}
// Header
$excerpt = '';
if ( !empty($chapo) ) {
switch ( $this->plugin_options['introtext'] ) {
case 'in_excerpt':
$excerpt = $chapo;
break;
case 'in_content':
$content = '<p class="post_excerpt">' . $chapo . '</p>' . "\n<!--more-->\n" . $content;
break;
case 'in_excerpt_and_content':
$excerpt = $chapo;
$content = '<p class="post_excerpt">' . $chapo . '</p>' . $content;
break;
}
}
// Process content
$excerpt = $this->process_content($excerpt, $post_media);
$content = $this->process_content($content, $post_media);
// Insert the post
$new_post = array(
'post_category' => $categories_ids,
'post_content' => $content,
'post_date' => $post_date,
'post_excerpt' => $excerpt,
'post_status' => $this->get_status($post['statut']),
'post_title' => $post['titre'],
'post_name' => sanitize_title($post['titre']),
'post_type' => $this->post_type,
'comment_status' => ($post['accepter_forum'] == 'non')? 'closed' : 'open',
);
// Hook for modifying the WordPress post just before the insert
$new_post = apply_filters('fgs2wp_pre_insert_post', $new_post, $post, $object_type);
$new_post_id = wp_insert_post($new_post, true);
// Increment the Spip last imported article ID
update_option('fgs2wp_last_spip_article_id', $post['id']);
if ( is_wp_error($new_post_id) ) {
$this->display_admin_error(sprintf(__('Article #%d:', 'fg-spip-to-wp'), $post['id']) . ' ' . $new_post_id->get_error_message());
} else {
// Add links between the post and its medias
$this->add_post_media($new_post_id, $new_post, $post_media, $this->plugin_options['logo'] != 'in_content');
// Add the Spip ID as a post meta in order to modify links after
add_post_meta($new_post_id, '_fgs2wp_old_article_id', $post['id'], true);
if ( $this->post_type == 'page' ) {
$this->pages_count++;
} else {
$this->posts_count++;
}
// Hook for doing other actions after inserting the post
do_action('fgs2wp_post_insert_post', $new_post_id, $post, $object_type);
}
return $new_post_id;
}
/**
* Convert a SPIP 1.x LONGBLOB to TEXT with the UTF8 encoding
*
* @since 2.10.0
*
* @param string $text Text
* @return string Text
*/
public function convert_spip1_longblob($text) {
if ( $this->blob_encoding && ($this->spip_charset != 'utf-8') ) {
$text = utf8_encode($text);
}
return $text;
}
/**
* Import news
*
* @return bool Import successful or not
*/
private function import_news() {
$this->log(__('Importing news...', 'fg-spip-to-wp'));
// Anti-duplicate
$this->test_antiduplicate = false;
// Hook for doing other actions before the import
do_action('fgs2wp_pre_import_news');
do {
if ( $this->import_stopped() ) {
break;
}
$posts = $this->get_news($this->chunks_size); // Get the Spip news
$posts_count = count($posts);
if ( is_array($posts) ) {
foreach ( $posts as $post ) {
$new_post_id = $this->import_one_news($post);
if ( $new_post_id === false ) {
return false;
}
// Hook for doing other actions after importing the post
do_action('fgs2wp_post_import_post', $new_post_id, $post, 'breve');
}
}
$this->progressbar->increment_current_count($posts_count);
} while ( ($posts != null) && ($posts_count > 0) );
if ( !$this->import_stopped() ) {
// Hook for doing other actions after the import
do_action('fgs2wp_post_import_news');
}
return true;
}
/**
* Import a news (breve)
*
* @since 2.0.0
*
* @param array $post Post data
* @return int new post ID | false | WP_Error
*/
public function import_one_news($post) {
$object_type = 'breve';
$post['titre'] = FG_Spip_to_WordPress_Tools::fix_encoding($post['titre']);
$post['texte'] = $this->convert_spip1_longblob($post['texte']); // SPIP 1.x LONGBLOB
$post['texte'] = FG_Spip_to_WordPress_Tools::fix_encoding($post['texte']);
// Anti-duplicate
if ( !$this->test_antiduplicate ) {
sleep(2);
$test_post_id = $this->get_wp_post_id_from_spip_news_id($post['id']);
if ( !empty($test_post_id) ) {
$this->display_admin_error(__('The import process is still running. Please wait before running it again.', 'fg-spip-to-wp'));
return false;
}
$this->test_antiduplicate = true;
}
// SPIP 2.0 fixes
if ( version_compare($this->spip_version, '3', '<') ) {
$post['titre'] = $this->remove_id($post['titre']); // Remove the ID from the title
}
// Hook for modifying the Spip post before processing
$post = apply_filters('fgs2wp_pre_process_post', $post, $object_type);
// Date
$post_date = $this->sanitize_date($post['date_heure']);
$content = $post['texte'];
// Medias
if ( !$this->plugin_options['skip_media'] ) {
// Featured image
$featured_image = $this->get_featured_image($post['id'], $object_type);
list($featured_image, $post) = apply_filters('fgs2wp_pre_import_media', array($featured_image, $post));
$img_featured_image = '';
if ( !empty($featured_image) ) {
$img_featured_image = '<img src="' . $featured_image . '" />';
}
// Replace documents shortcodes
$content = $this->replace_document_shortcodes($content);
// Import media
$result = $this->import_media_from_content($img_featured_image . $content, $post_date);
$post_media = $result['media'];
$this->media_count += $result['media_count'];
// Add the logo into the content
if ( ($this->plugin_options['logo'] != 'as_featured') ) {
$content = '<p>' . $img_featured_image . '</p>' . $content;
}
} else {
// Skip media
$post_media = array();
}
// Category
$categories_ids = $this->get_wp_category_ids($post['id_rubrique'], $this->imported_categories);
// Process content
$content = $this->process_content($content, $post_media);
// Insert the post
$new_post = array(
'post_category' => $categories_ids,
'post_content' => $content,
'post_excerpt' => '',
'post_date' => $post_date,
'post_status' => $this->get_status($post['statut']),
'post_title' => $post['titre'],
'post_name' => sanitize_title($post['titre']),
'post_type' => 'post',
);
// Hook for modifying the WordPress post just before the insert
$new_post = apply_filters('fgs2wp_pre_insert_post', $new_post, $post, $object_type);
$new_post_id = wp_insert_post($new_post, true);
// Increment the Spip last imported post ID
update_option('fgs2wp_last_spip_news_id', $post['id']);
if ( is_wp_error($new_post_id) ) {
$this->display_admin_error(sprintf(__('Article #%d:', 'fg-spip-to-wp'), $post['id']) . ' ' . $new_post_id->get_error_message());
} else {
// Add links between the post and its medias
$this->add_post_media($new_post_id, $new_post, $post_media, $this->plugin_options['logo'] != 'in_content');
// Add the Spip ID as a post meta in order to modify links after
add_post_meta($new_post_id, '_fgs2wp_old_news_id', $post['id'], true);
// Add the extra SPIP fields
if ( !empty($post['lien_titre']) ) {
add_post_meta($new_post_id, 'lien_titre', $post['lien_titre'], true);
}
if ( !empty($post['lien_url']) ) {
add_post_meta($new_post_id, 'lien_url', $post['lien_url'], true);
}
$this->posts_count++;
// Hook for doing other actions after inserting the post
do_action('fgs2wp_post_insert_post', $new_post_id, $post, $object_type);
}
return $new_post_id;
}
/**
* Get the WordPress status from the SPIP status
*
* @since 1.9.0
*
* @param string $spip_status SPIP status
* @return string WordPress status
*/
public function get_status($spip_status) {
switch ( $spip_status ) {
case 'publie': // published
$status = 'publish';
break;
case 'prop': // pending
$status = 'pending';
break;
default:
$status = 'draft';
}
return $status;
}
/**
* Remove the ID at the beginning of a string
*
* @param string $string String
* @return string String
*/
public function remove_id($string) {
$result = preg_replace('/^\d+\. /', '', $string);
return $result;
}
/**
* Replace the articles shortcodes (art, br) in the post content
*
* @since 2.30.0
*
* @param string $content Content
* @return string Content
*/
private function replace_articles_shortcodes($content) {
$matches = array();
// Replace the shortcodes like [anchor_text->art99] or [anchor_text->br99]
if ( preg_match_all('#\[(.*?)->(art|br)(\d+)\]#', $content, $matches, PREG_SET_ORDER) > 0 ) {
foreach ($matches as $match ) {
$anchor_text = $match[1];
$short_object_type = $match[2]; // art | br
$id = $match[3];
$object_type = ($short_object_type == 'br')? 'breve' : 'article';
if ( empty($anchor_text) ) {
$anchor_text = $this->get_article_or_news_title($id, $object_type);
}
$replacement = '<a href="' . $object_type . $id . '.html">' . $anchor_text . '</a>';
$content = preg_replace('#' . preg_quote($match[0]) . '#', $replacement, $content);
}
}
return $content;
}
/**
* Get the title of the article (or the news)
*
* @since 2.30.0
*
* @param int $id Object ID
* @param string $object_type Object type
* @return string Title
*/
private function get_article_or_news_title($id, $object_type) {
if ( $object_type == 'br' ) {
$title = $this->get_news_title($id);
} else {
$title = $this->get_article_title($id);
}
return $title;
}
/**
* Get a news title
*
* @since 2.30.0
*
* @param int $id News ID
* @return string Title
*/
private function get_news_title($id) {
$title = 'Breve ' . $id;
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT titre
FROM ${prefix}breves b
WHERE b.id_breve = '$id'
LIMIT 1
";
$result = $this->spip_query($sql);
if ( count($result) > 0 ) {
$title = $result[0]['titre'];
}
return $title;
}
/**
* Get an article title
*
* @since 2.30.0
*
* @param int $id Article ID
* @return string Title
*/
private function get_article_title($id) {
$title = 'Article ' . $id;
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT titre
FROM ${prefix}articles a
WHERE a.id_article = '$id'
LIMIT 1
";
$result = $this->spip_query($sql);
if ( count($result) > 0 ) {
$title = $result[0]['titre'];
}
return $title;
}
/**
* Replace the documents shortcodes (doc, img, emb, pdf) in the post content
* @param string $content Content
* @return string Content
*/
private function replace_document_shortcodes($content) {
$matches = array();
$matches_align = array();
// Import the medias that use the SPIP shortcodes <doc>, <img>, <emb> or <pdf>
if ( preg_match_all('#<(doc|img|emb|pdf)(\d+)(\|(.*?))?>#', $content, $matches, PREG_SET_ORDER) > 0 ) {
foreach ($matches as $match ) {
// $doc_embed_type = $match[1]; // doc | img | emb | pdf
$doc_id = $match[2];
$doc_align = isset($match[4])? $match[4]: '';
$document = $this->get_document($doc_id);
if ( !empty($document) ) {
$filename = $document['fichier'];
if ( !preg_match('/^http/', $document['fichier']) ) {
$filename = $this->media_path . $filename;
}
if ( preg_match('/^txt=(.*)/', $doc_align, $matches_align) ) {
$doc_title = $matches_align[1];
} elseif ( !empty($document['titre']) ) {
$doc_title = $document['titre'];
} else {
$doc_title = basename($document['fichier']);
}
$filetype = wp_check_filetype($filename);
// Description
$description = !empty($document['descriptif'])? ' data-description="' . $document['descriptif'] . '"' : '';
if ( preg_match('/image/', $filetype['type']) ) {
// Image
// Alignment
$alignment = '';
if ( !empty($doc_align) ) {
$alignment = ' align="' . $doc_align . '"';
}
if ( !empty($document['titre']) ) {
// With caption
$replacement = '<img src="' . $filename . '" alt="' . $doc_title . '" title="' . $document['titre'] . '" class="caption"' . $description . $alignment . ' />';
} else {
$replacement = '<img src="' . $filename . '" alt="' . $doc_title . '"' . $description . $alignment . ' />';
}
} elseif ( preg_match('#^https://www.youtube.com#', $filename) ) {
// Embed YouTube video
$replacement = '[embed]' . $filename . '[/embed]';
} else {
// Not an image
$replacement = '<a href="' . $filename . '"' . $description . '>' . $doc_title . '</a>';
}
$content = preg_replace('#' . preg_quote($match[0]) . '#', $replacement, $content);
}
}
}
// Import the medias that use the SPIP shortcodes [anchor_text->img]
if ( preg_match_all('#\[(.*?)->(doc|img|emb|pdf)(\d+)\]#', $content, $matches, PREG_SET_ORDER) > 0 ) {
foreach ($matches as $match ) {
$anchor_text = $match[1];
// $doc_embed_type = $match[2]; // doc | img | emb | pdf
$doc_id = $match[3];
$document = $this->get_document($doc_id);
if ( !empty($document) ) {
$filename = $this->media_path . $document['fichier'];
// Description
$description = !empty($document['descriptif'])? ' data-description="' . $document['descriptif'] . '"' : '';
$replacement = '<a href="' . $filename . '"' . $description . '>' . $anchor_text . '</a>';
$content = preg_replace('#' . preg_quote($match[0]) . '#', $replacement, $content);
}
}
}
return $content;
}
/**
* Get the matching WP category ID from a SPIP category
*
* @since 2.5.0
*
* @param int $category_id SPIP category ID
* @param array $imported_categories Mapping table of SPIP and WP categories IDs
* @return array List of categories IDs
*/
public function get_wp_category_ids($category_id, $imported_categories) {
$categories_ids = array();
if ( array_key_exists($category_id, $imported_categories) ) {
$categories_ids[] = $imported_categories[$category_id];
}
if ( count($categories_ids) == 0 ) {
$categories_ids[] = 1; // default category
}
return $categories_ids;
}
/**
* Stop the import
*
*/
public function stop_import() {
update_option('fgs2wp_stop_import', true);
}
/**
* Test if the import needs to stop
*
* @return boolean Import needs to stop or not
*/
public function import_stopped() {
return get_option('fgs2wp_stop_import');
}
/**
* Get Spip categories
*
* @param int $limit Number of categories max
* @return array of Categories
*/
protected function get_categories($limit=1000) {
$categories = array();
$prefix = $this->plugin_options['prefix'];
$last_category_id = (int)get_option('fgs2wp_last_category_id'); // to restore the import where it left
$sql = "
SELECT r.id_rubrique, r.id_parent, r.titre, r.descriptif, r.texte
FROM ${prefix}rubriques r
WHERE r.id_rubrique > '$last_category_id'
ORDER BY r.id_rubrique
LIMIT $limit
";
$sql = apply_filters('fgs2wp_get_categories_sql', $sql, $prefix);
$categories = $this->spip_query($sql);
$categories = apply_filters('fgs2wp_get_categories', $categories);
return $categories;
}
/**
* Get Spip articles
*
* @param int $limit Number of articles max
* @return array of articles
*/
protected function get_articles($limit=1000) {
$articles = array();
$last_spip_article_id = (int)get_option('fgs2wp_last_spip_article_id'); // to restore the import where it left
$prefix = $this->plugin_options['prefix'];
// Hooks for adding extra cols and extra joins
$extra_cols = apply_filters('fgs2wp_get_posts_add_extra_cols', '', 'article');
$extra_joins = apply_filters('fgs2wp_get_posts_add_extra_joins', '', 'article');
$sql = "
SELECT a.id_article AS id, a.titre, a.id_rubrique, a.chapo, a.texte, a.date, a.statut, a.visites, a.accepter_forum
$extra_cols
FROM ${prefix}articles a
$extra_joins
WHERE a.statut NOT IN ('refuse', 'poubelle') -- don't get the cancelled and the removed articles
AND a.id_article > '$last_spip_article_id'
ORDER BY a.id_article
LIMIT $limit
";
$sql = apply_filters('fgs2wp_get_posts_sql', $sql, $prefix, $extra_cols, $extra_joins, $last_spip_article_id, $limit);
$articles = $this->spip_query($sql);
return $articles;
}
/**
* Get Spip news
*
* @param int $limit Number of news max
* @return array of news
*/
protected function get_news($limit=1000) {
$news = array();
$last_spip_news_id = (int)get_option('fgs2wp_last_spip_news_id'); // to restore the import where it left
$prefix = $this->plugin_options['prefix'];
// Hooks for adding extra cols and extra joins
$extra_cols = apply_filters('fgs2wp_get_posts_add_extra_cols', '', 'breve');
$extra_joins = apply_filters('fgs2wp_get_posts_add_extra_joins', '', 'breve');
$sql = "
SELECT b.id_breve AS id, b.titre, b.id_rubrique, b.texte, b.date_heure, b.statut, b.lien_titre, b.lien_url
$extra_cols
FROM ${prefix}breves b
$extra_joins
WHERE b.statut NOT IN ('refuse', 'poubelle') -- don't get the cancelled and the removed news
AND b.id_breve > '$last_spip_news_id'
ORDER BY b.id_breve
LIMIT $limit
";
$sql = apply_filters('fgs2wp_get_posts_sql', $sql, $prefix, $extra_cols, $extra_joins, $last_spip_news_id, $limit);
$news = $this->spip_query($sql);
return $news;
}
/**
* Get the featured image of an article or from a news
*
* @param int $post_id
* @param string $object_type article | breve
* @return string Image path
*/
protected function get_featured_image($post_id, $object_type) {
$images_path = trailingslashit($this->get_media_root_path()) . $this->media_path;
// Object type
switch ( $object_type ) {
case 'article': $prefix = 'arton'; break;
case 'breve': $prefix = 'breveon'; break;
default: return ''; // unknown type
}
// Extensions
$extensions = array('jpg', 'JPG', 'png', 'PNG', 'gif', 'GIF');
foreach ( $extensions as $extension ) {
$image_file_path = $images_path . $prefix . $post_id . '.' . $extension;
if ( $this->file_exists($image_file_path) ) {
return $image_file_path;
}
}
return '';
}
/**
* Get the media root path
*
* @since 2.3.0
*
* @return string Media root path
*/
public function get_media_root_path() {
$path = '';
switch ( $this->plugin_options['media_import_method'] ) {
case 'http':
$path = $this->plugin_options['url'];
break;
case 'local':
$path = $this->plugin_options['root_directory'];
break;
}
return $path;
}
/**
* Test if a file exists
*
* @since 2.3.0
*
* @param string $filePath
* @return boolean True if the file exists
*/
public function file_exists($filePath) {
switch ( $this->plugin_options['media_import_method'] ) {
case 'http':
return $this->url_exists($filePath);
case 'local':
return file_exists($filePath);
}
}
/**
* Test if a remote file exists
*
* @param string $filePath
* @return boolean True if the file exists
*/
public function url_exists($filePath) {
$url = str_replace(' ', '%20', $filePath);
// Try the get_headers method
$headers = @get_headers($url);
$result = preg_match("/200/", $headers[0]);
if ( !$result && strpos($filePath, 'https:') !== 0 ) {
// Try the fsock method
$url = str_replace('http://', '', $url);
if ( strstr($url, '/') ) {
$url = explode('/', $url, 2);
$url[1] = '/' . $url[1];
} else {
$url = array($url, '/');
}
$fh = fsockopen($url[0], 80);
if ( $fh ) {
fputs($fh,'GET ' . $url[1] . " HTTP/1.1\nHost:" . $url[0] . "\n");
fputs($fh,"User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36\n\n");
$response = fread($fh, 22);
fclose($fh);
$result = (strpos($response, '200') !== false);
} else {
$result = false;
}
}
return $result;
}
/**
* Get the image path
*
* @return string Image path
*/
public function get_image_path() {
$dir_img = $this->get_spip_meta('dir_img');
if ( empty($dir_img) ) {
$dir_img = 'IMG/';
}
return $dir_img;
}
/**
* Get the SPIP version
*
* @return string SPIP version
*/
private function get_spip_version() {
$version = 0;
$raw_plugin_info = $this->get_spip_meta('plugin');
if ( strpos($raw_plugin_info, 'a:') !== false ) {
$plugin_info = @unserialize($raw_plugin_info);
if ( !$plugin_info ) {
$plugin_info = @unserialize(utf8_decode($raw_plugin_info));
}
$version = isset($plugin_info['SPIP']['version'])? $plugin_info['SPIP']['version']: 0;
} else {
$version_installee = $this->get_spip_meta('version_installee');
$version = !empty($version_installee)? $version_installee: 0;
}
return $version;
}
/**
* Get the meta value from the SPIP meta table
*
* @param string $meta_key
* @return string meta value
*/
public function get_spip_meta($meta_key) {
$meta_value = '';
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT m.valeur
FROM ${prefix}meta m
WHERE m.nom = '$meta_key'
LIMIT 1
";
$result = $this->spip_query($sql);
if ( isset($result[0]['valeur']) ) {
$meta_value = $result[0]['valeur'];
}
return $meta_value;
}
/**
* Test if the texts are encoded as blob
*
* @return bool
*/
private function is_text_encoded_as_blob() {
global $spip_db;
$blob_encoded = false;
$prefix = $this->plugin_options['prefix'];
$table = 'articles';
$column = 'texte';
switch ( $this->plugin_options['driver'] ) {
case 'mysql':
$sql = "SHOW COLUMNS FROM ${prefix}${table} LIKE '$column'";
break;
case 'sqlite':
$sql = "PRAGMA table_info(${prefix}${table})";
break;
}
$query = $spip_db->query($sql, PDO::FETCH_ASSOC);
if ( $query !== false ) {
if ( $this->plugin_options['driver'] == 'sqlite' ) {
// SQLite
$result = $query->fetchAll();
foreach ( $result as $row ) {
if ( isset($row['name']) && ($row['name'] == $column) ) {
if ( preg_match('/blob/', $row['type']) ) {
$blob_encoded = true;
}
break;
}
}
} else {
// MySQL
$result = $query->fetch();
if ( isset($result['Type']) && preg_match('/blob/', $result['Type']) ) {
$blob_encoded = true;
}
}
}
return $blob_encoded;
}
/**
* Import post medias from content
*
* @param string $content post content
* @param date $post_date Post date (for storing media)
* @param array $options Options
* @return array:
* array media: Medias imported
* int media_count: Medias count
*/
public function import_media_from_content($content, $post_date, $options=array()) {
$media = array();
$media_count = 0;
$matches = array();
$alt_matches = array();
$title_matches = array();
$description_matches = array();
if ( preg_match_all('#<(img|a)(.*?)(src|href)="(.*?)"(.*?)>#', $content, $matches, PREG_SET_ORDER) > 0 ) {
if ( is_array($matches) ) {
foreach ($matches as $match ) {
$filename = $match[4];
$other_attributes = $match[2] . $match[5];
// Image Alt
$image_alt = '';
if (preg_match('#alt="(.*?)"#', $other_attributes, $alt_matches) ) {
$image_alt = wp_strip_all_tags(stripslashes($alt_matches[1]), true);
}
// Image caption
$image_caption = '';
if (preg_match('#title="(.*?)"#', $other_attributes, $title_matches) ) {
$image_caption = $title_matches[1];
}
// Image description
$image_description = '';
if (preg_match('#data-description="(.*?)"#', $other_attributes, $description_matches) ) {
$image_description = $description_matches[1];
}
$attachment_id = $this->import_media($image_alt, $filename, $post_date, $options, $image_caption, $image_description);
if ( $attachment_id !== false ) {
$media_count++;
$media[$filename] = $attachment_id;
}
}
}
}
return array(
'media' => $media,
'media_count' => $media_count
);
}
/**
* Import a media
*
* @param string $name Image name
* @param string $filename Image URL
* @param date $date Date
* @param array $options Options
* @param string $image_caption Image caption
* @param string $image_description Image description
* @return int attachment ID or false
*/
public function import_media($name, $filename, $date, $options=array(), $image_caption='', $image_description='') {
if ( $date == '0000-00-00 00:00:00' ) {
$date = date('Y-m-d H:i:s');
}
$import_external = ($this->plugin_options['import_external'] == 1) || (isset($options['force_external']) && $options['force_external'] );
$filename = urldecode(html_entity_decode($filename)); // for filenames with spaces or accents
$filetype = wp_check_filetype($filename);
if ( empty($filetype['type']) || ($filetype['type'] == 'text/html') ) { // Unrecognized file type
return false;
}
$media_root_path = $this->get_media_root_path();
// Upload the file from the Spip web site to WordPress upload dir
if ( preg_match('/^http/', $filename) ) {
if ( $import_external || // External file
preg_match('#^' . $media_root_path . '#', $filename) // Local file
) {
$old_filename = $filename;
} else {
return false;
}
} elseif ( strpos($filename, $media_root_path) !== 0 ) { // Don't add the media_root_path if it has already been added
if ( strpos($filename, '/') === 0 ) { // Avoid a double slash
$old_filename = untrailingslashit($media_root_path) . $filename;
} else {
$old_filename = trailingslashit($media_root_path) . $filename;
}
} else {
$old_filename = $filename;
}
if ( $this->plugin_options['media_import_method'] == 'http' ) {
$old_filename = str_replace(" ", "%20", $old_filename); // for filenames with spaces
}
$img_dir = strftime('%Y/%m', strtotime($date));
$uploads = wp_upload_dir($img_dir);
$new_upload_dir = $uploads['path'];
$new_filename = $filename;
if ( $this->plugin_options['import_duplicates'] == 1 ) {
// Images with duplicate names
$new_filename = preg_replace('#.*'. untrailingslashit($this->media_path) . '/#', '', $new_filename);
$new_filename = str_replace('http://', '', $new_filename);
$new_filename = str_replace('/', '_', $new_filename);
}
$basename = basename($new_filename);
$basename = sanitize_file_name($basename);
$new_full_filename = $new_upload_dir . '/' . $basename;
if ( $this->plugin_options['force_media_import'] || !file_exists($new_full_filename) || (filesize($new_full_filename) == 0) ) {
// print "Copy \"$old_filename\" => $new_full_filename<br />";
switch ( $this->plugin_options['media_import_method'] ) {
case 'http':
// HTTP remote copy
if ( ! @$this->remote_copy($old_filename, $new_full_filename) ) {
$error = error_get_last();
$error_message = $error['message'];
$this->display_admin_error("Can't copy $old_filename to $new_full_filename : $error_message");
return false;
}
break;
case 'local':
// Local copy
if ( !copy($old_filename, $new_full_filename) ) {
$error = error_get_last();
$error_message = $error['message'];
$this->display_admin_error("Can't copy $old_filename to $new_full_filename : $error_message");
return false;
}
break;
}
}
$post_title = !empty($name)? $name : preg_replace('/\.[^.]+$/', '', $basename);
// Image Alt
$image_alt = '';
if ( !empty($name) ) {
$image_alt = wp_strip_all_tags(stripslashes($name), true);
}
// GUID
$upload_dir = wp_upload_dir();
$guid = str_replace($upload_dir['basedir'], $upload_dir['baseurl'], $new_full_filename);
$attachment_id = $this->insert_attachment($post_title, $basename, $new_full_filename, $guid, $date, $filetype['type'], $image_alt, $image_caption, $image_description);
return $attachment_id;
}
/**
* 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;
}
}
/**
* Save the attachment and generates its metadata
*
* @param string $attachment_title Attachment name
* @param string $basename Original attachment filename
* @param string $new_full_filename New attachment filename with path
* @param string $guid GUID
* @param date $date Date
* @param string $filetype File type
* @param string $image_alt Image description
* @param string $image_caption Image caption
* @param string $image_description Image description
* @return int|false Attachment ID or false
*/
public function insert_attachment($attachment_title, $basename, $new_full_filename, $guid, $date, $filetype, $image_alt='', $image_caption='', $image_description='') {
$post_name = 'attachment-' . sanitize_title($attachment_title); // Prefix the post name to avoid wrong redirect to a post with the same name
// If the attachment does not exist yet, insert it in the database
$attachment_id = 0;
$attachment = $this->get_attachment_from_name($post_name);
if ( $attachment ) {
$attached_file = basename(get_attached_file($attachment->ID));
if ( $attached_file == $basename ) { // Check if the filename is the same (in case of the legend is not unique)
$attachment_id = $attachment->ID;
}
}
if ( $attachment_id == 0 ) {
$attachment_data = array(
'guid' => $guid,
'post_date' => $date,
'post_mime_type' => $filetype,
'post_name' => $post_name,
'post_title' => $attachment_title,
'post_status' => 'inherit',
'post_content' => $image_description,
'post_excerpt' => $image_caption,
);
$attachment_id = wp_insert_attachment($attachment_data, $new_full_filename);
add_post_meta($attachment_id, '_fgs2wp_imported', 1, true); // To delete the imported attachments
}
if ( !empty($attachment_id) ) {
if ( preg_match('/(image|audio|video)/', $filetype) ) { // Image, audio or video
// 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( $attachment_id, $new_full_filename );
wp_update_attachment_metadata($attachment_id, $attach_data);
// Image Alt
if ( !empty($image_alt) ) {
update_post_meta($attachment_id, '_wp_attachment_image_alt', addslashes($image_alt)); // update_post_meta expects slashed
}
}
return $attachment_id;
} else {
return false;
}
}
/**
* Get a document by its ID
*
* @param int $doc_id SPIP document ID
* @return array document data
*/
private function get_document($doc_id) {
$document = array();
$prefix = $this->plugin_options['prefix'];
$sql = "
SELECT d.id_document, d.fichier, d.titre, d.descriptif, d.taille, d.date
FROM ${prefix}documents d
WHERE d.id_document = '$doc_id'
LIMIT 1
";
$documents = $this->spip_query($sql);
if ( isset($documents[0]) ) {
$document = $documents[0];
}
return $document;
}
/**
* Process the post content
*
* @param string $content Post content
* @param array $post_media Post medias
* @return string Processed post content
*/
public function process_content($content, $post_media=array()) {
if ( !empty($content) ) {
$content = $this->replace_articles_shortcodes($content);
$content = $this->spip_format($content);
$content = preg_replace("/\\\\+'/", "'", $content); // Fix the multiple escapes of '
// Replace media URLs with the new URLs
$content = $this->process_content_media_links($content, $post_media);
// Replace video links
$content = $this->process_video_links($content);
// For importing backslashes
$content = addslashes($content);
$content = apply_filters('fgs2wp_process_content', $content);
}
return $content;
}
/**
* Replace media URLs with the new URLs
*
* @param string $content Post content
* @param array $post_media Post medias
* @return string Processed post content
*/
private function process_content_media_links($content, $post_media) {
$matches = array();
$matches_caption = array();
if ( is_array($post_media) ) {
// Get the attachments attributes
$attachments_found = false;
$medias = array();
foreach ( $post_media as $old_filename => $attachment_id ) {
$media = array();
$media['attachment_id'] = $attachment_id;
$media['url_old_filename'] = urlencode($old_filename); // for filenames with spaces
if ( preg_match('/image/', get_post_mime_type($attachment_id)) ) {
// Image
$image_src = wp_get_attachment_image_src($attachment_id, 'full');
$media['new_url'] = $image_src[0];
$media['width'] = $image_src[1];
$media['height'] = $image_src[2];
} else {
// Other media
$media['new_url'] = wp_get_attachment_url($attachment_id);
}
$medias[$old_filename] = $media;
$attachments_found = true;
}
if ( $attachments_found ) {
// Remove the links from the content
$this->post_link_count = 0;
$this->post_link = array();
$content = preg_replace_callback('#<(a) (.*?)(href)=(.*?)</a>#i', array($this, 'remove_links'), $content);
$content = preg_replace_callback('#<(img) (.*?)(src)=(.*?)>#i', array($this, 'remove_links'), $content);
// Process the stored medias links
foreach ($this->post_link as &$link) {
$new_link = $link['old_link'];
$alignment = '';
if ( preg_match('/(align="|float: )(left|right|center)/', $new_link, $matches) ) {
$alignment = 'align' . $matches[2];
}
if ( preg_match_all('#(src|href)="(.*?)"#i', $new_link, $matches, PREG_SET_ORDER) ) {
$caption = '';
foreach ( $matches as $match ) {
$old_filename = $match[2];
$link_type = ($match[1] == 'src')? 'img': 'a';
if ( array_key_exists($old_filename, $medias) ) {
$media = $medias[$old_filename];
if ( array_key_exists('new_url', $media) ) {
if ( (strpos($new_link, $old_filename) > 0) || (strpos($new_link, $media['url_old_filename']) > 0) ) {
// URL encode the filename
$new_filename = basename($media['new_url']);
$encoded_new_filename = rawurlencode($new_filename);
$new_url = str_replace($new_filename, $encoded_new_filename, $media['new_url']);
$new_link = preg_replace('#(' . preg_quote($old_filename) . '|' . preg_quote($media['url_old_filename']) . ')#', $new_url, $new_link, 1);
if ( $link_type == 'img' ) { // images only
// Define the width and the height of the image if it isn't defined yet
if ((strpos($new_link, 'width=') === false) && (strpos($new_link, 'height=') === false)) {
$width_assertion = isset($media['width']) && ($media['width'] != 0)? ' width="' . $media['width'] . '"' : '';
$height_assertion = isset($media['height']) && ($media['height'] != 0)? ' height="' . $media['height'] . '"' : '';
} else {
$width_assertion = '';
$height_assertion = '';
}
// Caption shortcode
if ( preg_match('/class=".*caption.*?"/', $link['old_link']) ) {
if ( preg_match('/title="(.*?)"/', $link['old_link'], $matches_caption) ) {
$caption_value = str_replace('%', '%%', $matches_caption[1]);
$align_value = ($alignment != '')? $alignment : 'alignnone';
$caption = '[caption id="attachment_' . $media['attachment_id'] . '" align="' . $align_value . '"' . $width_assertion . ']%s' . $caption_value . '[/caption]';
}
}
$align_class = ($alignment != '')? $alignment . ' ' : '';
$new_link = preg_replace('#<img(.*?)( class="(.*?)")?(.*) />#', "<img$1 class=\"$3 " . $align_class . 'size-full wp-image-' . $media['attachment_id'] . "\"$4" . $width_assertion . $height_assertion . ' />', $new_link);
}
}
}
}
}
// Add the caption
if ( $caption != '' ) {
$new_link = sprintf($caption, $new_link);
}
}
$link['new_link'] = $new_link;
}
// Reinsert the converted medias links
$content = preg_replace_callback('#__fg_link_(\d+)__#', array($this, 'restore_links'), $content);
}
}
return $content;
}
/**
* Remove all the links from the content and replace them with a specific tag
*
* @param array $matches Result of the preg_match
* @return string Replacement
*/
private function remove_links($matches) {
$this->post_link[] = array('old_link' => $matches[0]);
return '__fg_link_' . $this->post_link_count++ . '__';
}
/**
* Restore the links in the content and replace them with the new calculated link
*
* @param array $matches Result of the preg_match
* @return string Replacement
*/
private function restore_links($matches) {
$link = $this->post_link[$matches[1]];
$new_link = array_key_exists('new_link', $link)? $link['new_link'] : $link['old_link'];
return $new_link;
}
/**
* Add a link between a media and a post (parent id + thumbnail)
*
* @param int $post_id Post ID
* @param array $post_data Post data
* @param array $post_media Post medias IDs
* @param boolean $set_featured_image Set the featured image?
*/
public function add_post_media($post_id, $post_data, $post_media, $set_featured_image=true) {
$thumbnail_is_set = false;
if ( is_array($post_media) ) {
foreach ( $post_media as $attachment_id ) {
$attachment = get_post($attachment_id);
if ( !empty($attachment) ) {
$attachment->post_parent = $post_id; // Attach the post to the media
$attachment->post_date = $post_data['post_date'] ;// Define the media's date
wp_update_post($attachment);
// Set the featured image. If not defined, it is the first image of the content.
if ( $set_featured_image && !$thumbnail_is_set ) {
set_post_thumbnail($post_id, $attachment_id);
$thumbnail_is_set = true;
}
}
}
}
}
/**
* Modify the video links
*
* @param string $content Content
* @return string Content
*/
private function process_video_links($content) {
if ( strpos($content, '{"video"') !== false ) {
$content = preg_replace('/(<p>)?{"video":"(.*?)".*?}(<\/p>)?/', "$2", $content);
}
return $content;
}
/**
* Modify the internal links of all posts
*
* @return array:
* int links_count: Links count
*/
private function modify_links() {
$links_count = 0;
$step = 1000; // to limit the results
$offset = 0;
$matches = array();
// Set the list of previously imported categories
$this->imported_categories = $this->get_term_metas_by_metakey('_fgs2wp_old_category_id');
// Hook for doing other actions before modifying the links
do_action('fgs2wp_pre_modify_links');
do {
$args = array(
'numberposts' => $step,
'offset' => $offset,
'orderby' => 'ID',
'order' => 'ASC',
'post_type' => 'any',
'post_status' => 'any',
);
$posts = get_posts($args);
foreach ( $posts as $post ) {
$post = apply_filters('fgs2wp_post_get_post', $post); // Used to translate the links
$content = $post->post_content;
if ( preg_match_all('#<a(.*?)href="(.*?)"(.*?)>#', $content, $matches, PREG_SET_ORDER) > 0 ) {
if ( is_array($matches) ) {
foreach ( $matches as $match ) {
$link = $match[2];
list($link_without_anchor, $anchor_link) = $this->split_anchor_link($link); // Split the anchor link
// Is it an internal link ?
if ( !empty($link_without_anchor) && $this->is_internal_link($link_without_anchor) ) {
$new_link = '';
if ( preg_match('/^rub(\d+)$/', $link_without_anchor, $matches) ) { // Is it a link to a category?
$new_link = $this->get_category_link($matches[1], $post);
} else {
list($article_id, $object_type) = $this->find_article_id_in_link($link_without_anchor); // Is it a link to an article or to a news?
if ( $article_id != 0 ) {
$new_link = $this->get_article_link($article_id, $object_type, $post);
}
}
if ( !empty($new_link) ) {
if ( !empty($anchor_link) ) {
$new_link .= '#' . $anchor_link;
}
$content = str_replace("href=\"$link\"", "href=\"$new_link\"", $content);
// Update the post
wp_update_post(array(
'ID' => $post->ID,
'post_content' => $content,
));
$links_count++;
}
}
}
}
}
}
$offset += $step;
} while ( ($posts != null) && (count($posts) > 0) );
// Hook for doing other actions after modifying the links
do_action('fgs2wp_post_modify_links');
return array('links_count' => $links_count);
}
/**
* Test if the link is an internal link or not
*
* @since 2.36.3
*
* @param string $link
* @return bool
*/
private function is_internal_link($link) {
$result = (preg_match("#^".$this->plugin_options['url']."#", $link) > 0) ||
(preg_match("#^(http|//)#", $link) == 0);
return $result;
}
/**
* Find an article ID in a link
*
* @param string $link Link
* @return array [Article ID, Object type]
*/
private function find_article_id_in_link($link) {
$article_id = 0;
$object_type = 'article';
$matches = array();
if ( is_numeric($link) ) {
$article_id = $link;
} elseif ( preg_match('/(article|breve)(\d+)/', $link, $matches)) { // article12.html or spip.php?article12 or breve12.html or spip.php?breve12
$object_type = $matches[1];
$article_id = $matches[2];
} elseif ( preg_match('/id_(article|breve)=(\d+)/', $link, $matches)) { // spip.php?page=article&id_article=12 or spip.php?page=breve&id_breve=12
$object_type = $matches[1];
$article_id = $matches[2];
}
return array($article_id, $object_type);
}
/**
* Get the WordPress article link matching the SPIP article ID
*
* @since 2.18.0
*
* @param int $article_id SPIP article ID
* @param string $object_type article | breve
* @param array $post Post
* @return string New link
*/
private function get_article_link($article_id, $object_type, $post) {
$new_link = '';
if ( $object_type == 'breve' ) {
// News
$wp_post_id = $this->get_wp_post_id_from_spip_news_id($article_id);
} else {
// Article
$wp_post_id = $this->get_wp_post_id_from_spip_article_id($article_id);
}
if ( !empty($wp_post_id) ) {
$wp_post_id = apply_filters('fgs2wp_post_get_post_by_spip_id', $wp_post_id, $post); // Used to get the ID of the translated post
$new_link = get_permalink($wp_post_id);
}
return $new_link;
}
/**
* Get the WordPress category link matching the SPIP category ID
*
* @since 2.18.0
*
* @param int $category_id SPIP Category ID
* @return string New link
*/
private function get_category_link($category_id) {
$new_link = '';
$wp_category_id = $this->get_wp_category_ids($category_id, $this->imported_categories);
if ( count($wp_category_id) > 0 ) {
$new_link = get_category_link($wp_category_id[0]);
}
return $new_link;
}
/**
* Split a link by its anchor link
*
* @param string $link Original link
* @return array(string link, string anchor_link) [link without anchor, anchor_link]
*/
private function split_anchor_link($link) {
$pos = strpos($link, '#');
if ( $pos !== false ) {
// anchor link found
$link_without_anchor = substr($link, 0, $pos);
$anchor_link = substr($link, $pos + 1);
return array($link_without_anchor, $anchor_link);
} else {
// anchor link not found
return array($link, '');
}
}
/**
* Copy a remote file
* in replacement of the copy function
*
* @param string $url URL of the source file
* @param string $path destination file
* @return boolean
*/
public function remote_copy($url, $path) {
$result = false;
if ( !$this->plugin_options['force_media_import'] && file_exists($path) && (filesize($path) > 0) ) {
// Don't download the file if already downloaded
return true;
}
$response = wp_remote_get($url, array(
'timeout' => $this->plugin_options['timeout'],
'sslverify' => false,
'user-agent' => 'Mozilla/5.0 AppleWebKit (KHTML, like Gecko) Chrome/ Safari/', // the default "WordPress..." user agent is rejected with some NGINX config
)); // Uses WordPress HTTP API
if ( is_wp_error($response) ) {
trigger_error($response->get_error_message(), E_USER_WARNING);
} elseif ( $response['response']['code'] != 200 ) {
trigger_error($response['response']['message'], E_USER_WARNING);
} else {
$content_type = wp_remote_retrieve_header($response, 'content-type');
if ( preg_match('/^text/', $content_type) ) {
// Not a media
trigger_error('Not a media', E_USER_WARNING);
} else {
file_put_contents($path, wp_remote_retrieve_body($response));
$result = true;
}
}
return $result;
}
/**
* Recount the items for a taxonomy
*
* @return boolean
*/
private function terms_tax_count($taxonomy) {
$terms = get_terms(array($taxonomy));
// Get the term taxonomies
$terms_taxonomies = array();
foreach ( $terms as $term ) {
$terms_taxonomies[] = $term->term_taxonomy_id;
}
if ( !empty($terms_taxonomies) ) {
return wp_update_term_count_now($terms_taxonomies, $taxonomy);
} else {
return true;
}
}
/**
* Recount the items for each category and tag
*
* @return boolean
*/
private function terms_count() {
$result = $this->terms_tax_count('category');
$result |= $this->terms_tax_count('post_tag');
}
/**
* Returns the imported posts mapped with their Spip ID
*
* @return array of post IDs [spip_article_id => wordpress_post_id]
*/
public function get_imported_spip_articles() {
global $wpdb;
$posts = array();
$sql = "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_fgs2wp_old_article_id'";
$results = $wpdb->get_results($sql);
foreach ( $results as $result ) {
$posts[$result->meta_value] = $result->post_id;
}
ksort($posts);
return $posts;
}
/**
* Returns the imported posts mapped with their Spip ID
*
* @return array of post IDs [spip_news_id => wordpress_post_id]
*/
public function get_imported_spip_news() {
global $wpdb;
$posts = array();
$sql = "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_fgs2wp_old_news_id'";
$results = $wpdb->get_results($sql);
foreach ( $results as $result ) {
$posts[$result->meta_value] = $result->post_id;
}
ksort($posts);
return $posts;
}
/**
* Returns the imported users mapped with their Spip ID
*
* @return array of user IDs [spip_user_id => wordpress_user_id]
*/
public function get_imported_spip_users() {
global $wpdb;
$users = array();
$sql = "SELECT user_id, meta_value FROM {$wpdb->usermeta} WHERE meta_key = '_fgs2wp_old_user_id'";
$results = $wpdb->get_results($sql);
foreach ( $results as $result ) {
$users[$result->meta_value] = $result->user_id;
}
ksort($users);
return $users;
}
/**
* Test if a column exists
*
* @param string $table Table name
* @param string $column Column name
* @return bool
*/
public function column_exists($table, $column) {
global $spip_db;
$cache_key = 'fgs2wp_column_exists:' . $table . '.' . $column;
$found = false;
$column_exists = wp_cache_get($cache_key, '', false, $found);
if ( $found === false ) {
$column_exists = false;
try {
$prefix = $this->plugin_options['prefix'];
switch ( $this->plugin_options['driver'] ) {
case 'mysql':
$sql = "SHOW COLUMNS FROM ${prefix}${table} LIKE '$column'";
break;
case 'sqlite':
$sql = "PRAGMA table_info(${prefix}${table})";
break;
}
$query = $spip_db->query($sql, PDO::FETCH_ASSOC);
if ( $query !== false ) {
if ( $this->plugin_options['driver'] == 'sqlite' ) {
// SQLite
$result = $query->fetchAll();
foreach ( $result as $row ) {
if ( isset($row['name']) && ($row['name'] == $column) ) {
$column_exists = true;
break;
}
}
} else {
// MySQL
$result = $query->fetch();
$column_exists = !empty($result);
}
}
} catch ( PDOException $e ) {}
// Store the result in cache for the current request
wp_cache_set($cache_key, $column_exists);
}
return $column_exists;
}
/**
* Test if a table exists
*
* @param string $table Table name
* @return bool
*/
public function table_exists($table) {
global $spip_db;
$cache_key = 'fgs2wp_table_exists:' . $table;
$found = false;
$table_exists = wp_cache_get($cache_key, '', false, $found);
if ( $found === false ) {
$table_exists = false;
try {
$prefix = $this->plugin_options['prefix'];
switch ( $this->plugin_options['driver'] ) {
case 'mysql':
$sql = "SHOW TABLES LIKE '${prefix}${table}'";
break;
case 'sqlite':
$sql = "SELECT name FROM sqlite_master WHERE type='table' AND name='${prefix}${table}';";
break;
}
$query = $spip_db->query($sql, PDO::FETCH_ASSOC);
if ( $query !== false ) {
$result = $query->fetch();
$table_exists = !empty($result);
}
} catch ( PDOException $e ) {}
// Store the result in cache for the current request
wp_cache_set($cache_key, $table_exists);
}
return $table_exists;
}
/**
* Get all the term metas corresponding to a meta key
*
* @param string $meta_key Meta key
* @return array List of term metas: term_id => meta_value
*/
public function get_term_metas_by_metakey($meta_key) {
global $wpdb;
$metas = array();
$sql = "SELECT term_id, meta_value FROM {$wpdb->termmeta} WHERE meta_key = '$meta_key'";
$results = $wpdb->get_results($sql);
foreach ( $results as $result ) {
$metas[$result->meta_value] = $result->term_id;
}
ksort($metas);
return $metas;
}
/**
* Returns the imported post ID corresponding to a SPIP article ID
*
* @param int $spip_id SPIP article ID
* @return int WordPress post ID
*/
public function get_wp_post_id_from_spip_article_id($spip_id) {
$post_id = $this->get_wp_post_id_from_meta('_fgs2wp_old_article_id', $spip_id);
return $post_id;
}
/**
* Returns the imported post ID corresponding to a SPIP news ID
*
* @param int $spip_id SPIP news ID
* @return int WordPress post ID
*/
public function get_wp_post_id_from_spip_news_id($spip_id) {
$post_id = $this->get_wp_post_id_from_meta('_fgs2wp_old_news_id', $spip_id);
return $post_id;
}
/**
* Returns the imported post ID corresponding to a meta key and value
*
* @param string $meta_key Meta key
* @param string $meta_value Meta value
* @return int WordPress post ID
*/
public function get_wp_post_id_from_meta($meta_key, $meta_value) {
global $wpdb;
$sql = "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = '$meta_key' AND meta_value = '$meta_value' LIMIT 1";
$post_id = $wpdb->get_var($sql);
return $post_id;
}
/**
* Sanitize a date
*
* @param date $date Date
* @return date
*/
public function sanitize_date($date) {
$date = preg_replace('#-00#', '-01', $date); // For the dates having day = 00
return $date;
}
}
}