klenwell information services : WordPressResetHost

WordPress: Script to Reset Host

return to DevWordPress

WordPress uses absolute urls for some reason to track the domain host, and the urls that are built therefrom, for a site. This makes it unnecessarily painful to run local development and production versions of a site. Several records in the database must be updated each time domain is changed. This script does that for you, in a quick and rather dirty way.

Usage

# ADD THIS LINE
if ( defined('WP_STOP_LOAD') && WP_STOP_LOAD ) return;

# EXISTING WordPress SETTINGS
/* That's all, stop editing! Happy blogging. */

/** WordPress absolute path to the Wordpress directory. */
if ( !defined('ABSPATH') )
    define('ABSPATH', dirname(__FILE__) . '/');

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');
cd <MY_WORDPRESS_ROOT_DIR>
php ./cli_reset_host.php -t
php ./cli_reset_host.php http://localhost/path_to_wp


Code

<?php
/**
 * WordPress Reset Host (Command Line Interface)
 *
 * Note Well: This script is designed to be run from the command line as a
 * non-webserver process, specifically for cron tasks. For security reasons,
 * it cannot be executed through the browser.
 *
 * USAGE
 *  test:               php WP_ROOT/cli_reset_host.php -t
 *  run:                php WP_ROOT/cli_reset_host.php http://mynewdomain.com/path
 *
 * NOTES
 *  You must add the following line near the bottom of your wp config file
 *  for this script to succeed:
 *      if ( defined('WP_STOP_LOAD') && WP_STOP_LOAD ) return;
 *  Must come before line:
 *      require_once(ABSPATH . 'wp-settings.php');
 *
 * @package WordPress
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
 * @author  {@link http://klenwell.com/is Tom Atwell}
 * @copyright Copyright 2010       Tom Atwell <klenwell@gmail.com>
 *
 */



/**
 * Imports
 */

# loaded by class below



/**
 * RequestHandler class
 * @this runs the script (see bottom of file)
 */

class RequestHandler {

    # configurable properties
    var $server_name    = 'localhost';  # if $_SERVER['SERVER_NAME'] needs to be set
    var $debug          = 0;
    var $pretty_print   = 1;
    var $wp_root        = '';           # defined in constructor
    var $is_multisite   = FALSE;        # seems signficant for some reason

    # non-configurable properties
    var $start_time     = 0;
    var $db             = NULL;
    var $table_prefix   = '';

    function RequestHandler() {
        $this->start_time = microtime();
        $this->argv = $_SERVER['argv'];
        $this->wp_root = dirname(__FILE__) . '/';

        if ( ! empty($this->server_name) ) {
            $_SERVER['SERVER_NAME'] = $this->server_name;
        }

        # config file flag
        define('WP_STOP_LOAD', 1);
    }

    function security_checks() {
        $this->cli_check();
        $this->sanity_checks();
    }

    function cli_check() {
        if ( ! php_sapi_name() == 'cli' ) {
            trigger_error('This script is accessible only from the PHP CLI.',
                          E_USER_ERROR);
        }
        define('WP_IS_CLI', 1);
    }

    function sanity_checks() {
    }

    function parse_command_line()
    {
        $ShortOpts = array(
            'c:',   # config key ($_SERVER['SERVER_NAME'])
            't',    # test
        );

        $options = getopt(implode('',$ShortOpts));


        if ( isset($options['t']) ) {
            $run_mode = 'test';
        }
        else {
            $run_mode = 'default';
        }

        $this->basename = basename($_SERVER['argv'][0]);

        return $run_mode;
    }

    function abort($message='') {
        # Note: WP db object seems to require a certain SERVER var
        #$_SERVER = array('Run test to see SERVER vars');

        $this->debug_output();
        print "\n** ABORT ** \n";
        if ( $message ) {
            print "$message\n";
        }

        die("\n\n");
    }

    #
    # wp load methods
    #
    function load_wp_config() {
        if ( ! function_exists('is_multisite') ) {
            if ( ! defined('WPDB_MULTISITE') ) define('WPDB_MULTISITE', $this->is_multisite);
            function is_multisite() { return WPDB_MULTISITE; }
        }
        require_once($this->wp_root . 'wp-config.php');
        $this->table_prefix = $table_prefix;
    }

    function load_parameters() {
        if ( ! isset($this->argv[1]) ) {
            $this->abort('You must include the new url to which you wish to update as a parameter.');
        }
        $this->new_url = $this->argv[1];

        if ( strpos($this->new_url, 'http://') === FALSE &&
             strpos($this->new_url, 'https://') === FALSE ) {
            $this->abort('Include http:// or https:// with you new url');
        }
    }

    #
    # database methods
    #
    # ref: http://core.trac.wordpress.org/browser/tags/3.0.2/wp-includes/wp-db.php
    function connect_to_database() {
        $wpdb = 1;      # prevents wp-config.php from auto-loading db class
        require_once($this->wp_root . 'wp-includes/wp-db.php');
        $this->db = new wpdb(DB_USER, DB_PASSWORD, DB_NAME, DB_HOST);
        $this->db->set_prefix($this->table_prefix);
        print_r($this->db);
    }

    function get_current_url() {
        $sql = "SELECT option_value FROM wp_options WHERE option_name='home'";

        if ( ! $this->db ) {
            $this->load_wp_config();
            $this->connect_to_database();
        }

        if ( $Results = $this->db->get_results( $sql ) ) {
            $this->old_url = $Results[0]->option_value;
        }
        else {
            trigger_error('unable to get current home setting from options table',
                          E_USER_ERROR);
        }
        return $this->old_url;
    }

    # ref: http://wpengineer.com/1746/wordpress-database-functions/
    function update_wp_options() {
        if ( ! $this->db->update( $this->db->options,
            array( 'option_value' => $this->new_url ),
            array( 'option_name' => 'home' )
        ) ) {
            $this->abort('failed to update "home" option value to new url');
        };

        if ( ! $this->db->update( $this->db->options,
            array( 'option_value' => $this->new_url ),
            array( 'option_name' => 'siteurl' )
        ) ) {
            $this->abort('failed to update "siteurl" option value to new url');
        }
    }

    function update_wp_posts() {
        $sql = sprintf("UPDATE %s SET guid = REPLACE(guid, '%s', '%s')",
                       $this->db->posts,
                       $this->old_url,
                       $this->new_url);

        if ( ! $posts_updated = $this->db->query($sql) ) {
            $this->abort('failed to update url in any post guids');
        }

        return $posts_updated;
    }


    # output methods
    function debug_output() {
        $format_ = <<<HDOC

wordpress host reset
-----------------
basename:           %s
current url:        %s
server time:        %s

argv:
%s

_SERVER:
%s

USAGE:
    php %s [-t] new_url

script complete in %.4f s

HDOC;
        # filter some $_SERVER values
        $server_filter = array('LS_COLORS', 'DBUS_SESSION_BUS_ADDRESS',
                               'SSH_AUTH_SOCK');
        foreach ( $server_filter as $key ) {
            if ( isset($_SERVER[$key]) ) unset($_SERVER[$key]);
        }

        printf( $format_,
                $this->basename,
                $this->get_current_url(),
                date('Y-m-d H:i:s'),
                print_r($this->argv,1),
                print_r($_SERVER,1),
                __FILE__,
                microtime() - $this->start_time );
    }

    function prepare_output($posts_updated) {
        $format_ = <<<HDOC

URL Updated
-----------------
old url:            %s
new url:            %s
posts update:       %s
server time:        %s

argv:
%s

script complete in %.4f s

HDOC;
        return sprintf( $format_,
                        $this->old_url,
                        $this->get_current_url(),
                        $posts_updated,
                        date('Y-m-d H:i:s'),
                        print_r($this->argv,1),
                        microtime() - $this->start_time );
    }

    function pretty_print_output($content) {
        $content = preg_replace('%<br[^>]*>|\n%', '***', $content);
        $content = preg_replace('%\s+%', ' ', $content);
        $content = str_replace('***', "\n", $content);
        $content = preg_replace('%\n{3,}%', "\n\n", $content);
        print $content;
    }

    function output($content) {
        if ( $this->debug ) {
            $this->debug_output();
        }

        if ( $this->pretty_print ) {
            $this->pretty_print_output($content);
        }
        else {
            print $content;
        }
    }

    # main methods
    function main_cli() {
        $this->load_parameters();
        $this->load_wp_config();
        $this->connect_to_database();
        $this->old_url = $this->get_current_url();
        $this->update_wp_options();
        $posts_updated = $this->update_wp_posts();
        return $this->prepare_output($posts_updated);
    }

    function test_cli() {
        $this->load_wp_config();
        $this->connect_to_database();
        $this->debug_output();
    }

    function main()
    {
        $this->security_checks();
        $run_mode = $this->parse_command_line();

        if ( $run_mode == 'test' ) {
            $this->test_cli();
        }
        else {
            $content = $this->main_cli();
            $this->output($content);
        }
    }
}


/**
 * main section: limits functionality to command line
 */

$is_main_cli = isset($_SERVER['argv'][0]) && (realpath($_SERVER['argv'][0]) == __FILE__);
if ( $is_main_cli ) {
    $CliHandler = new RequestHandler();
    $CliHandler->main();
}
else {
        print "<h4>this script intended to be run from command line only</h4>";
}