How to get your command line PHP script working with WordPress-MU 2.7

OK, this one is obscure. I only post about what I can’t find on Google!

Until recently it has been possible to run command-line PHP scripts that include wp-config.php or wpmu-settings.php, in order to give those scripts access to WordPress globals like $wpdb, functions such as wp_insert_post etc.

These scripts worked with WordPress-MU until recently — now the scripts just exit with no output.

The reason? WPMU now initiates a redirect in the bootstrap process (search for ‘header( “Location: “‘ in wpmu-settings.php). A browser can follow that redirection, but a command line script cannot. So, if you want to initiate scripts that run from the command line, you will have to get the web server involved by invoking a text browser such as curl, wget, or links.

It’s best not to force your scripts to figure out where to find wp-config.php anyway. I have taken to using a method suggested in this thread, as shown in the code sample below. The good news is, you know that your script will work the same whether initiated from a plugin in a graphic browser, used in an Ajax call, or initiated from cron or the command line shell.

So instead of kicking your script off with something like

/usr/bin/php -q myscript.php

You will create the script as a proper plugin and do something like

/usr/bin/curl -d mypp_cmd=status http://mywpmusite.com

Sample plugin code used for the above example follows. The prefix for the functions is ‘mypp’, which of course stands for ‘MY Plugin Prefix’ to create a unique namespace. The code below returns results as JSON encoded, and calls die()/exit() at the end to prevent an entire page being created. For log files run from cron, you may choose to return plain text instead.

  /**
   * Add a query var for this plugin
   * This allows Ajax programs to operate without requiring file paths
   * Instead, Ajax functions look for the query var 'mypp_cmd'
   */
  function mypp_query_vars($qvars) {
    $qvars[] = 'mypp_cmd';
    return $qvars;
  } // function mypp_query_vars
 
  /**
   * Handle AJAX requests in the template_redirect action
   * We recognize our requests from the query var 'mypp_cmd'
   * Here we allow GET requests using $_REQUEST; to restrict to POST, use $_POST instead
   */
  function mypp_template_redirect() {
    global $wpdb;
    $cmd = get_query_var('mypp_cmd');
    $response = array();
    if ($cmd) {
      switch($cmd) {
      case 'status':
	$response['status'] = array('success' => true,
				    'message' => 'Sample status message');
	break;
      default:
	$response['status'] = array('success' => false,
				    'msg' => 'Unknown command',
				    'cmd' => $cmd);
	break;
      } // switch $cmd
      header('Content-type: text/x-json; charset=utf-8');
      print utf8_encode(json_encode($response));
      die();
    } // $cmd is set
  } // function mypp_template_redirect
 
add_filter('query_vars', array($this, 'mypp_query_vars'));
add_action('template_redirect', array($this, 'mypp_template_redirect'));
Posted in Development, wordpress, wordpress-mu Tagged with: , , , , , ,

How to change the number of posts shown in the WordPress admin area without hacking the core

use the hook!

use the hook!

It is easy to go in and hack the core WordPress files to change the hard-coded number, but I wanted to find a way to do it with a hook.  That way, I could one day change the number of posts shown using controls in the interface.

Though there is no filter provided for the number of posts displayed, I hit upon a method of doing this which I would like to share.  Perhaps someone will point out a better way, but for now this is making me happy

The trick is to hijack the query string just for the query that produces the table of posts.  Here’s what I did:

/**  * Extend the number of posts displayed in the Edit Posts  */ 
function dapl_query_string($query_string) {   
    global $pagenow;   
    if (is_admin() && $pagenow == 'edit.php') {
        $query_string = str_replace('posts_per_page=15', 'posts_per_page=100', $query_string); 
    }
    return $query_string; 
}  
add_filter('query_string', 'dapl_query_string');
Posted in Development, wordpress Tagged with: , , , , ,

How to give all new WPMU blogs default properties, theme and pages

I’ve been developing an application on WordPress-MU and thought I’d share a cool tip.

When new web sites are generated by my client, I wanted the experience to be painless; a one-button ready-to-go web site.

It turns out there is an action hook (of course there is!) when a new blog is created.  So let’s get down to the nitty gritty and see how to implement it.

I wanted to create a property that would apply to the new web site, which would allow my client to limit what data gets displayed on that site.  I also wanted to generate the basic set of pages that I am using to support the sites’ URL structure.  Each page has a unique template that gives it some special navigation and content mojo.

So first I set the site-global option:

add_blog_option($blog_id, 
	        'campus_selection_criteria', 
                "CampusStateID LIKE '%'");

Now for the pages with their templates.  In order to let wp_insert_post know which blog to use, we use a handy function call:

switch_to_blog($blog_id);

We will also need to specify the theme we are using so that the starting theme will be selected and the templates will be correctly associated.

I can then create the pages as I would in WordPress-non-MU.  The final step is to call add_action() to hook this code into the blog creation event.

Here is the code in its entirety

function dscp_initialize_blog($blog_id) {
   add_blog_option($blog_id, 
                   'campus_selection_criteria', 
                   "CampusStateID LIKE '%'");
   switch_to_blog($blog_id);
   // switch theme
   switch_theme('thematic', 'mychildtheme');
   $postdata = array('post_parent' => 0,
   'post_status' => 'publish',
   'post_title'   => 'DESCRIPTIVE TITLE',
   'post_name'  => 'descriptive-title', /* the slug */
   'page_template' => 'template-whatever.php',
   'post_type'   => 'page');
   $newid = wp_insert_post($postdata);
   if ($newid && !is_wp_error($newid)) {
      add_meta($newid);
   } else {
      // your error handling code
   }
}
 
add_action('wpmu_new_blog', 'dscp_initialize_blog');
Posted in Development, wordpress Tagged with: , ,

How to upgrade WordPress SAFELY using Subversion and Rsync

I keep all my WordPress projects in a Subversion repository. I also have a snapshot of unmodified ‘vanilla’ releases kept in the same repository.

Now theoretically I should simply be able to use the svn merge command in a working directory. But I have encountered serious problems, including file corruption warnings, when using svn merge in an actively developed working directory. Additionally, svn merge will delete files and directories that you added to the core WordPress install.

The method outlined here will be safe even if you have hacked core WordPress files, as long as you are very careful in constructing your rsync command.

  1. Import and tag the latest WordPress release into the repository
    cd /tmp
    tar zxf /path/to/archive/wordpress-2.6.2.tar.gz
        OR
    unzip /path/to/archive/wordpress-2.6.2.zip
    svn import -m "Vanilla 2.6.2" wordpress file:///repository/wordpress/tags/2.6.2
  2. Remove the directory in /tmp
    rm -rf /tmp/wordpress
  3. Check out a fresh copy of your WordPress project, and export a copy of the latest vanilla WordPress
    cd /tmp
    svn co --ignore-externals file:///repository/wordpress/projects/myhappyblog
    svn export file:///repository/wordpress/tags/2.6.2 wordpress-2.6.2
  4. Do a dry run of rsync, starting with something like the following
    rsync --dry-run -av --delete --svn-exclude --exclude '.svn/' --exclude favicon.ico wordpress-2.6.2/ myhappyblog/|less -SiX
  5. Now begins an iterative process – carefully examine the output from the above rsync dry run, paying special attention to files that will be deleted, since those will show you directories and files you have added. Add those directories or files as required using multiple ‘–exclude’ options. Here is an example from a recent upgrade I did:
    rsync --dry-run -av --delete --svn-exclude --exclude '.svn/' --exclude favicon.ico --exclude 'images/' --exclude 'wp-content/plugins/podpress' --exclude 'wp-content/themes/sandbox' --exclude 'wp-content/uploads' wordpress-2.6.2/ myhappyblog/|less -SiX
  6. Once you are satisfied that you are not asking rsync to delete files and directories you need, run the command without ‘–dry-run’
    rsync -av --delete --svn-exclude --exclude '.svn/' --exclude favicon.ico --exclude 'images/' --exclude 'wp-content/plugins/podpress' --exclude 'wp-content/themes/sandbox' --exclude 'wp-content/uploads' wordpress-2.6.2/ myhappyblog/
  7. Now change to your project working directory and look at the output of ‘svn stat’, here including sample output:
    svn stat
    
    M      wp-login.php
    M      wp-includes/post.php
    M      wp-includes/version.php
    M      wp-includes/query.php
    M      wp-includes/formatting.php
    M      wp-includes/pluggable.php
    M      wp-includes/widgets.php
    M      wp-settings.php
    M      wp-admin/includes/template.php
    M      wp-admin/includes/image.php
    M      wp-admin/import/textpattern.php
    M      wp-admin/css/press-this-ie.css
  8. (conditional) In major upgrades, there will be WordPress core file deletions and additions. Handling these will require an extra couple commands, shown below. These commands are only necessary if there are additions and deletions.
    # tell repository about deleted files that were removed by rsync
    svn remove --force `svn stat |egrep '^\!' | cut -d' ' -f2-999`
    # add new files to repository
    svn add `svn stat|egrep '^\?' | cut -d' ' -f2-999`
  9. You may choose to look through all the changes, or you may decide that the files that have been changed are safe (ie, unhacked WordPress core files).Now you are ready to commit the changes to the repository.
    svn diff | less # optional
    svn commit -m "Upgraded to WordPress 2.6.2"
  10. At long last, you can go to the working directory where you are actively developing, and update that. Once you have tested thoroughly, you will be ready to update your live site (possibly with the same ‘svn update’ command).
    cd /path/to/my/development/myhappyblog
    svn up
  11. Repeat from Step 3 for each of your SVN-managed WordPress projects!
  12. Drink. Pray that WordPress is not upgraded for at least another 6 months.
Posted in Development, wordpress Tagged with: , , , , , ,