Daniel Dvorkin

My take on WordPress and related geekery

Tag: WordPress

holding the key

Take ownership of a WordPress database

One of the gigs that used to put food on my table was as WPML‘s support manager. Customers that needed help usually ended up sending me a DB dump so I could implement a local copy to reproduce the problem and test whatever their issue might be.

Tired of doing the repetitive task of updating the site url in wp_options table, changing all the urls in the wp_posts table, and changing the password for the admin user, I came up with this little script that will do that for me.

It needs to be said: Be careful of not uploading this script to a live server.


<?php

// Bad, bad things WILL happen if you forget to delete this file when you upload the site to a public server
// Did I say bad already?

// Load WordPress environment
require_once( dirname(__FILE__) . '/wp-load.php' );

// First I want to get access. Changing all administrator passwords to "admin". Go read the first comment of this code!
$wp_user_search = new WP_User_Query( array( 'role' => 'administrator' ) );
$admins = $wp_user_search->get_results();

foreach ($admins as $admin){
    wp_set_password('admin',$admin->ID);
}

// Now lets fix the Site URL and Home URL
// But first let's save the current siteurl, for later use.
$old_siteurl = get_option("siteurl");

$pageURL = 'http';
if (isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
$pageURL .= "://";
if ($_SERVER["SERVER_PORT"] != "80") {
 $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
} else {
 $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
}
$new_siteurl = substr($pageURL,0,strrpos($pageURL,"/"));

update_option("siteurl", $new_siteurl);
update_option("home", $new_siteurl);

//And now those pesky hardcoded permalinks

$wpdb->query(
 "UPDATE $wpdb->posts SET guid = replace(guid, '{$old_siteurl}','{$new_siteurl}'); "
);

// Last but not least, those hardcoded urls (links, images, etc) in the posts contents

$wpdb->query(
 "UPDATE $wpdb->posts SET post_content = replace(post_content, '{$old_siteurl}','{$new_siteurl}');"
);

?>

Just drop this file in any WordPress installation and execute it on the browser.

iStock_LaptopBeach

WordPress XML-RPC Helper Class

I found myself copying and pasting quite often the necessary code to make WordPress XML-RPC work. And what do we nerds do in those situations? Abstract!

This helper class will take the burden off of you. I’ll post the whole code here, and then explain each part.

abstract class MZAXMLRPC {
	protected $calls = Array();
	protected $namespace = "myxmlrpc";

	function __construct( $namespace ) {
		$this->namespace = $namespace;
		$reflector       = new ReflectionClass( $this );
		foreach ( $reflector->getMethods( ReflectionMethod::IS_PUBLIC ) as $method ) {
			if ( $method->isUserDefined() && $method->getDeclaringClass()->name != get_class() ) {
				$this->calls[] = $method->name;
			}
		}
		add_filter( 'xmlrpc_methods', array( $this, 'xmlrpc_methods' ) );
	}

	public function xmlrpc_methods( $methods ) {
		foreach ( $this->calls as $call ) {
			$methods[$this->namespace . "." . $call] = array( $this, "dispatch" );
		}
		return $methods;
	}

	public function dispatch( $args ) {
		global $wp_xmlrpc_server;

		$username = $args[1];
		$password = $args[2];
		$data     = $args[3];

		if ( !$wp_xmlrpc_server->login( $username, $password ) ) return $wp_xmlrpc_server->error;

		$call = $this->get_called_method();

		if ( method_exists( $this, $call ) ) {
			$status = call_user_func_array( array( $this, $call ), array( $data ) );
			return $status;
		} else {
			return "Method not allowed";
		}

	}

	private function get_called_method() {
		global $wp_xmlrpc_server;
		$call   = $wp_xmlrpc_server->message->methodName;
		$pieces = explode( ".", $call );
		return $pieces[1];
	}

}

This is an abstract class. You won’t instantiate objects out of it. What you’ll do is create a new class that inherits from MZAXMLRPC, and in it you’ll make public methods for each XML-RPC call you want to expose. I’ll post an example in a moment, but first let’s break this code into parts.

The constructor uses Reflection to find all the user-defined public methods of the child class that is inheriting from it. Then it will tell WordPress that we’re accepting XML-RPC calls for this methods. The XML-RPC methods are exposed with the name $namespace.$public_method_name.

All those new XML-RPC will arrive to the same method, dispatch. It will first validate the user/pass for the remote call, then it will check that effectively there is a method declared to take care of the XML-RPC call. If all validates ok it will dispatch the call to the appropriate method of the child class, passing along all the data that came through the XML-RPC server.

Enough gibberish already! The only thing you need to do is:

class MY_XMLRPC extends MZAXMLRPC {

	public function QuoteUpload( $data ) {

		if ( !isset( $data["author"] ) ) return "Missing 'author' parameter";

		if ( !isset( $data["quote"] ) ) return "Missing 'quote' parameter";

		$author = $data["author"];
		$quote  = $data["quote"];

		$new_post = array( 'post_status' => 'publish',
		                   'post_type'   => 'mzaquotes',
		                   'post_title'  => $quote );

		$new_post_id = wp_insert_post( $new_post );
		wp_set_post_terms( $new_post_id, $author, 'quote_author' );

		return "OK";
	}
}

new MY_XMLRPC( 'my_function' );

This little piece of code will expose a XML-RPC method called my_function.QuoteUpload. The parent class will deal with authentication and WordPress XML-RPC APIs for you.

Powered by WordPress & Theme by Anders Norén