Guide To Having PhpStorm Use Windows Subsystem For Linux’s Git

I’m one of the rare Windows users at Automattic but thanks to the introduction of Windows Subsystem for Linux, my life is way easier. I can now run pretty much any Bash script without having to spin up a virtual machine like I used to have to. While it’s possible to build Node.js-powered projects natively under Windows thanks to the Windows-Build-Tools package, it’s a lot easier to just do everything within Linux. This is largely because building in one environment means that you can’t run the tools in the other environment.

The main time that this bites you is when the project you’re working on has a pre-commit hook in Git. If you build your project in Linux but attempt to commit from Windows, it won’t work. IDEs such as PhpStorm do all of their Git operations from Windows. This blog post will explain how to get it to use the copy of Git within Linux.

  1. Install Pageant from PuTTY or if you’re signing your commits, then Gpg4win (its gpg-connect-agent can be set to be PuTTY compatible). Have it start with Windows in order to load your SSH keys.
  2. Verify that the agent is working by using PuTTY to connect to with the username git. GitHub won’t let you open a shell but it’ll let you know that you have successfully authenticated. Note that command line ssh won’t work because it’s not Pageant-compatible.
  3. Install weasel-pageant to allow you to use SSH keys from within Linux.
  4. Verify that the agent is working by running ssh-add -l in Linux. Your key(s) should be listed.
  5. Verify SSH is working by running ssh If it doesn’t work, append -vvv to the end of the command to enable debug output to see what’s wrong.

Now that you have Git authentication working within Linux, it’s time to get PhpStorm (or whatever IDE you use) to use Linux’s Git.

The trick here is instead of having PhpStorm use git.exe, you need to point it at a batch script. This Stack Overflow question helped me a ton, but I needed to modify it a little bit.

For whatever reason, my .bashrc file wasn’t being loaded when calling bash.exe -c which meant that agent wasn’t being loaded. So as a part of my batch script, I’m manually loading my personal file that contains my shell customizations. Here’s my full batch file:

@echo off
setlocal enabledelayedexpansion
set command=%*
set find=C:\Users\%USERNAME%\AppData\Local\Temp\git-commit-msg-.txt
set replace=/mnt/c/Users/%USERNAME%/AppData/Local/Temp/git-commit-msg-.txt
call set command=%%command:!find!=!replace!%%
    C:\Windows\sysnative\bash.exe -c 'source ~/.viper-common; git %command%'
) Else (
    bash.exe -c 'source ~/.viper-common; git %command%'

In PhpStorm, go to File → Settings (or Default Settings) → Version Control → Git and set the “Path to Git executable” to point at the batch file. Verify that it works by clicking the Test button.

With that, everything should work now!

Questions? Problems? Leave a comment below.

New WordPress Plugin: SmartCrop

I’ve written and released a new WordPress plugin called SmartCrop. Instead of creating cropped thumbnails from the center of an uploaded image, SmartCrop attempts to automatically determine the most interesting part of the image and centers the crop there.

It’s most easily explained with this example:

Viper’s Video Quicktags WordPress Plugin Discontinued

I’m officially discontinuing my Viper’s Video Quicktags WordPress plugin. It was one of the first plugins I ever wrote over 10 years ago. Back then embedding videos into WordPress posts was a chore and so I wrote the plugin to make the life of authors much easier.

Since then a lot has changed, namely the inclusion of native support in WordPress for even easier embeds, a feature that I actually contributed myself to WordPress.

Unfortunately users of my Video Quicktags plugin have been forced to keep the plugin activated so that embeds in old posts continue to work. Without the plugin, the shortcodes that the plugin created would cease working. So recently I wrote and released a tiny replacement plugin that creates those same shortcodes but has the native WordPress embed functionality handle the actual embedding of content.

If you are a Viper’s Video Quicktags plugin user, then I strongly recommend that you install my new plugin and then delete Viper’s Video Quicktags.

Besides switching away from a plugin I no longer support, advantages of the replacement plugin are modern, HTML5 embeds instead of Adobe Flash as well as automatic width to fit most themes, rather than fixed width independent of what theme you’re using.

It should be noted that the new plugin does not include the YouTube, Vimeo, etc. buttons in the editor but those are redundant due to how easy it is to embed videos directly from WordPress now — just paste the video’s URL on its own line.

Feel free to leave any questions or comments below.

WordPress Appearance On “Orphan Black”

In the latest episode of the great TV show Orphan Black, a character is searching for something on the Internet and is for some reason viewing search results in the form of HTML (ooo, what a hacker!). If you look at the stylesheet URLs, you’ll notice “wp-content”, a sign that it’s a WordPress-powered site!

WordPress On "Orphan Black"

Before you bother to check, the domain is registered in real life but there’s no site there, WordPress or otherwise.

For other sightings of WordPress on television, check out these posts.

Important Security Update For SyntaxHighlighter Evolved

If you use my popular SyntaxHighlighter Evolved WordPress plugin, please upgrade immediately. Ben Bidner discovered a security issue with the JavaScript highlighting library that my plugin uses. A couple of my Automattic co-workers and I worked with the author of that library to resolve the issue and the latest version of my plugin, 3.1.10, includes the fix.

Ideal WordPress Plugin Development Using PhpStorm 8

The upcoming PhpStorm 8 features built-in WordPress support, as explained in this support document. However what’s the best way to set up your WordPress install in order to write plugins? Here’s my personal answer — feel free to suggest alternatives in the comments section.

When working on a WordPress plugin, you don’t want functions, classes, variables, etc. from other plugins to leak into your current plugin through auto-complete or other types of automation. For this reason, I suggest avoiding opening a whole WordPress checkout with all of your plugins inside of it using PhpStorm. At the same time, you don’t want to have a separate copy of WordPress for each plugin that you work on. This is redundant and makes keeping WordPress up to date harder.

So instead do a single checkout of WordPress to its own folder and then define WP_PLUGIN_DIR and WP_PLUGIN_URL, as described on the Codex, so that your plugins folder will live outside of your WordPress folder. This way you can open and index the WordPress folder without getting all of your plugins along with it.

Now create a new project for each individual plugin. When doing so, you’ll want to add the WordPress folder as an include path in PhpStorm, as described in their documentation.

All of this will result in only your individual plugin’s folder showing up in PhpStorm but with WordPress showing up under the “External Libraries” list. This one WordPress install can be used in your browser to test all of your plugins but the plugin codes won’t overlap.

Date Queries In WordPress 3.7+

Earlier today, a patch for WordPress that I’ve been working on got committed to WordPress trunk. “Trunk” is the in-development version of WordPress and will eventually become the next version of WordPress, in this case 3.7.

My patch introduces the ability to do complex date-based queries for fetching both posts and comments from the WordPress database. In the past, you could select posts that had a specific value for year, month, etc. but there was no way to do things like selecting all posts before (or after) a certain date or selecting all posts between two different dates. With my patch, this and more is now easily possible.

Here’s some examples:

// Get the 10 most recent posts made
// between 9AM and 5PM on weekdays
$some_posts = new WP_Query( array(
	'date_query' => array(
			'hour' => 9,
			'compare' => '>=',
			'hour' => 17,
			'compare' => '<=',
			'dayofweek' => array( 2, 6 ),
			'compare' => 'BETWEEN',
	'posts_per_page' => 10,
) );

// Get all posts from this summer
// June 1st to August 31st, inclusive
// Note that strtotime()-compatible strings can be used
$some_posts = new WP_Query( array(
	'date_query' => array(
			// String via strtotime()
			'after'     => 'June 1st, 2013',
			// Or if you want, an array
			'before'    => array(
				'year'  => 2013,
				'month' => 8,
				'day'   => 31,
			'inclusive' => true,
	'posts_per_page' => -1,
) );

// Any posts made over a year ago
// but modified in the past month
$some_posts = new WP_Query( array(
	'date_query' => array(
			'column' => 'post_date_gmt',
			'before' => '1 year ago',
			'column' => 'post_modified_gmt',
			'after'  => '1 month ago',
	'posts_per_page' => -1,
) );

It works for comments too:

// All comments from post ID 123
// that are within the past week
$some_comments = get_comments( array(
	'post_ID' => 123,
	'date_query' => array(
			'after' => '1 week ago',
) );

As you can see, the possibilities and combinations of cool things you can do are endless.

Here’s all of the possible arguments:

'date_query' => array(
	'column' => 'optional, column to query against, default is post_date',
	'compare' => 'optional, see WP_Date_Query::get_compare()',
	'relation' => 'optional, OR or AND, how the sub-arrays should be compared, default is AND',
		'column' => 'see above',
		'compare' => 'see above',
		'after' => 'string or array, see WP_Date_Query::build_mysql_datetime()',
		'before' => 'string or array, see WP_Date_Query::build_mysql_datetime()',
		'inclusive' => 'boolean, for after/before, whether exact value should be matched or not',
		'year' => '4 digit int',
		'month' => 'int, 1-12',
		'week' => 'int, 0-53',
		'day' => 'int, 1-31',
		'hour' => 'int, 0-23',
		'minute' => 'int, 0-60',
		'second' => 'int, 0-60',

Additionally, all of the old-school date and time arguments for WP_Query are now handled by my code as well. They will continue to work as before and you only need to use the date_query parameter if you want more advanced control of your results.

Questions? Anything you want me to clarify? Leave a comment below. 🙂

Important Security Update For SyntaxHighlighter Evolved

If you use my SyntaxHighlighter Evolved WordPress plugin, please update ASAP. There’s a security issue with the Flash file that is used by version 2 of the highlighting library. This file is meant to be used for allowing one-click copying of the code to your clipboard (since normal copy/paste doesn’t work with it) but the file reportedly suffers from a cross-site scripting security issue.

Even if you use the better version 3 of the library (the default for my plugin), the file from version 2 of the library will still be included in the plugin’s files.

As a temporary fix, I have emptied out the file. This unfortunately means your visitors will not easily be able to copy any code you paste. I recommend switching to the superior version 3 via my plugin’s settings page. Code highlighted using the newer version can be selected and copied normally.

Feel free to leave any questions you have about this security issue on this post but please leave other general SyntaxHighlighter comments on the plugin’s homepage. Thanks.

WordPress: Debug Functions Attached To A Filter

I was debugging something in WordPress, trying to figure out what callback function was applying a change to a filter (in this case a post’s content). To get a list of what functions were hooked into the filter, I threw together a quick helper function and I thought I’d post it here incase anyone else found it useful.

function viper_debug_filter( $filter ) {
	add_filter( $filter, function( $value ) {
		global $wp_filter;

		$filters = array();

		foreach ( (array) $wp_filter[ current_filter() ] as $priority => $functions ) {
			foreach ( (array) $functions as $function => $args ) {
				$filters[$priority][] = $function;

		var_dump( current_filter(), $filters );

		return $value;
	} );

// Pass the filter name here
viper_debug_filter( 'the_content' );

Nothing fancy like excluding itself from the output — it was just a quick and dirty hack. Use it as you see fit.