Author: Daniel Pataki

Batch Renaming Files in OSX With Regex

For an awesome new WordPress theme I have bought the wonderfull Glyphicons package. For various reasons I needed to batch rename all the 800+ files removing the ‘glyphicons_003_’ but from the beginning. I thought automator would help, but it turns out that it’s search and replace doesn’t support wildcards or regular expressions!

I am no command line expert but I managed to hack the following together for this:

zmv 'glyphicons_([0-9][0-9][0-9])_(*).png' '$2.png'

You’ll need to have Z Shell (zsh) installed and you might need to use autoload zmv before entering the code above, other than that it should work fine.

I still need to take a look at how the regex works here exactly since it’s not completely standard for sure. For one thing the dot character is treated as a literal.

In any case, if you need a quick and dirty job done you should be able to modify the example above for your own needs.

Standardizing custom and default page menus in WordPress

I’ve wanted to get around to standardizing menus for a while now. When you use the <code>wp_nav_menu()</code> function and the user does not have a default menu set for the location in question the <code>wp_page_menu()</code> 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 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 bs_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 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

Photoshop Auto Select Layers Keyboard Shortcut

The most useful thing I’ve come across in a while is how to auto select layers in Photoshop. I’ve been doing this by clicking the checkbox in the toolbar but this is just wasteful as I generally need to untick it when I move something. While not a keyboard shortcut for auto select you can use Command+Control+Click to select the layer of the pixel the mouse cursor is over. This will probably save me 10 minutes daily!

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…

A common site for center-aligned items

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:

Much cleaner and much more readable!

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

Media Custom Fields In WordPress

A while ago I created a plugin names Media Custom Fields which allows you to add custom fields to WordPress attachments. The functionality was broken in WordPress 3.5 due to a problem with one of the hooks.

However, you can still add media custom fields by adding meta boxes to the attachment post type. The drawback of this is that the custom fields won’t show up when uploading your media, only on single item pages.

The only thing you’ll need to keep in mind is that you’ll need to hook the save function to save_attachment and edit_attachment instead of just the usual save_post hook.

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_function() {
    do_action( 'my_body_function' );
}

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

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

Note that the ‘my_body_function’ 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 <code>add_meta_box()</code> 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.

Loading Multisite Functions

I was installing WordPress as a subdomain multisite install, knowing that I would need to exclude some domains. I still wanted the wildcard subdomain option though so we could just create sites on the fly. Getting this up and running is not difficult, the problem was that I wanted to use WordPress functions on the “extra” subdomain, but not WordPress itself.

Usually this is not that difficult. Say you have a WordPress website at http://mysite.com. You can create a folder in that directory called ‘stuff’ with an index.php file. If you visit http://mysite.com/stuff the index.php file handle the display, not WordPress. What you can usually do in this situation is include the ‘wp-load.php’ file from your WordPress install and voilla, you can use all WordPress functions.

With a multisite install this isn’t the case. If you include ‘wp-load.php’ WordPress will know you’re loading the code from a subdomain which is not a part of your sites. Depending on your registration settings it will forward you somewhere. You can change the location of the forwarding, but you can’t disable it.

After mucking about in the source code I figured out that if you define the <code>$current_site</code> and <code>$current_blog</code> objects before you include ‘wp-load.php’ all will be well. WordPress will think you are on the specified site and it will not redirect you. You can then use any WordPress code or switch between blogs using <code>switch_to_blog()</code>

$current_site = (object) array(
	'id' => 1,
	'domain' => 'mydomain.com',
	'path' => '/',
	'blog_id' => 1,
	'cookie_domain' => 'mydomain.com',
	'site_name' => 'My WP Network Site',
);
$current_blog = (object) array(
    'blog_id' => 1,
    'site_id' => 1,
    'domain' => 'mydomain.com',
    'path' => '/',
    'registered' => '2012-10-27 01:40:55',
    'last_updated' => '2012-10-29 07:00:34',
    'public' => 1,
    'archived' => 0,
    'mature' => 0,
    'spam' => 0,
    'deleted' => 0,
    'lang_id' => 0,
);

include( SITEPATH . '/wp-load.php' );

I would like to stress that this sucks. However, it seems to be the only way to do it without actually creating a site for the subdomain. If anyone knows a better solution please-please let me know in the comments!

Automated Beanstalk Revision Notifications

I use Beanstalk as an SVN server and I absolutely love it! One of the great features it has is “Web Hooks” 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 blow in Gmail.