Node Module for Detecting Modified Core WordPress Files

Modifying core WordPress files is a quick way to introduce security vulnerabilities, break your site, and break future updates. From the perspective of a developer, nothing is worse than searching through a theme and plugins for a problem only to discover a previous developer modified a core WordPress file an introduced a bug.

I wrote a simple Node module that lets you easily check WordPress installations for modified or removed core files. Install the detect-wp-core-modifications npm package with the following shell command:

npm install -g detect-wp-core-modifications

You can run the command without any arguments from within the root of a WordPress installation with the following shell
command:

detect-wp-core-modifications

You can also specify a relative or absolute path to a WordPress installation:

detect-wp-core-modifications ../wordpress

I’ll probably write a WP-CLI command to compliment the node module. You can follow development on Github.

Granularly Manage Per-Post Access with Editorial Access Manager Plugin

Given the unmet need to allow users only access to edit specific pieces of content, I created a simple plugin called Editorial Access Manager.

By default in WordPress, we can create users and assign them to roles. Roles are automatically assigned certain capabilities. However, sometimes default roles are not enough, and we have one-off situations. Editorial Access Manager lets you set which users or roles have access to specific posts (as well as pages and custom post types).

Only the Administrator and Editor role have access to manage pages by default in WordPress. Making a user an Editor gives them a lot of power. I ran into the situation where we wanted a Contributor (less power than an Editor) to be able to edit only a few pages hence the need for this plugin.

My plan is to eventually integrate this plugin with EditFlow allowing people to assign User Groups to have access to specific pieces of content.

Any development help on this project would be much appreciated! Fork the Github repo.

Unit Testing, WordPress Code Techniques, WordPress Core

WP_UnitTestCase: The Hidden API

Background:

Unit testing is the automated testing of units of source code against assumptions. The goal of unit testing is to write test cases with assumptions that test if a unit of code is truly working as intended. If an assumption fails, a potential issue is exposed, and code needs to be revised.

By definition unit tests do not have dependencies on outside systems; in other words only your code (a single unit of code) is being tested. Integration testing works similarly to unit tests but assumptions are tested against systems of code, moving parts, or an entire application. The phrases unit testing and integration testing are often misused to reference one another especially in the context of WordPress. This article will try to stay consistent with WordPress terminology whether correct or not. Personally, in writing tests for my WordPress plugins/themes I write integration tests which I feel are more useful for a number of reasons that are outside of the realm of this article.

PHPUnit is the defacto library used to run unit and integration tests in PHP and thus server-side WordPress. This article assumes you are familiar with basic concepts of unit testing with PHPUnit.

What is WP_UnitTestCase?

WP_UnitTestCase is a PHP class included in the WordPress core development repository. Using SVN, you can check out that repo like so:

svn co http://develop.svn.wordpress.org/trunk/ wordpress-develop

The WordPress core development repository contains the core WordPress unit tests. Cool, huh? You can setup these tests, run them, and even write your own! Let’s poke around a few WordPress core test files. Open up wordpress-develop/tests/phpunit/tests/actions.php.

Normally, PHPUnit tests are structured like so:

class MyTestSuite extends PHPUnit_Framework_TestCase {
  public function setUp() {
    // This code will run before each test!
  }

  public function tearDown() {
    // This code will run after each test
  }

  public function testBasic() {
    $this->assertTrue( true );
  }
}

However, when writing integration tests for WordPress based applications, there exists a cool API we can leverage: WP_UnitTestCase. Remember how I asked you to open the actions.php file? You will see the test class in there extends WP_UnitTestCase. WP_UnitTestCase provides shortcuts for doing a number of tasks when creating your test cases. The first thing you will need to do to use this API is to require the file in your PHPUnit bootstrap file:

require_once( $tests_dir . '/includes/bootstrap.php' );

Of course you will need to setup $tests_dir appropriately. Within the WordPress core development repository, this bootstrap file lives at /tests/phpunit/includes/bootstrap.php. Including this bootstrap file will “bootstrap setup” WordPress, setup some things for unit testing, and include a number of useful things one of which is WP_UnitTestCase. There are other ways you could include WP_UnitTestCase, but this is by far the easiest.

Let’s setup our test class to use WP_UnitTestCase:

class MyTestSuite extends WP_UnitTestCase {
  public function setUp() {
    parent::setUp();
    // This code will run before each test!
  }

  public function tearDown() {
    parent::tearDown();
    // This code will run after each test
  }

  public function testBasic() {
    $this->assertTrue( true );
  }
}

Notice our class is extending WP_UnitTestCase instead of PHPUnit_Framework_TestCase. You can probably guess that WP_UnitTestCase extends PHPUnit_Framework_TestCase so we can use everything in PHPUnit_Framework_TestCase by extending WP_UnitTestCase plus a bunch more. Also notice within setUp() and tearDown() we are calling the same methods in the parent class; this is extremely important to ensure WP_UnitTestCase is working correctly. WP_UnitTestCase::setUp() and  WP_UnitTestCase::tearDown() do a bunch of magic such as cache clean up and global resets.

WP_UnitTestCase has an instance variable named $factory. Before each of your tests is run $factory is set to a newly instantiated object of type WP_UnitTest_Factory. The meat of WP_UnitTestCase is in this $factory variable. Let’s look some cools way that we can use WP_UnitTestCase.

Creating Blogs within a Network

public function testBasic() {
  $blog_id = $this->factory->blog->create();
  $blog_id_array = $this->factory->blog->create_many( 4 );
}

This is extremely useful for writing test cases that make cross-site assumptions. As you can tell $this->factory->blog->create() creates a blog and returns the new blog ID. $this->factory->blog->create_many( 4 ), creates 4 new blogs and returns an array of the ID’s in order.

If multisite is not setup, this factory will not exist! You can ensure WordPress is bootstrapped as multisite by setting the following constant up in your phpunit.xml file:

<const name="WP_TESTS_MULTISITE" value="1" />

Creating Test Posts

public function testBasic() {
  $post_id = $this->factory->post->create();
  $post_id_array = $this->factory->post->create_many( 4 );
}

Many times when I am writing tests I need to bulk create posts. WP_UnitTestCase let’s you accomplish this very easily. You can pass an array of post args (same as wp_insert_post) like so: create( $args ) and create_many( $num, $args ). If no arguments are passed, generic post_title/post_content info is generated. Post args passed to create_many will be applied to every post created.

Creating Test Comments

public function testBasic() {
  $comment_id = $this->factory->comment->create();
  $comment_id_array = $this->factory->comment->create_many( 4 );
}

Again, we can leverage WP_UnitTestCase to bulk create comments. You can see the ways to use the class is very consistent :). Comment args (like wp_insert_comment) can be passed to create() and create_many() in the exact same way as the post factory.

Creating Test Users

public function testBasic() {
  $user_id = $this->factory->user->create( array( 'user_login' => 'test', 'role' => 'administrator' ) );
  $user_id_array = $this->factory->user->create_many( 4 );
}

WP_UnitTestCase allows us to bulk create users as well. User args (same as wp_insert_user) can be passed to create() and create_many() in the same fashion as the post factory.

Creating Test Terms

public function testBasic() {
  $term_id = $this->factory->term->create( array( 'name' => 'Term Name', 'taxonomy' => 'category', 'slug' => 'term-slug' ) );
  $term_id_array = $this->factory->term->create_many( 4, array( 'taxonomy' => 'category' );
}

Creating bulk terms is slightly different from other factories. Create() and create_many() do take arguments the same was as wp_insert_term(). However, we provide ‘taxonomy’ and ‘name’ as a part of the array rather than as separate parameters.

Conclusion

WP_UnitTestCase contains additional factories for categories, tags, networks, and attachments. They work in a similar fashion as the factories above, so I will let you explore these API’s yourself :). WordPress contains a bunch of other useful API’s for building your test suites such as a system for mocking actions and a test case class for AJAX hooks. I plan on outlining those tools and a few others in future blog posts.

Database Theory, WordPress Code Techniques

A Performant Way to Feature Posts

In a past blog post I explained why featuring posts using a taxonomy term is much more performant than using a meta query. The comment I get from people is “that’s awesome, but using tags to feature a post is not a good user experience”. I agree, attaching a “featured” tag to featured posts, while performant is not a good experience for users because it leaves room for error on the admin side and shows the “featured” tag to users on the front end (if you are listing your tags).

Thankfully, there is a much better way to do this. We can create a small meta box with a “Featured Post” checkbox. This checkbox will add/remove a term in a hidden taxonomy from the post. Here is what the meta box will look like in WordPress 3.9:

Featured post meta box

I will take you through the code necessary to set this up. First we need to register a private taxonomy for internal use:

function tl_register_taxonomy() {
  $args = array(
    'hierarchical' => false,
    'show_ui' => false,
    'show_admin_column' => false,
    'query_var' => false,
    'rewrite' => false,
  );

  register_taxonomy( 'tl_post_options', array( 'post' ), $args );
}
add_action( 'init', 'tl_register_taxonomy' );

Now let’s write the code that actually associates the taxonomy term with featured posts. This will hook onto the “save_post” action.

function tl_save_post( $post_id ) {
  if ( ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) || ! current_user_can( 'edit_post', $post_id ) || 'revision' == get_post_type( $post_id ) )
   return;

  if ( ! empty( $_POST['additional_options'] ) && wp_verify_nonce( $_POST['additional_options'], 'additional_options_action' ) ) {
    if ( ! empty( $_POST['tl_featured'] ) ) {
      $featured = term_exists( 'tl_featured', 'tl_post_options' );
      if ( empty( $featured ) ) {
        $featured = wp_insert_term( 'tl_featured', 'tl_post_options' );
      }
      wp_set_post_terms( $post_id, array( (int) $featured['term_id'] ), 'tl_post_options' );
    } else {
      wp_set_post_terms( $post_id, array(), 'tl_post_options' );
    }
  }
}
add_action( 'save_post', 'tl_save_post' );

Next, we need to output a meta box with a checkbox. If this checkbox is checked, the post is marked as featured and the appropriate information is sent to the “save_post” hook on POST.

function tl_meta_box_additional_options( $post ) {
  wp_nonce_field( 'additional_options_action', 'additional_options' );
  $featured = has_term( 'tl_featured', 'tl_post_options', $post );
  echo 'Featured: <input type="checkbox" name="tl_featured" value="1" ' . ( ( $featured ) ? 'checked="checked"' : '' ) . '>';
}

Don’t forget we need to actually register our new meta box:

function tl_add_meta_boxes() {
  add_meta_box( 'tl_additional_options', 'Additional Options', 'tl_meta_box_additional_options', 'post', 'side' );
}
add_action( 'add_meta_boxes', 'tl_add_meta_boxes' );

Querying for posts on the front end is super easy! Here is an example query:

$query = new WP_Query( array(
  'tl_post_options' => 'tl_featured'
  'post_status' => 'publish',
  'post_type' => 'post',
) );
Computer Science, WordCamps

Computer Science in WordPress

Last year I did a presentation at WordCamp Orange County, WordCamp Birmingham, WordCamp Toronto, and WordCamp Providence called “What You Missed in Computer Science”. I have a Computer Science degree which I believe has provided me with some tools to think about problems in a certain way. This presentation will teach you about some of those tools, specifically Big-Oh Notation and race conditions. I will frame these Computer Science topics in terms of WordPress.

You can see a video recording of me giving the talk here at WordCamp Providence. I am reposting the slides on SlideShare since they seem to have disappeared:

Command Line WordPress, WordCamps, WordPress Plugins

WordCamp Ottawa

This weekend I was lucky enough to present at the 2nd annual WordCamp Ottawa. My talk was titled “Saving Time with WP-CLI”. WP-CLI is a plugin that lets you interact with your WordPress installations via the command line. My talk runs through some cool built-in WP-CLI commands as well as creating custom commands. My slides for the talk are here:

Pull Feed Content into WordPress

For the past year or so I’ve been using Automattic’s Syndication plugin to pull feed content into my WordPress plugin. Feeds that I designate are pulled in as posts using WordPress Cron. I decided while the plugin worked well for the most part, it wasn’t quite meeting my needs. This prompted me to build a new plugin called Feed Pull.

Here are some differences between the two plugins:

  • Feed Pull is a plugin for pulling content out of XML feeds. Syndication has feed pulling as well as content pushing features.
  • Feed Pull has a much friendlier feed management screen. Both Syndication and Feed Pull use the WordPress post edit, screen, however Feed Pull offers a much cleaner experience from the way options are presented to the instructions provided. At the moment Feed Pull does not have all the features of Syndication such as taxonomy and constant field mapping. However, Feed Pull probably has everything you need and is very extensible.
  • Feed Pull has far superior error logging to Syndication.
  • Feed Pull allows you to schedule content pulling in the future.
  • Feed Pull allows you to do manual pulls using AJAX rather than a sometimes frustrating one-time cron job.

Feed Pull contributions are always welcome on Github.

Introducing Post Customizer

10up just released a new plugin called the Post Customizer. I, along with John James Jacoby, John Bloch, Drew Jaynes, and Carl Danley led the charge on the plugin. The idea of the plugin is to mimic the theme customizer for posts. The plugin adds functionality that displays an overlay when you click “Preview” within the post editor. The overlay has a sidebar allowing you to edit the excerpt and featured post. In the middle of the overlay is a frame that shows the front of the website. Within that frame you can edit the post title and content. This enables you to make “live” changes and to see how they look as you make them. There are other plugins that offer similar behavior. However, Post Customizer closely follows the Theme Customizer and thus WordPress standards.

We want to make this plugin super extensible, and we need all the help we can get. We would appreciate contributions! Fork the plugin on Github.

Safe Redirect Manager

Hey Everyone!

I wanted to let everyone know about a new WordPress plugin called Safe Redirect Manager. I am one of the main developers of this plugin, and it has just been released on WordPress.org along with WordPress.com VIP (which is quite a special honor).

So what is the difference between this plugin and all the other redirect management plugins? Well, this plugin is simple, safe, and straight to the point. Instead of using the WordPress options table to store redirects, it uses a custom post type; this is much more flexible and lighter on your server. The plugin has been tested and reviewed by multiple WordPress core contributors and is available on WordPress.com — in order for a plugin to be available on WordPress.com it must be extremely secure. Safe Redirect Manager also allows you to use regular expressions in your redirects (if you don’t know what this is, don’t worry it’s an optional feature).

Here is a screenshot:

Download here: http://wordpress.org/extend/plugins/safe-redirect-manager

P.S: If you are a developer, Safe Redirect Manager is available to be forked on Github.

Edit: Thank you Branco Radenovich for the Slovak translation. This will be included in version 1.6.1 of the plugin.