Category Archives: WordPress

Git post-receive hook to deploy WordPress and plugins as submodules

In a previous blog post I discussed how best to manage file and folder permissions when deploying with Git, but today I’ll show a specific example of what that post-receive hook might look like for a WordPress project that uses submodules.

I have three servers that I can deploy to, but the post-receive hook only deploys a project when it encounters the specified branch as defined per server:

  1. QA waits for a release branch
  2. Staging waits for the master branch
  3. Production waits for the master branch

Other than this small difference, the post-receive hook is identical on all three servers to reduce maintenance.

Lastly, each server has two repositories per project:

  1. Bare repository – storage unit that uses a post-receive hook to deploy the project.
  2. Working repository – web root that will serve the project to the end-user.

This method has several benefits:

  1. View a combined list of all version-controlled projects via the /opt/repositories directory.
  2. Recover a corrupted web root by cloning a fresh copy from the origin.
  3. Prevent some issues that may occur during the deployment, since it will fail before post-receive hook is fired.

Continue reading

Prevent contact form spam in WordPress with Contact Form 7 and Akismet


If you’re running WordPress and have a contact form on your website, there’s a good chance you’re using Contact Form 7. You can get away with using it as-is for a while, but as time goes on, spambots begin to find their way into your inbox.

At that point you have two options. You can deal with the spam via your:

  1. Website– prevent messages from ever being submitted.
  2. Inbox– tune your spam filter to delete those messages.

It seems logical to try and stop the messages as early as possible.

Most people would resort to something like CAPTCHA now, but I’m personally not a fan of it. I believe in keeping the user experience in tact for as long as I possibly can.

Enter Akismet, a service that can pretty reliably identify post comments containing spam. Luckily, what’s good for comments is also good for emails. It makes sense, too, because from a spambot’s perspective, both are submittable forms.

Continue reading

Bash script to mirror directory and database of website between servers


When you have a site that’s an on-going project, and you’re using a development, staging, and production server configuration, time and time again you’ll have a need to mirror the  production site content with your other environments.

Previously, this either meant to manually (FTP) or semi-manually (rsync) update the files, export the database, and in the case of WordPress MU, update certain records in the database. While the entire act isn’t hard, it has a zero-fun factor.

I put some time aside to write a small bash script that could automate this for multiple sites with just two commands. The script could definitely be improved, but it’s functional and gets the job done nicely, but I’m always open to suggestions and improvements.

I’ll go through the entire script, and if you find it useful, you can adapt it to meet your needs. Any variables or data you may need to change, will be highlighted in red below the code box.

You can find the entire code in a Gist. Note that there are two versions. One for server to server, the other for server to localhost. We’ll discuss the server edition below.

Table of Contents

  1. Program Skeleton
  2. Server Environment
  3. Production/Local Server Variables
  4. Program Arguments
  5. Display Functions (page 2)
  6. MySQL Functions
  7. Main Functions (page 3)
    1. Download Files
    2. Export Database
    3. Upload Files
    4. Import Database
  8. Run Functions (page 4)
    1. Run Synchronize
    2. Run Update
    3. Run
  9. Run Program (page 5)

Continue reading

Prevent WordPress from automatically purging trash from custom post type


WordPress has a constant called EMPTY_TRASH_DAYS that it automatically sets to 30. What that means is that WordPress will automatically delete all posts, pages, custom post types, etc, that have been in the trash for 30 or more days.

// wp-includes/default-constants.php

function wp_functionality_constants( ) {
	if ( !defined( 'EMPTY_TRASH_DAYS' ) )
		define( 'EMPTY_TRASH_DAYS', 30 );

Whenever you trash a post, WordPress creates a meta field called _wp_trash_meta_time containing the time it was trashed.

// wp-includes/post.php

function wp_trash_post($post_id = 0) {
	add_post_meta($post_id,'_wp_trash_meta_time', time());

WordPress has a daily event scheduled…

// wp-admin/admin.php

if ( !wp_next_scheduled('wp_scheduled_delete') && !defined('WP_INSTALLING') )
	wp_schedule_event(time(), 'daily', 'wp_scheduled_delete');

…that will run a function called wp_scheduled_delete to permanently delete all expired posts.

// wp-includes/functions.php

function wp_scheduled_delete() {
	global $wpdb;

	$delete_timestamp = time() - ( DAY_IN_SECONDS * EMPTY_TRASH_DAYS );

	$posts_to_delete = $wpdb->get_results($wpdb->prepare("SELECT post_id FROM $wpdb->postmeta WHERE meta_key = '_wp_trash_meta_time' AND meta_value < '%d'", $delete_timestamp), ARRAY_A);

	foreach ( (array) $posts_to_delete as $post ) {
		$post_id = (int) $post['post_id'];
		if ( !$post_id )

		$del_post = get_post($post_id);

		if ( !$del_post || 'trash' != $del_post->post_status ) {
			delete_post_meta($post_id, '_wp_trash_meta_status');
			delete_post_meta($post_id, '_wp_trash_meta_time');
		} else {

Continue reading