wordpress/php-fpm/wordpress_files/plugins/fg-spip-to-wp/admin/class-fg-spip-to-wp-admin.php
2020-05-22 01:40:23 +00:00

3318 lines
102 KiB
PHP
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}
}