Archive for the ‘General Development’ Category

Modern WordPress Development – Composer

November 19th, 2013 by

Composer is a PHP dependency manager that’s been in the wild for roughly 2 years. In short it helps mitigate the extremely antiquated ways PHP developers had been managing third party libraries.

Composer is nothing new to PHP, as I said it’s over 2 years old, but WordPress has been slow to get on board. I’ve set up a workflow that, I admit, is “somewhat flawed,” but is a step in the right direction for managing WordPress via Composer.

The goal of this article is to be a reference and I am going to keep it as concise as possible. To install Composer follow this guide, be sure to install it globally. For a more in-depth guide read excellent Scott Walkinshaw’s posts Using Composer with WordPress and WordPress Plugins with Composer and buy the Roots screencast Using Composer with WordPress it’s worth 3x it’s cost.

One quick note, is all Composer requires a composer.json file which is essentially a manifest that outlines everything we want completed for the project. Also, I will show you my completed json file below and you can use that as a reference for any notes I make to indexes in this article.

Manually Add WordPress to Composer

Composer’s de facto repository for packages is at packagist.org, since there is no official WordPress packagist package in that repo, we can manually add WordPress to our package by adding the following into our manifest’s “repositories” key (which is an array):

{
      "type": "package",
      "package": {
        "name": "wordpress",
        "type": "webroot",
        "version": "3.7.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/WordPress/WordPress/archive/3.7.1.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    }

Ignore the *type* webroot and *require* of webroot-installer for now, I’ll get to that in the next section.

What this does is add a manually add a package to our manifest. We tell it that its name is WordPress which is arbitrary, we can call it whatever we want, we list the version as the most recent (as of this writing 3.7.1) and tell it where it is located, in the “dist” key– where we set that it is a zip file and it’s located at the official WordPress github repository. We choose to keep the WordPress core in a directory “wp” – later you will see we will store our application specific packages (plugins, themes) in a directory in line with “wp” i.e. our application specific packages will live in /our/server/app/ and WordPress core will live in /our/server/wp/ which gives us excellent and flexible separation of concerns.

Change the Directory WordPress is Installed In

Composer, by default, stores all packages in a /vendors/ directory. To get around that we can use fancy guy’s webroot installer plugin for Composer… and guess what, we can just require it, so no manual downloading necessary… told you composer is great!

If you refer to the last section, we can see how to change the behavior of Composer. Since we are going to want to install WordPress in a subdirectory of the root and not stuffed in the vendors directory (which is Composer’s default behavior), we modify the setting of our custom WordPress package. First we set the package type to “webroot” so that it uses the webroot plugin for Composer and we require the webroot plugin for this particular package.

We set the desired destination of the package in the “extra” key below, e.g. we add

 "webroot-dir": "wp",
 "webroot-package": "wordpress"

to the composer.json’s “extra” index.

Additionally, we are going to want to set where WordPress plugins, themes and must use plugins are to go. To do so we set the “installer-paths” key in the “extra” key of the composer.json file like such:

"installer-paths": {
    "app/plugins/{$name}/": ["type:wordpress-plugin"],
    "app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
    "app/themes/{$name}/": ["type:wordpress-theme"]
}

I chose app as the subdirectory where my applications’ non-core files will be located – you can choose whatever you want. You can keep it as wp-content or rename it to content as Mark Jaquith does in WordPress Skeleton.

WordPress Packagist

Outlandish created an awesome repository for WordPress Plugins, WordPress Packagist. This repository mirrors the WordPress Plugin Repository and allows you to include plugins listed within it super easy. It even sets them as “wordpress-plugin” type so the plugins will listen to our installer-paths declaration. To access this repository we have to tell our manifest that we are going to be using this repository by adding an entry to its “repositories” array like such:

    {
      "type":"composer",
      "url":"http://wpackagist.org"
    }

We tell it that this repository is set up as a composer style repo and that it lives at http://wpackagist.org.

Now we can simply add plugins to our project by adding to our “require” key’s object the name of the package (prefixed with our source, wpackagist/) and the version of the plugin we wish to install like such:

"wpackagist/easy-responsive-carousel":"0.4.5"

Custom WordPress Plugins & Themes (not in a repository)

There may come a time that you want to include a plugin that is not located in a Composer repository, for example they may just live on github or somewhere else as a zip file. We can easily add this as an element of the “respositories” key in our composer.json file like such:

    {
      "type": "package",
      "package": {
        "name": "easy-nag-popup",
        "type": "wordpress-plugin",
        "version": "2.1.7.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/matstars/easy-nag-popup/archive/2.1.7.1.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    }

and be sure to include it in the “requires” key like such:

    "easy-nag-popup":"2.1.7.1"

We can even do this for themes, like such:

    {
      "type": "package",
      "package": {
        "name": "roots",
        "type": "wordpress-theme",
        "version": "6.5.0",
        "dist": {
          "type": "zip",
          "url": "https://github.com/roots/roots/archive/6.5.0.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    }

Notice how I specified the type as wordpress-theme, this will follow the installer-paths set in the “extra” key.

Let’s Compose!

Remember how I said this process was somewhat flawed? This is where that “somewhat flawed” kicks in. Before I get into that, let’s take a look at the composer.json file we have created:

{
  "repositories": [
    {
      "type":"composer",
      "url":"http://wpackagist.org"
    },
    {
      "type": "package",
      "package": {
        "name": "wordpress",
        "type": "webroot",
        "version": "3.7.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/WordPress/WordPress/archive/3.7.1.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    },
    {
      "type": "package",
      "package": {
        "name": "easy-nag-popup",
        "type": "wordpress-plugin",
        "version": "2.1.7.1",
        "dist": {
          "type": "zip",
          "url": "https://github.com/matstars/easy-nag-popup/archive/2.1.7.1.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    },
    {
      "type": "package",
      "package": {
        "name": "roots",
        "type": "wordpress-theme",
        "version": "6.5.0",
        "dist": {
          "type": "zip",
          "url": "https://github.com/roots/roots/archive/6.5.0.zip"
        },
        "require" : {
          "fancyguy/webroot-installer": "1.*"
        }
      }
    }      

  ],
  "require": {
    "wordpress": "3.7.1",
    "fancyguy/webroot-installer": "1.0.0",
    "wpackagist/advanced-custom-fields":"*",
    "wpackagist/posts-to-posts":"1.4.*",
    "wpackagist/easy-responsive-carousel":"0.4.5",
    "easy-nag-popup":"2.1.7.1",
    "roots":"6.5.0"

  },
  "extra": {
    "webroot-dir": "wp",
    "webroot-package": "wordpress",
    "installer-paths": {
        "app/plugins/{$name}/": ["type:wordpress-plugin"],
        "app/mu-plugins/{$name}/": ["type:wordpress-muplugin"],
        "app/themes/{$name}/": ["type:wordpress-theme"]
    }
  }

}

Brief rundown of the keys:

repositories: Here we list any repositories outside of the official Composer repo (packagist.org), this can include full fledged repositories (wpackagist.org) and individual packages hosted elsewhere (github, bitbucket, etc.)

require: what packages are we going to include in our project? Here we include webroot-installer, which helps us store our files where we need to install them, WordPress core, WordPress plugins and WordPress themes.

extra: here we list where we want WordPress installed (webroot-dir and webroot-package set to “wp” and “wordpress” to denote where we want what installed, respectively). We also tell webroot-installer the default location for specific package types (i.e. wordpress-plugins in app/plugins, wordpress-muplugins in app/mu-plugins/ and wordpress-themes in app/themes/, respectively). N.B. remember we decided, as a matter of separating concerns, to store the plugins/themes in the directory /app and wordpress core in /wp.

Okay, so we have a single composer.json file. Drop it in an empty directory and run composer install. Once you install your composed application, you will see the following directories created: vendor, wp, app as well as a composer.lock file. For all intents and purposes we can ignore the vendor directory. The app directory is where all our application specific code will live (themes/plugins) and the WordPress core will live in the wp directory.

Now comes the manual work. Since we are essentially Giving WordPress Its Own Directory, we need to do some manual work. First things first, we have to copy /wp/wp-config-sample.php to the root level and rename it wp-config.php. Let’s edit this file with the information we are going to need to add and update.

First things first add your database information as you normally would. Next we need to set some constants for our WordPress environment, namely where our application specific code will live and, optionally, where our must use plugins will live (aside, since it’s a bit of a kludge, I have yet to use must use plugins), if you followed along we would add the following code right after we set our database credentials:

define( 'WP_CONTENT_DIR', dirname( __FILE__ ) . '/app' );
define( 'WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/app' );
define( 'WPMU_PLUGIN_DIR', dirname( __FILE__ ) . '/app/mu-plugins' );
define( 'WPMU_PLUGIN_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/app/mu-plugins' );

additionally we need to tell WordPress that our core is not located in the root, but rather in the subdirectory wp. To do so, we need to update the definition of ABS path in the wp-config file, like such:

define('ABSPATH', dirname(__FILE__) . '/wp/');

Next we need to copy /wp/index.php to our root directory and make one minor change: we need to tell index.php where our wp-blog-header.php file is located — it is no longer in our root but in the wp sub directory, so we change the require command to:

require( dirname( __FILE__ ) . '/wp/wp-blog-header.php' );

Let’s run through the WordPress installation, and we can make the final changes. Once the site is set up, if you have been following along, WordPress will be looking for a theme that is not there (at this writing TwentyThirteen), so we have to set Roots as our theme.

Finally, since we are using WordPress in a subdirectory, we have to go into Settings > General and remove “/wp” from Site Address (URL)  (not WordPress Address (URL)).

We are done!

Note, for some reason Roots is not enqueuing the right CSS file, but if you copy Twenty Thirteen from wp/wp-content/themes/ to app/themes/ and activate the Twenty Thirteen theme it works fine.

Hope that this helps you all out there and let me know if there’s anything I missed (I’m still relatively new to Composer) or something that is easier. I need to come up with a way to automate the moving/setting of index.php and wp-config.php – maybe with Grunt. I tried adding a shell script (I’m not too great with writing scripts either) to “scripts” > “post-install-cmd” in composer.json but ran into trouble.

Until next time….

I was scared of the WordPress’ Rewrite API, but I’m doing something about it

September 4th, 2013 by

I’m going to make this short, but I wanted to make sure I put this up while I had it fresh in my mind. This is a pretty arbitrary example, but it should suffice for an example of how to use the Rewrite API. I have a custom post type called sponsors, and I want to be able to show all of the posts (without pagination) when the user hits the endpoint http://myblog.com/sponsors/showall. This is how to accomplish it…

/* add show_all to query_vars */
add_filter('query_vars', function($vars){
    $vars[] = 'show_all';
    return $vars;
});

/* set up rewrite rule  */
add_action('init', function(){
    add_rewrite_rule('sponsors/([^/]*)$', 'index.php?post_type=sponsors&show_all=$matches[1]', 'top');
});

/* if show_all is set to 'showall' show all of the posts! */
add_action('pre_get_posts', function($query){
    if ( get_query_var('show_all') == 'showall' ) {
        $query->set('posts_per_page', -1);
    }

Upgrade OS X’s PHP Version to the latest version

August 24th, 2013 by

  • First things first, you will need homebrew installed, the easiest way to do so is check out brew.sh or just simply execute, and follow the prompts of:
ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"
  • Once homebrew is installed check Jose Gonzalez’s github for homebrew-php for the latest package name (as of this writing it is php55, so I am going to go through the steps using php55, if there’s a newer one replace the token php55 with the newer version, likewise if you want to use an older version, e.g. 5.4, you could substitute the token php55 below with php54.
  • Ready to rock. Simply issue the following commands
brew tap homebrew/dupes
brew tap josegonzalez/homebrew-php
brew update
brew install php55
brew link --overwrite php55
  • After you are complete add this line to the end of your ~/.bashrc export PATH=/usr/local/opt/php55:$PATH
  • Close and reopen terminal and issue “php -v” it should now say
PHP 5.5.3 (cli) (built: Aug 24 2013 13:46:24)
Copyright (c) 1997-2013 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies

{S tada} we’re done!

Use archive.php as the search results page

March 28th, 2013 by

This one is easy too…
add_action( 'template_redirect', function(){
if (is_search()) {
include("archive.php");
die();
}
});

It’s important to note this uses an anonymous function which requires PHP 5.3+.