📢 Simple Converter from Wordpress To SonikBB ( Topics and Categories )

User Avatar
👤 admin
🔴 Admin
✍️ It's not important where you are, it's important with who you are and how you live with them.
⏳ Last active: 15 Apr 2025 at 16:00
📅 Created: 03 Mar 2025 at 19:48
👀 Viewed: 65 times
✉️ Send Email

WordPress to Forum Migration Script

Overview
This simple PHP script connects to your WordPress database, reads existing categories and published posts, then inserts them into your forum database as forum categories and topics. It helps you preserve content structure (titles, descriptions, etc.) during migration.

Key Points

  • Fetches WordPress categories (wp_terms, wp_term_taxonomy) and creates corresponding records in the forum's categories table.
  • Maps published posts (wp_posts) to forum topics, retaining the post title, content, and date.
  • Uses a simple lookup to place each post into the correct category in the forum.
  • Can be extended to handle multiple categories, user mapping, and comment migration.

Usage

  1. Configure database credentials for both WordPress and forum in the script.
  2. Run the script (e.g., via command line or browser).
  3. Verify that categories and topics are created in your forum’s database.

Important

  • Always back up both databases before running the script.
  • Adjust the code for special cases (multiple categories, custom taxonomies, user accounts, comments, etc.).
<?php
/**
 * Migration of WordPress posts and their categories (one primary category per post)
 * to the `categories` and `topics` tables in the forum database.
 */

// 1. Connect to the WordPress database
$wpHost = 'localhost';
$wpDb   = 'wordpress';     // Name of the WP database
$wpUser = 'root';
$wpPass = 'your_wp_pass';

try {
    $wp_conn = new PDO("mysql:host=$wpHost;dbname=$wpDb;charset=utf8mb4", $wpUser, $wpPass);
    $wp_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Error connecting to WordPress DB: " . $e->getMessage());
}

// 2. Connect to the forum database
$forumHost = 'localhost';
$forumDb   = 'wordpressforum'; // Name of the forum database
$forumUser = 'root';
$forumPass = 'your_forum_pass';

try {
    $forum_conn = new PDO("mysql:host=$forumHost;dbname=$forumDb;charset=utf8mb4", $forumUser, $forumPass);
    $forum_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Error connecting to forum DB: " . $e->getMessage());
}

// -----------------------------------------------------------
// A) Migrating categories (WordPress -> forum)
// -----------------------------------------------------------
$catMap = [];  // Array to store the mapping between WP term_id and forum cat_id

// 1) Retrieve categories from WordPress
$catQuery = "
    SELECT t.term_id, t.name, tt.description
    FROM wp_terms AS t
    JOIN wp_term_taxonomy AS tt ON t.term_id = tt.term_id
    WHERE tt.taxonomy = 'category'
";
$wp_cats_stmt = $wp_conn->prepare($catQuery);
$wp_cats_stmt->execute();

// 2) For each WP category, insert a corresponding category into the forum `categories` table
while ($catRow = $wp_cats_stmt->fetch(PDO::FETCH_ASSOC)) {
    $wp_term_id = $catRow['term_id'];
    $catName    = $catRow['name'];
    $catDesc    = $catRow['description'] ?? '';

    // Insert the category into the forum (example INSERT)
    $insCat = "
        INSERT INTO categories (position, cat_name, cat_desc, def_icon)
        VALUES (:pos, :cname, :cdesc, :icon)
    ";
    // position: you can set 1, 2, 3,... or 0, etc. Here we use 0 for illustration.
    $catStmt = $forum_conn->prepare($insCat);
    $catStmt->execute([
        ':pos'   => 0,
        ':cname' => $catName,
        ':cdesc' => $catDesc,
        ':icon'  => 'images/forum.png'
    ]);

    $newCatId = $forum_conn->lastInsertId();

    // Store the mapping: WP term_id => forum cat_id
    $catMap[$wp_term_id] = $newCatId;
}

// -----------------------------------------------------------
// B) Migrating posts as topics
// -----------------------------------------------------------

// 1) Retrieve published posts from WordPress (wp_posts)
$postQuery = "SELECT ID, post_title, post_content, post_date, post_author
              FROM wp_posts
              WHERE post_type = 'post' 
                AND post_status = 'publish'";

$wp_stmt = $wp_conn->prepare($postQuery);
$wp_stmt->execute();

// 2) Migrate each post as a topic in the `topics` table
while ($row = $wp_stmt->fetch(PDO::FETCH_ASSOC)) {
    $wp_post_id   = $row['ID'];
    $topic_name   = mb_substr($row['post_title'], 0, 255); // limit to 255 chars
    $topic_desc   = $row['post_content'];
    $date_added   = $row['post_date'];
    $topic_author = 1;  // For simplicity, use admin=1

    // Find the primary category of this post (in WordPress, there can be multiple, here we take the first)
    $catQueryForPost = "
        SELECT tr.term_taxonomy_id
        FROM wp_term_relationships tr
        JOIN wp_term_taxonomy tt ON tr.term_taxonomy_id = tt.term_taxonomy_id
        WHERE tr.object_id = :post_id
          AND tt.taxonomy = 'category'
        LIMIT 1
    ";
    $postCatStmt = $wp_conn->prepare($catQueryForPost);
    $postCatStmt->bindParam(':post_id', $wp_post_id, PDO::PARAM_INT);
    $postCatStmt->execute();
    $categoryRes = $postCatStmt->fetch(PDO::FETCH_ASSOC);

    if ($categoryRes) {
        // In many WP installations, term_taxonomy_id == term_id, but not always.
        // For safety, you might want to do a JOIN to wp_terms to get the real t.term_id.
        // Let’s assume term_taxonomy_id matches term_id in this scenario:
        $wp_term_id_current = $categoryRes['term_taxonomy_id'];
        // Map WP term_id to the new forum cat_id
        $forum_parent_id = $catMap[$wp_term_id_current] ?? 1; // default to 1 if not found
    } else {
        // If the post has no category, default to 1
        $forum_parent_id = 1;
    }

    // Prepare INSERT into the forum `topics`
    $insertTopic = "
        INSERT INTO topics (parent, topic_name, topic_desc, topic_author, date_added_topic)
        VALUES (:parent, :tname, :tdesc, :tauthor, :tdate)
    ";
    $ins_stmt = $forum_conn->prepare($insertTopic);
    $ins_stmt->bindParam(':parent',  $forum_parent_id);
    $ins_stmt->bindParam(':tname',   $topic_name);
    $ins_stmt->bindParam(':tdesc',   $topic_desc);
    $ins_stmt->bindParam(':tauthor', $topic_author);
    $ins_stmt->bindParam(':tdate',   $date_added);
    $ins_stmt->execute();

    // (Optional) $new_topic_id = $forum_conn->lastInsertId();
}

echo "Categories and posts have been migrated successfully.\n";
?>

After

  1. Change category position in phpmyadmin
If you want to comment: Login or Register
User Avatar
👤 admin
🔴 Admin
✍️ It's not important where you are, it's important with who you are and how you live with them.
⏳ Last active: 15 Apr 2025 at 16:00
📅 Commented: 04 Mar 2025 at 13:46
✉️ Send Email

When all the articles are moved you can now format them part 1

<?php
// Данни за връзка с MySQL
$host = 'localhost';
$dbname = 'sonikbb'; // Замени с твоето име на база
$user = 'root'; // Замени с твоя потребител
$pass = 'password'; // Замени с твоята парола

try {
    // Свързване с базата
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Извличане на всички записи с topic_desc, съдържащи <img> или WP блокове
    $stmt = $pdo->query("SELECT topic_id, topic_desc FROM topics WHERE topic_desc LIKE '%<img%' OR topic_desc LIKE '%<!-- wp:%'");

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $topic_id = $row['topic_id'];
        $topic_desc = $row['topic_desc'];

        // 1. Премахване на всички WP коментари (начални и затварящи)
        $updated_desc = preg_replace('/<!--\s*\/?wp:[^>]+-->\s*/', '', $topic_desc);

        // 2. Премахване на <figure> и <figcaption>
        $updated_desc = preg_replace('/<figure[^>]*>/', '', $updated_desc);
        $updated_desc = preg_replace('/<\/figure>/', '', $updated_desc);
        $updated_desc = preg_replace('/<figcaption[^>]*>.*?<\/figcaption>/is', '', $updated_desc);

        // 3. Преобразуване на <img> в Markdown, премахване на "-WIDTHxHEIGHT" от URL и корекция на "uploads/"
        $updated_desc = preg_replace_callback(
            '/<img[^>]+src="([^"]+)"[^>]*>/i',
            function ($matches) {
                // Премахване на размерите (-1024x539 и т.н.) от URL
                $clean_url = preg_replace('/-\d{2,4}x\d{2,4}(\.\w{3,4})$/', '$1', $matches[1]);
                // Премахване на "https://lateweb.info/wp-content/"
                $clean_url = str_replace("https://lateweb.info/wp-content/", "uploads/", $clean_url);
                return "![Image](" . $clean_url . ")";
            },
            $updated_desc
        );

        // 4. Премахване на излишни празни редове
        $updated_desc = preg_replace('/^\s*[\r\n]/m', '', $updated_desc);

        // Обновяване на базата данни само ако има промяна
        if ($updated_desc !== $topic_desc) {
            $updateStmt = $pdo->prepare("UPDATE topics SET topic_desc = :topic_desc WHERE topic_id = :topic_id");
            $updateStmt->execute(['topic_desc' => $updated_desc, 'topic_id' => $topic_id]);
        }
    }

    echo "Обработката е завършена! WP блоковете са премахнати, изображенията са коригирани, а нови редове са добавени.";
} catch (PDOException $e) {
    echo "Грешка: " . $e->getMessage();
}
?>
User Avatar
👤 admin
🔴 Admin
✍️ It's not important where you are, it's important with who you are and how you live with them.
⏳ Last active: 15 Apr 2025 at 16:00
📅 Commented: 04 Mar 2025 at 13:46
✉️ Send Email

part 2

<?php
// Данни за връзка с MySQL
$host = 'localhost';
$dbname = 'sonikbb'; // Замени с твоето име на база
$user = 'root'; // Замени с твоя потребител
$pass = 'password'; // Замени с твоята парола

try {
    // Свързване с базата
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Извличане на всички записи с topic_desc
    $stmt = $pdo->query("SELECT topic_id, topic_desc FROM topics");

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $topic_id = $row['topic_id'];
        $topic_desc = $row['topic_desc'];

        // 1. Премахване на <p>, <h2> и <div>
        $updated_desc = preg_replace('/<\/?(p|h2|div)[^>]*>/', '', $topic_desc);

        // 2. Поправка на дублираното "uploads/uploads/"
        $updated_desc = str_replace("uploads/uploads/", "uploads/", $updated_desc);

        // 3. Добавяне на нови редове преди и след изображенията
        $updated_desc = preg_replace_callback(
            '/!\[Image\]\(([^)]+)\)/',
            function ($matches) {
                return "\n\n" . $matches[0] . "\n\n"; // Добавяне на два нови реда
            },
            $updated_desc
        );

        // 4. Премахване на излишни празни редове
        $updated_desc = preg_replace('/\n{3,}/', "\n\n", $updated_desc); // Ако има повече от 2 празни реда, оставяме само 2

        // Обновяване на базата данни само ако има промяна
        if ($updated_desc !== $topic_desc) {
            $updateStmt = $pdo->prepare("UPDATE topics SET topic_desc = :topic_desc WHERE topic_id = :topic_id");
            $updateStmt->execute(['topic_desc' => $updated_desc, 'topic_id' => $topic_id]);
        }
    }

    echo "Обработката е завършена! Всички HTML тагове са премахнати, изображенията са форматирани.";
} catch (PDOException $e) {
    echo "Грешка: " . $e->getMessage();
}
?>
User Avatar
👤 admin
🔴 Admin
✍️ It's not important where you are, it's important with who you are and how you live with them.
⏳ Last active: 15 Apr 2025 at 16:00
📅 Commented: 04 Mar 2025 at 13:47
✉️ Send Email

part 3

<?php
// Данни за връзка с MySQL
$host = 'localhost';
$dbname = 'sonikbb'; // Замени с твоето име на база
$user = 'root'; // Замени с твоя потребител
$pass = 'password'; // Замени с твоята парола

try {
    // Свързване с базата
    $pdo = new PDO("mysql:host=$host;dbname=$dbname;charset=utf8mb4", $user, $pass);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // Извличане на всички записи с topic_desc
    $stmt = $pdo->query("SELECT topic_id, topic_desc FROM topics");

    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $topic_id = $row['topic_id'];
        $topic_desc = $row['topic_desc'];

        // 1. Преобразуване на <code> в тройни грависи ```
        $updated_desc = preg_replace('/<code>/', "```\n", $topic_desc);
        $updated_desc = preg_replace('/<\/code>/', "\n```", $updated_desc);

        // 2. Премахване на <ol>, <ul>, <li> и форматиране като Markdown списък
        $updated_desc = preg_replace('/<\/?(ol|ul)>/', '', $updated_desc);
        $updated_desc = preg_replace('/<li>(.*?)<\/li>/', "- $1\n", $updated_desc); // Превръща <li> в Markdown списък

        // 3. Премахване на <h2>, <p>, <div> и други ненужни HTML тагове
        $updated_desc = preg_replace('/<\/?(h2|p|div)[^>]*>/', '', $updated_desc);

        // 4. Поправка на дублираното "uploads/uploads/"
        $updated_desc = str_replace("uploads/uploads/", "uploads/", $updated_desc);

        // 5. Добавяне на нови редове преди и след изображенията
        $updated_desc = preg_replace_callback(
            '/!\[Image\]\(([^)]+)\)/',
            function ($matches) {
                return "\n\n" . $matches[0] . "\n\n"; // Добавяне на два нови реда
            },
            $updated_desc
        );

        // 6. Добавяне на празни редове между параграфите
        $updated_desc = preg_replace('/(\S)(\n)(\S)/', "$1\n\n$3", $updated_desc);

        // 7. Премахване на излишни празни редове
        $updated_desc = preg_replace('/\n{3,}/', "\n\n", $updated_desc); // Оставя само 2 празни реда

        // Обновяване на базата данни само ако има промяна
        if ($updated_desc !== $topic_desc) {
            $updateStmt = $pdo->prepare("UPDATE topics SET topic_desc = :topic_desc WHERE topic_id = :topic_id");
            $updateStmt->execute(['topic_desc' => $updated_desc, 'topic_id' => $topic_id]);
        }
    }

    echo "Обработката е завършена! <code> е заменен с ```, HTML таговете са премахнати, изображенията са форматирани.";
} catch (PDOException $e) {
    echo "Грешка: " . $e->getMessage();
}
?>