PHPUnit Installer Script that Works in Travis CI and Locally for VVV

Travis CI is great and we’re using a very (VERY) simple singular test that just checks whether or not Titan Framework encounters any activation errors. As of the moment we haven’t wrote any other detailed tests for Titan, and that simple activation test soon will no longer cut it.

Ideally, testing would be done both remotely and locally during development so that you can catch errors quickly.. probably with a Gulp watch running the tests, but that would be for another article. I did some research on running PHPUnit tests locally and found Pippin’s 4-part blog post on Unit Testing for WordPress Plugins really helpful (read it if you haven’t yet). We’re using that as our guide to adding unit tests for Titan.

As of the moment we’re using VVV as our development environment, and it’s good that it already has WP-CLI and PHPUnit pre-installed so we can quickly jump into trying out unit testing locally. Titan already has a bin/install-wp-tests.sh so we don’t need to do a wp scaffold. We tried initializing the testing environment using this command inside VVV:

$ bash bin/install-wp-tests.sh wordpress_unit_tests root 'root' localhost latest

Surprise, the command failed. It works when Travis CI uses it, but it fails inside VVV. Why? Because Travis CI runs it’s tests on an empty environment, while VVV already has a bunch of development stuff inside it like a development copy of WordPress.

Not only that, the normal installer script would take a long time to finish since it downloads the WordPress installer, unzips it and uses that one as the testing environment. IF we performed testing across all our plugins, that would take up precious time.

So we modified the install-wp-tests.sh to only download stuff only when necessary and so skip cloning of the dev copy of WordPress if it already exists. Now, the script works locally inside VVV and it still works great also in Travis CI.

Here’s the copy of the install script that Titan Framework uses if anyone finds it useful:

For newly scaffolded projects, here’s the modified one:

Using IDs or query_vars instead of slug names in get_post_types

Here’s one that had my head scratching for a while.

We are currently developing a much-sought-after update for Carousel Anything, and it involves enumerating post types, taxonomies and terms. On a routine testing en route to being a candidate build, our testing team found out it wasn’t working with the custom post types by Meet The Team.

Several comparative var dumps later, I learned it wasn’t returning the correct post type variable!

Then I was reminded I implemented a feature previously in Meet The Team where I could change the slug name to something far more frendlier. It was friendly for readers in SEO, but not for the devs.

Or so I thought.

This meant slugs can’t be used for internal queries because it could be modified midway and wasn’t reliable, until I scoured a var dump of get_post_types() and found what I needed.

The query_vars key.

At last, this was the id that identified each post type reliably. And most slugs take up its name! No wonder why some post types worked and some did not!

That’s one piece of code definitely going to the snippets.

Here is what was wrong before.

$posttypes['slug'][] = $post_type->rewrite['slug'];
$posttypes['name'][ $post_type->rewrite['slug'] ] = $post_type->labels->name;

And here’s the code that set things right.

$posttypes['slug'][] = $post_type->query_var;
$posttypes['name'][ $post_type->query_var ] = $post_type->labels->name;

Converting Relative URLs to Absolute URLs in PHP

We needed to convert relative URLs to absolute URLs inside CSS files for our upcoming plugin Combinator.

There are a lot of code floating online that partially worked. The one that was closest was from http://99webtools.com/blog/convert-relative-path-into-absolute-url/. Here’s the reworked version that works great in PHP 5.3+

function rel2abs( $rel, $base ) {

	// parse base URL  and convert to local variables: $scheme, $host,  $path
	extract( parse_url( $base ) );

	if ( strpos( $rel,"//" ) === 0 ) {
		return $scheme . ':' . $rel;
	}

	// return if already absolute URL
	if ( parse_url( $rel, PHP_URL_SCHEME ) != '' ) {
		return $rel;
	}

	// queries and anchors
	if ( $rel[0] == '#' || $rel[0] == '?' ) {
		return $base . $rel;
	}

	// remove non-directory element from path
	$path = preg_replace( '#/[^/]*$#', '', $path );

	// destroy path if relative url points to root
	if ( $rel[0] ==  '/' ) {
		$path = '';
	}

	// dirty absolute URL
	$abs = $host . $path . "/" . $rel;

	// replace '//' or  '/./' or '/foo/../' with '/'
	$abs = preg_replace( "/(\/\.?\/)/", "/", $abs );
	$abs = preg_replace( "/\/(?!\.\.)[^\/]+\/\.\.\//", "/", $abs );

	// absolute URL is ready!
	return $scheme . '://' . $abs;
}

Usage

rel2abs( '../images/image.jpg', 'http://gambit.ph/css/style.css' );
// Outputs http://gambit.ph/images/image.jpg