Automating Grunt Builds in PhpStorm

I’ve started using PhpStorm for doing PHP development. So far, it’s been great. I find that I need to have significantly fewer programs and windows open, and that it automates a lot of the tasks I was doing manually.

Today, I puzzled out how to have PhpStorm invoke Grunt instead of running grunt watch in a terminal window:

  1. Navigate to Project Settings > File Watchers.
  2. Click + > Custom.
  3. Name: Grunt.
  4. Show console: Always.
  5. Deselect Immediate File Synchronization.
  6. File type: Any.
  7. Scope: Click button.
    1. Click + and add a new scope – name it Grunt Watch, click OK.
    2. Expand this window.
    3. With your scope selected, browse in the file tree and select directories that Grunt would be watching and click Include Recursively.
    4. Select files that Grunt is outputting (such as minified CSS and JS files) that you included in the previous step and click Exclude (this prevents the resulting output file from endlessly re-triggering Grunt execution).
    5. Click OK.
  8. Program: (browse to grunt executable path).
  9. Working Directory: (browse to the directory that contains the Grunt file).
  10. Click OK to create the File Watcher.
  11. Click OK to exit the Preferences dialog.

A Vagrant Script to Automatically Enable Apache Sites

At work, we are starting to use Vagrant to manage our virtual machines, and are largely having great success with it. Through mapping a virtual directory back to a source folder on our Mac, we are able to use the same git repositories across multiple virtual servers and operating system environments, and thus Vagrant automates most of the VM build and configuration process for us.

One area that isn’t automated, that we decided should be, is mapping the Apache configuration files stored in our git repositories to Apache automatically. I wrote this small script and placed it in our Puppet / PuPHPet files/exec-always directory, which crawls our git folders looking for local configuration files and mapping them into an Apache conf file at initial vagrant up and then at every reboot:

We have PuPHPet set up to map /Volumes/Sites to /var/www, so that /var/www contains all of our repos. Apache config is found in /var/www/reponame/apache/local.conf – if your configuration differs the above would need to be modified. However, it automates the process of setting up Apache config, which just helps us develop faster. Combine this tactic with the use of dnsmasq to automatically resolve all addresses ending with a custom TLD directly to the virtual machine, it also eliminates the need to modify the hosts file for each new site.

EDIT: Depending on how fast the mapping to /var/www happens, it is possible that Apache will attempt to load configuration from /var/www before it is actually mounted, causing Apache to error out and fail to start. I changed the Apache reload directive for a restart directive to ensure that Apache starts after loading the config, which is already being delayed by 30 seconds to give the filesystem time to fully mount.

Performance Patch for WP_Meta_Query in WordPress Core

WP_Meta_Query has a problem – it doesn’t perform well when using the OR operator with multiple key/value pairs for comparison. The performance worsens exponentially with each additional key/value pair added to the query. The problem is due to how the SQL query is constructed. Let’s take an example WP_Query containing a meta query:

The above query produces the following SQL statement:

On the install where I ran this test, the raw SQL query execution time was 9.154 seconds on a WordPress install with 4,445 rows in the posts table and 40,453 rows in the postmeta table.

Why is query execution performance so poor?

The root of the problem is the fact that the query is performing three INNER JOIN operations before filtering the results using the WHERE clause. The problem worsens exponentially with every additional meta query parameter, because each parameter results in another INNER JOIN. In this example, the first record has 8 meta values, and is joined to itself three times, which results in 8 * 8 * 8 = 512 rows for one post. Multiply this times the total number of posts, and you can begin to see why it takes so long to run the query.

Additionally, the INNER JOIN operation is tacking the postmeta columns onto the columns for the post, once for each time the INNER JOIN is executed. Although only the ID column is being selected, the key and value columns are needed for comparison, so they need to exist in memory in order to complete the query.

How this can be improved

Basically, WordPress is compiling a massive temporary table in memory, and then paring it down with a series of WHERE clauses. We can improve on that by inverting the logic, and instead selecting from a series of smaller result sets using subqueries:

This query runs in 0.035 seconds, which is about 260x faster for a meta_query with three OR values on this database than the native WordPress meta query SQL.

Increasing the query limit to 100 results in negligible increases in the new query’s execution time – increasing by only 0.001 seconds – whereas the WordPress native meta query increases by 0.795 seconds.

The patch

You can download the patch file and try it yourself.

I have also submitted the patch to WordPress.org Trac #24093.

Fixing WordPress Permissions

Problem: Setting your site’s WordPress permissions according to the instructions found on the official Changing File Permissions page results in the dreaded FTP credentials prompt (“To perform the requested action, WordPress needs to access your web server”).

How to Reproduce: Setting the owner as a user other than the web server user, and trying to manage permissions using group membership by giving write permissions to the web server user’s group. For example:

Reason: WordPress (in /wp-admin/includes/file.php) checks the file owner to determine whether direct modification is possible, ignoring group membership entirely:

Solution: Add a line near the end of your wp-config.php file to force WordPress to use direct upgrades, bypassing the get_filesystem_method check entirely:

Fixing Display Bug in Chrome on Virtualized Ubuntu

I was having a rather large problem with Chrome in my virtualized Ubuntu 12.04 Desktop build causing a glitch with the virtualized graphics driver that would crash not just Chrome, not just my VM, but my entire OSX session. I wouldn’t be able to break out of fullscreen/mouse/keyboard capture and therefore couldn’t force-close the VM, and I would have to reboot my entire system. The display glitch seemed to only happen on sites with somewhat advanced layouts, and might be related to either Z-indexing or transparent 24-bit or 32-bit PNGs.

One notable example was the Chrome Web Store – I knew something was amiss when the display wouldn’t redraw on an action (such as a link click) without switching to a different tab and switching back. Other things were happening as well – sometimes my mouse wouldn’t be visible inside the Chrome window that was affected, or tabbing to another window to put it on top of the Chrome window would show the affected area of the Chrome window on top of the program that should have been visible. Sometimes the VM would crash of its own accord, and sometimes it was tied to doing certain things – clicking, switching tabs, closing tabs, etc.

After a bit of Googling, I discovered a post about a related issue that I think has fixed my problem. Edit both /opt/google/chrome/google-chrome.desktop and /usr/share/applications/google-chrome.desktop and modify all lines that begin with Exec= to include the following flag at the end:

–blacklist-accelerated-compositing

It appears that the problem is caused by the virtualized graphics acceleration not playing nicely with some of the code in Chrome. I haven’t had this problem with Firefox, but I did have it with Chromium, so I would imagine that a similar execution flag for Chromium would solve the problem for those users as well. I debated about just using Firefox, but I use the Chrome Inspector heavily in my development, and prefer it to Firebug / Firefox Inspector.