WordPress Upload Issues With Vagrant

It may be just my setup but if I create a virtual machine using Vagrant I usually end up with a WordPress installation that has trouble uploading files due to permission issues. This can be solved by setting the owner and the group in the Vagrantfile but this isn’t ideal.

If I set the owner and group to www-data WordPress works fine, but I need to sudo my commands in the terminal, even for a simple file creation operation. I finally had some time to figure this out and it turns out it isn’t that difficult.

You’ll need to edit the /etc/apache2/apache2.conf file in your virtual machine. Find the User and Group directives and make sure vagrant is used for both:

<code class='language-bash'>User vagrant
Group vagrant</class>

Once this is added, make sure to restart your server using sudo service apache2 restart and everything should be dandy. The terminal won’t scream for sudo all the time and WordPress will upload images/plugins/themes and such without a hitch.

Grunt Bus Error

While using grunt, more specifically the grunt-contrib-watch package I stumbled on a weird error. When I used grunt watch everything was dandy, but as soon as a change took place the script exited with a bus error.

According to the close notice on this issue, a similar issue was settled by updating node. The upgrade can be done via npm like so:

sudo npm cache clean -f
sudo npm install -g n
sudo n stable

That’s all there is to it, if you get a similar error try updating node, perhaps everything will pop back into place.

(Thanks to David Walsh for the upgrade method)

WordPress File Permission, Ownership And FTP Uploads

Do you have a WordPress website which won’t allow you to install and activate themes and plugins from the repository without asking for FTP data? This can be pretty annoying, especially during development where you may want to switch themes and plugins pretty often.

The solution to this problem is grossly misunderstood because this is not a file permission issue, it is actually a file ownership issue. You could change your file permissions to 777 and it still wouldn’t work, you’ll need to use chown to change the ownership of your files.

WordPress makes sure that the owner of the files is the same as the apache user. This is usually your user account, not root. So first of all, why can these sometimes be out of sync?

In my case this happened because I used a root login to gain ssh access to my server and upload an unzip WordPress. This created all the files and folders necessary but since I was logged in as root, the files and folders are owned by root.

Using the following command you can list all users in the account:

awk -F: '$3 >= 1000 && $1 != "nobody" {print $1}' /etc/passwd

you’ll need to select your user. This usually has something to do with your main domain, you may need to experiment a bit.

Once you know the user you’ll need to navigate to the root directory of your installation and issue a command like this:

chown username:group * -R

username should be the username you want to take ownership of the files and group is the group you’d like to use. I’m not sure what you should put there, I used root. I think this is safe, but I’m still checking.

In any case, once this command has been issued you can use ls -l . to show all permissions and you should see the change. Then, visit the theme install page and all should be well.

WordPress Plugin Activation Checks

I’ve noticed through our customers on Themeforest that quite a number of people have very old versions of PHP running on their servers. I’m talking pre 5.3 here which is now almost 5 years old. Here’s a quick way to make sure the plugin can’t be activated in this case, along with a friendly message.

function my_activation_check() {

	$php = '5.3';

	if ( version_compare( PHP_VERSION, $php, '<' ) ) {
		deactivate_plugins( basename( __FILE__ ) );
		wp_die(
			'<p>' .
			sprintf(
				__( 'My Awesome Plugin can not be activated because it requires a PHP version greater than %1$s. Your PHP version can be updated by your hosting company.', 'textdomain' ),
				$php
			)
			. '</p> <a href="' . admin_url( 'plugins.php' ) . '">' . __( 'go back', 'textdomain' ) . '</a>'
		);
	}

	return;

}
register_activation_hook( __FILE__, 'my_activation_check' );

If you require a specific WordPress version you could include that as well in a similar fashion.

Standardizing Custom And Default WordPress Menus

I’ve wanted to get around to standardizing WordPress menus for a while now. When you use the wp_nav_menu() function and the user does not have a default menu set for the location in question the wp_page_menu() function will be used. This function outputs a different structure and uses different classes. This makes it harder to style menus consistently with CSS.

Here’s a little snippet I worked on which tries to standardize these two WordPress menus. It’s still in beta, I’m testing it for a new theme so if you find any problems please do let me know.

function dp_nav_menu(){
	$menu = wp_page_menu( array(
		'menu_class' => 'menu-container',
		'echo'       => false
	));

	$menu = str_replace(
		array(
			'current_page_item',
			'current_page_parent',
			'current_page_ancestor',
			'<ul>',
			'page_item',
			'<ul class=\'children\'>'
		),
		array(
			'current-menu-item',
			'current-menu-parent',
			'current-menu-ancestor',
			'<ul class="menu">',
			'menu-item',
			'<ul class="sub-menu">'
		),
		$menu
	);

	echo $menu;
}

This should allow you to use roughly the same classes for both WordPress menus. Here are the things that are changed in the default menu:

  • sub menus have the ‘sub-menu’ class instead of the ‘children’ class
  • current items have the ‘current-menu-item’ class instead of the ‘current_page_item’ class
  • parent items have the ‘current-menu-parent’ class instead of the ‘current_page_parent’ class
  • item ancestors have the ‘current-menu-ancestor’ class instead of the ‘current_page_ancestor’ class

This function needs to be called as the fallback function of the wp_nav_menu() function, something like this:

$args = array(
	'theme_location'  => 'header_menu',
	'fallback_cb'     => 'dp_nav_menu',
);

wp_nav_menu( $args );

Center Aligned Elements With Graceful Line Break

I have no idea why I didn’t realize this before, but you can use the white-space CSS property to make elements line break nicely. I’ve been using this in menus and other places, but I had an epiphany today: this is ideal for post meta sections. I’m probably the last one in the World to realize this…

Some post information aligned a bit oddly
The line break makes the information seem odd

To make this problem disappear all you have to do is apply white-space:nowrap to the meta elements. Here’s the HTML (I removed links for brevity) :

<div class'metas'>
    <span class='meta date'>
        <span class='icon date'></span> Posted: October 16, 2012
    </span>
    <span class='meta tags'>
        <span class='icon tags'></span> Tags: black, purple, red 
    </span>
    <span class='meta categories'>
        <span class='icon category'></span> In: Characters, Special Posts
    </span>
    <span class='meta comments'>
        <span class='icon comment'></span> 6 comments
    </span>
</div>

Just apply the white-space property to the .meta class and you’re done, here’s the result:

Now that the icon is positioned correctly it's much better
Now that the icon is positioned correctly it’s much better

Get Only Posts With Featured Images

A neat trick you might need sometimes is to enable users to only show posts with featured images (galleries, etc). This is easily done using the WP_Query class like so:

$args = array(
    'post_type'        => 'post',
    'post_status'      => 'publish',
    'order'            => 'DESC',
    'meta_query'       => array(
        array(
            'key'     => '_thumbnail_id',
            'value'   => '',
            'compare' => '!=',
        )
    )
);
$awesome_posts = new WP_Query( $args );

You can add multiple meta fields to query with, just take a look at the Codex

The Missing WordPress Body Hook

WordPress is awesome, but one of the top features not yet included on my list is the availability of a built in “just after the opening body tag” hook. You can hook anything into the header using wp_head() or anything just before the closing body tag using wp_footer() but there’s nothing for the opening body tag, so let’s code it ourselves.

Why? Most prominently, Facebook recommends – when using the Javascript SDK – to put some javascript just after the initial body tag. If you’re building a theme for sale you’ll want to do this with hooks to make it easier for users to add their own API details.

To remedy this, we can use a custom hook, it’s really very easy. First, create a function that will act as our hook.

/* Header Stuff */
</head>
<body>
<?php my_body_hook() ?>
/* Body Stuff */

Next, let’s create this function and make it run all the functions associated with a specific hook.

function my_body_hook() {
    do_action( 'my_body_hook' );
}

Now all we need to do is hook other functions into this.

add_action( 'my_body_hook', 'add_facebook_sdk' );
function add_facebook_sdk() {
    echo '<div class="fb-root"></div>'
}

Note that the ‘my_body_hook’ name does not need to match the action name in the do_action() function, but it is easier to leave it the same.

Meta Boxes For Page Templates

Adding meta boxes to posts is fairly easy using the documentation found in the Codex. Restricting them to post types is a no-brainer, the functionality is built in using the fourth parameter of the add_meta_box() function. How about restricting meta boxes to page templates? All you need is 2 extra lines of code to detect which post you are currently on when using the function.

add_action( 'add_meta_boxes', 'my_meta_boxes' );

function my_meta_boxes() {
	$post_id = $_GET['post'] ? $_GET['post'] : $_POST['post_ID'] ;

	if( get_post_meta( $post_id, '_wp_page_template', true) == 'template-mashup.php' ) {

	    add_meta_box(
	        'classico_post_types',
	        __( 'Select Content Types', TEXTDOMAIN ),
	        'my_meta_boxes_box',
	        'page',
	        'side',
	        'high'
	    );

    }
}

All I’ve added is the detection of the post ID and to determine the template I grab the info from the _wp_page_template meta field.

Automated Beanstalk Revision Notifications

I use Beanstalk as an SVN server and I absolutely love it! One of the great features it has is Webhooks which can run before and/or after a deployment. You can read a bit about this on the Beanstalk Support Center, but here’s a quick and dirty working example.

include('wp-load.php');

$data = @file_get_contents('php://input');
$data = json_decode( $data );

add_filter(
	'wp_mail_content_type',
	create_function('', 'return "text/html";')
);

$headers[] = 'From: Daniel Pataki <myemail@mydomain.com>';

ob_start();
?>
	<p>
		"<?php echo $data->comment ?>"
	</p>

	<h3 style='margin:0 0 3px 0; padding: 0 0 3px 0; border-bottom:1px solid #ddd'>
		Details
	</h3>

	<table>
		<tr>
			<td style='text-align:right; padding-right:11px;'>
				<strong>repository</strong>:
			</td>
			<td> <?php echo $data->repository ?></td>
		</tr>
		<tr>
			<td style='text-align:right; padding-right:11px;'>
				<strong>revision</strong>:
			</td>
			<td> <?php echo $data->revision ?></td>
		</tr>
		<tr>
			<td style='text-align:right; padding-right:11px;'>
				<strong>date</strong>:
			</td>
			<td> <?php echo $data->deployed_at ?></td>
		</tr>
		<tr>
			<td style='text-align:right; padding-right:11px;'>
				<strong>server</strong>:
			</td>
			<td> <?php echo $data->environment ?></td>
		</tr>
		<tr>
			<td style='text-align:right; padding-right:11px;'>
				<strong>programmer</strong>:
			</td>
			<td> <?php echo $data->author_name ?></td>
		</tr>
	</table>

<?php
$message = ob_get_clean();

wp_mail( 
	'imsendingittoyou@mail.com', 
	$data->repository . ' | new revision (' . $data->revision . ')', 
	$message,
	$headers 
);

I include wp-load.php just because WordPress is there anyway and it gives me access to wp_mail(). You can use the regular old mail() function or any other method of course.

The point here is that the data can be retrieved using file_get_contents('php://input') and once you json_decode() it you can use all the available parameters. If you use my code, you’ll get something like the image below in Gmail.

An email triggered by a Beanstalk Webook