Migration to bbPress – fix topic slugs

So I’ve just had to migrate a whole load of data to bbPress, and unfortunately the fairly old migration tool I was using (while generally excellent) didn’t bring across the topic-slugs, meaning I couldn’t have pretty permalinks in bbPress. So I’ve written a quick plugin which creates the topic slugs, it does this by doing 1000 at a time every time the page loads, then it very rudely bangs up a big text notice telling you it’s done and you should remove the plugin… at this point bbPress won’t work until you remove the plugin. You have been warned. I couldn’t be bothered with polite messages as this is a one use migration tool. :)

Updated version, this one also create forum slugs:

<?php
/*
Plugin Name: Create Slugs
Description:  Creates topic and forum slugs where previously there weren't any. Outputs into error log, only works on plugin activation.
Plugin URI:  http://simonwheatley.co.uk/bbpress/create-slugs
Author: simonwheatley
Author URI: http://simonwheatley.co.uk
Version: 1.1
*/

class CreateSlugs
{
    protected $topics_have_slugs;
    protected $forums_have_slugs;
    
    function __construct()
    {
        global $bbdb;
        $this->db = & $bbdb;
        $this->topics_have_slugs = false;
        $this->forums_have_slugs = false;
    }
    
    public function create_slugs()
    {
        $this->create_topic_slugs();
        if ( ! $this->topics_have_slugs ) return;
        $this->create_forum_slugs();
        if ( ! $this->forums_have_slugs ) return;
        // Finished!
        echo "Everything now has slugs, you can disable the create topic slugs plugin by removing it from the plugins directory.";
        exit;
    }
    
    protected function maybe_finished()
    {
//        if ( ! $this->forums_have_slugs ) return;
    }
    
    protected function create_topic_slugs()
    {
        error_log( "TOPICS" );
        $topics = $this->slugless( 'topics' );
        if ( ! count( $topics ) ) $this->topics_have_slugs = true;
        foreach( $topics AS $topic ) {
            $new_slug = $this->generate_slug( 'topic', $topic->topic_id, $topic->topic_title );
            $this->update_topic_slug( $topic->topic_id, $new_slug );
            error_log( "$new_slug >> $topic->topic_title" );
        }
        error_log( "Last Query: " . $this->db->last_query );
    }
    
    protected function create_forum_slugs()
    {
        error_log( "FORUMS" );
        $forums = $this->slugless( 'forums' );
        if ( ! count( $forums ) ) $this->forums_have_slugs = true;
        foreach( $forums AS $forum ) {
            $new_slug = $this->generate_slug( 'forum', $forum->forum_id, $forum->forum_name );
            $this->update_forum_slug( $forum->forum_id, $new_slug );
            error_log( "$new_slug >> $forum->forum_name" );
        }
    }

    protected function slugless( $type )
    {
        // Just do 1,000 at a time for now
        if ( $type == 'topics' ) {
            $topics_table = $this->db->topics;
            $sql = " SELECT topic_id, topic_title FROM $topics_table WHERE topic_slug IS NULL OR topic_slug = '' LIMIT 1000 ";
        }
        if ( $type == 'forums' ) {
            $forums_table = $this->db->forums;
            $sql = " SELECT forum_id, forum_name FROM $forums_table WHERE forum_slug IS NULL OR forum_slug = '' LIMIT 1000 ";
        }
        // No need to prepared the SQL, no user input
        return $this->db->get_results( $sql );
    }
    
    protected function generate_slug( $type, $id, $title )
    {
        $slug = $_slug = bb_slug_sanitize( wp_specialchars_decode( $title, ENT_QUOTES ) );
        if ( strlen( $_slug ) < 1 ) $slug = $_slug = '0';

        // Ensure the slug is unique
        while ( is_numeric( $slug ) || $existing_slug = $this->existing_slug( $type, $id, $slug ) ) {
            $slug = bb_slug_increment( $_slug, $existing_slug );
        }
        return $slug;
    }
    
    protected function existing_slug( $type, $id, $slug )
    {
        if ( $type == 'topic' ) {
            $table = $this->db->topics;
            $sql = "SELECT topic_slug FROM $table WHERE topic_slug = %s AND topic_id != %d";
        }
        if ( $type == 'forum' ) {
            $table = $this->db->forums;
            $sql = "SELECT forum_slug FROM $table WHERE forum_slug = %s AND forum_id != %d";
        }
        $prepared_sql = $this->db->prepare( $sql, $slug, $id );
        return $this->db->get_var( $prepared_sql );
    }
    
    protected function update_topic_slug( $topic_id, $topic_slug )
    {
        $table = $this->db->topics;
        $data = array( 'topic_slug' => $topic_slug );
        $where = array( 'topic_id' => $topic_id );
        $this->db->update( $table, $data, $where );
    }
    
    protected function update_forum_slug( $forum_id, $forum_slug )
    {
        $table = $this->db->forums;
        $data = array( 'forum_slug' => $forum_slug );
        $where = array( 'forum_id' => $forum_id );
        $this->db->update( $table, $data, $where );
    }

}

$create_slugs = new CreateSlugs();

add_action( 'bb_init', array( & $create_slugs, 'create_slugs' ) );

?>

Join the Conversation

5 Comments

  1. thanks for the script simon. I test converted a forum from SMF (don’t even remember how, but I managed to do it through phpBB3) and it was missing the topic_slug and forum_slug columns.

  2. Hi Simon,

    Thanks fir the script. This plugin might help me a lot but I cant’ use it.
    I just upload it to the bb-plugins directory and rename it create-slugs.php but it doesn’t appear in the plugin page of the admin panel.

    Any idea ?

Leave a comment

Leave a Reply to xube Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.