When was the last time you were deeply motivated to do something positive because you felt ashamed? Ashamed that you did something naive or downright silly because you didn’t know any better? Embarrassed because more experienced people mocked you instead of quietly helping?

People are not positively motivated by shame.

Sometimes guilt can be helpful, but guilt comes after knowingly doing something wrong.
Sometimes embarrassment can be helpful, because it helps us to be more cautious after an honest mistake.

But, shame? Nope. It’s different than guilt or embarrassment.

Shame, however, is born of ignorance or of not having mastered a concept…that we think we have mastered.

And public shaming smacks of a superiority complex. The shamer is dragging the shamed out into the public square, and everyone loses, because the former is displaying questionable motives while the latter learns just about nothing.

Well, not nothing. They’re probably learning that the community doing the shaming isn’t worth being a part of.

Exhibit A: WordPress

The WordPress community hasn’t always been the best at welcoming new people—in that manner, it’s really not different from any other community that revolves around a codebase. There’s been a concerted effort in the past few years to be inclusive and accessible, though, and I do believe it’s paying off. Friendly WordPressers are being more helpful than ever, and WordCamps are bastions of sharing and learning.

Even outlandish requests in Trac (WordPress core’s ticketing system) are being handled with more grace then ever.

But, in an effort to push WordPress standards to make a better community overall, we have to be mindful of our tendency to shame those who aren’t doing it “right.” Instead, back away from your Twitter account, and take the time to contact someone personally with a helpful attitude.

For instance, here are some unhelpful, shaming public statements:

  • Who does that?!
  • Someone is getting paid to do that?!
  • What a shady business. I feel bad for their customers.
  • It’s sad that people can get talked into that.

Now, here are some helpful alternatives:

  • I know your theme/plugin is successful, so can we talk about your use of best practices?
  • I have a client who’s having trouble switching from your platform to another. How can we fix this?
  • May I send you an email with some suggestions that would make your product more valuable overall?

Shame will not motivate anyone to do better, but constructive, empathetic criticism often will. By affirming that someone’s work already has value and respecting that, you’re in a much better place to offer suggestions. And, by coming from a better place, you’re far more likely to effect the change you want to see in a manner that builds everyone up.

Next time you see something being done wrongly, consider that the folks involved may not know they’re doing so. If it’s remotely possible, then public shaming is actually your least likely path to fixing the problem.

That is what you were aiming to do, right?

September 19, 2014 — Leave a comment — In Blog, Community, Development, WordPress

Sometimes, sites can get overloaded with spam comments—thousands per day. Whether this is the case, or you’ve just never emptied out your spam comments on a big site, you can end up with too many to trash. This is due to some restrictions to the amount of data that can be sent along with a request.

You can clean things up with some simple SQL queries—it’s much more efficient than trying to use the WordPress admin area when you need to remove spam comments in bulk.

Before you do anything, get a full backup of your database. Seriously.

Querying the Database

Depending on your hosting environment and your level of expertise, you’ll run these queries

  • using phpMyAdmin, in the SQL tab
  • using a database management GUI, like Sequel Pro
  • using the MySQL command-line tool

To check the output of any of these queries before actually deleting anything, replace DELETE FROM with SELECT * FROM. You’ll see all the rows that will be deleted when you run the real query.

As well, note that these queries assume your database table prefix is wp_. You might need to change it.

Spam Removal Queries

To delete all comments marked as spam, run:

DELETE FROM wp_comments WHERE comment_approved = 'spam';

That should clear out your spam comments area in the admin. You should see about as many rows affected as you had spam comments.

Meta Data Cleanup

Even after you delete all those comments, you’ll still be left with all their metadata cluttering your database.

If you use Akismet, you can run this to get rid of everything:

DELETE FROM wp_commentmeta WHERE meta_key LIKE '%akismet%';

This query will attempt to delete any comment that no longer exists. It’s a little more complex, so double check the output before deleting—hopefully, the previous query will do the hard work first.

DELETE FROM wp_commentmeta WHERE comment_id NOT IN (SELECT comment_id FROM wp_comments);

After all is said and done, optimize both the wp_comments and wp_commentmeta tables.

Now, go figure out how to stop that spam from ever getting to you in the first place. 🙂

July 9, 2014 — Leave a comment — In Blog, Development, Resources, WordPress

Here’s a quick tip for WordPress theme developers that seems to be a bit buried in the Codex.

If you wanted to add a class to the <body> element based on the page template being used, you can’t just go straight for the (usually helpful) is_page_template() function. It can’t be used inside The Loop.

Instead, we see a workaround at the bottom of that article that tells us to use get_page_template_slug().

In my case, I wanted to add a ‘bg-dark’ class to the <body> if mytemplate.php is the page template being used. Here’s how I was able to do it:

function prefix_conditional_body_class($classes) {
	if ( get_page_template_slug(get_the_ID()) === 'mytemplate.php' ) {
		$classes[] = 'bg-dark';
	}
	return $classes;
}

add_filter( 'body_class', 'prefix_conditional_body_class' );

You can run that code in any theme file being called, including functions.php.

May 27, 2014 — Leave a comment — In Blog, Development, Resources, WordPress

Almost four years ago, I wrote what would be one of the most popular posts ever on this site: Taking Control of WordPress Gallery Styling (Without a Plugin). I think it resonated because WordPress’s gallery styling has been heavy-handed, injecting a <style> tag and snippet directly into the page with some mildly arbitrary CSS.

Things have changed with the release of WordPress 3.9. You can now declare theme support for HTML5 galleries (and captions), which outputs <figure> and <figcaption> elements and removes the default, injected styling. Now, we can have control over the gallery style more easily.

Enable HTML5

The first step is declaring support for HTML5 galleries—I’d recommend going ahead with captions, too. Make sure you’re on WordPress 3.9, and add this to a theme file (yes, functions.php is fine):

add_theme_support( 'html5', array( 'gallery', 'caption' ) );

Styling

You’ll need to style the galleries yourself now, including that horizontal distribution that WordPress did do really well. You can start with what used to be injected, which I’ve adapted to work with classes instead of IDs:

.gallery {
  margin: auto;
}

.gallery .gallery-item {
  float: left; // Change to 'right' if RTL is enabled
  margin-top: 10px;
  text-align: center;
}

.gallery img {
  border: 2px solid #cfcfcf;
}

.gallery .gallery-caption {
  margin-left: 0;
}

That’s certainly not required; it just gives you a starting point.

WordPress used to calculate the width of the items in a gallery using PHP, because we need to know how many items are in a row (“Columns”) and divide that by 100 to get the proper percentage. We can use JavaScript to set this width, because WordPress still adds a class to the gallery element telling us how many elements go in a row.

<script>
// Cache the Gallery element
var gallery = jQuery('.gallery');
if ( gallery.length > 0 ) {
  // Find the WordPress class that tells us how many columns to use
  var columns = jQuery.grep(gallery.attr('class').split(' '), function(v, i) {
      return v.indexOf('gallery-columns') === 0;
  }).join();
  // Get the number out of the class and calculate the width
  gallery.find('.gallery-item').width( 100/parseInt(columns.replace('gallery-columns-', '')) + '%' );
}
</script>

Lightbox

I like using Nivo Lightbox—so much so I built a WordPress plugin for it. You can grab that plugin and activate it, and it will work automatically throughout your site, including grouping galleries together automatically.

You can also easily integrate it into your theme. If you’re going that route, you ought to combine all the needed CSS and JS files with your theme files to gain any benefit—otherwise, just use the plugin. When integrating, I install Nivo Lightbox with Bower and enqueue the needed files with my existing Grunt configuration. Since the script is used nearly everywhere, we might as well include it in the main files.

You’ll want to do two things to integrate in this manner: change the theme CSS a bit and add the initiation call to your JavaScript file.

Nivo Lightbox CSS

I pull the CSS from the default Nivo Lightbox theme and put it in my own file for two reasons. First, since I’m including the files in a Grunt task, the paths to the small lightbox images (like the “close icon) need to be changed. Second, this allows me to make any visual changes I want. Just make sure those CSS components are pulled in after the main nivo-lightbox.css file.

Nivo Lightbox JS

To initialize the lightbox, we need to add a quick function call. The following is in my plugin that I linked up, but you’ll need it regardless:

<script>
jQuery(document).ready(function(){
    jQuery('.gallery a:has(img)').attr('data-lightbox-gallery', 'nivo-gallery');
    jQuery('a[href*=".png"]:has(img), a[href*=".gif"]:has(img), a[href*=".jpg"]:has(img)').nivoLightbox();
});
</script>

This looks through the page and initializes any link that’s pointing to an image, and adds a data attribute to gallery images so they’re grouped together.

You can add options inside the nivoLightbox() call as you wish.

That should get you started! Looking back on an old article, seeing its popularity, and seeing WordPress naturally evolve to address its concerns is encouraging.

I hope this updated article helps you move forward in building great websites. As always, feel free to leave questions in the comments area.

May 9, 2014 — 2 Comments — In Blog, Development, Tutorial, WordPress

I’m constantly looking for ways to make WordPress more palatable for the common user (see: non-developers). It may be simple in comparison to other content management systems, but it’s still got some confusing artifacts. And, once you start adding robust plugins, things can get messy.

Here are some of my approaches to optimizing the WordPress admin area, along with snippets for making it happen or links to a plugin.

Disable Editor and Updates

I can’t think of a good reason to ever use the built-in code editor in WordPress. If you’re far enough along to edit code, you’re far enough along to use a real code editor with FTP or version control. This will disable it entirely:

define( 'DISALLOW_FILE_EDIT', true );

If—and only if—you are consistently checking for updates and updating on your client’s behalf, and you don’t want them adding plugins autonomously, you can disable the ability to add and update plugins and themes:

define( 'DISALLOW_FILE_MODS', true );

The two lines above can go in wp-config.php or a plugin. Everything else from this point should go in a plugin.

Editor Permissions

I often want to give editors access to the Appearance menu, so I built a plugin that does that. No setup, no settings.

Hide Unnecessary or Sensitive Menu Items

The Tools > Available Tools menu item in WordPress provides no value to most of my clients (or me, for that matter). You can remove it from view with:

function yourplugin_remove_tools() {
   remove_submenu_page( 'tools.php', 'tools.php' );
}
add_action( 'admin_menu', 'yourplugin_remove_tools', 999 );

I also utilize plugins for caching and security, but I don’t really want either of those settings to be visible to folks if I’m helping them manage things. Here, I’ve removed the menu links for Better WP Security and W3 Total Cache:

function yourplugin_remove_tools() {
    remove_menu_page( 'better-wp-security' );
    remove_menu_page( 'w3tc_dashboard' );
}
add_action( 'admin_menu', 'yourplugin_remove_tools', 999 );

Note: these pages will still be accessible by visiting the proper URL. That means you can get to it, and it’s very unlikely that a user will stumble upon it. That’s the goal.

Hide Sensitive Plugins from the Plugins Page

Following the logic from above, there are some plugins that need to stay put and not be deactivated. In some cases, dropping plugins in the mu-plugins folder will work. That won’t do in all instances, so you can hide them from the plugins listing instead.

This removes the same two plugins:

function yourplugin_filter_plugins( $plugins ) {
    $hidden = array(
        'Better WP Security',
        'W3 Total Cache'
    );
    foreach ($plugins as $key => &$plugin ) {
        if ( in_array( $plugin["Name"], $hidden ) ) {
            unset($plugins[$key]);
        }
    }
    return $plugins;
}
add_filter( 'all_plugins', 'yourplugin_filter_plugins' );

Remove Specific Links from the Menu Bar

The W3 Total Cache plugin is a good example here: sometimes, I want to leave the menu option for purging cache available to users with permission. However, I don’t want the ‘FAQ’ and ‘Support’ links that come along with that dropdown. So, I’ll just remove those specific links:

function yourplugin_remove_admin_bar_links() {
    global $wp_admin_bar;
    $wp_admin_bar->remove_menu('w3tc-faq');
    $wp_admin_bar->remove_menu('w3tc-support');
}
add_action( 'wp_before_admin_bar_render', 'yourplugin_remove_admin_bar_links' );

Remove Dashboard Widgets

Yes, you can use the ‘Screen Options’ menu to show/hide widgets on the Dashboard. However, the ‘WordPress News’ widget is pretty irrelevant to most of my clients. We can hide it completely, instead:

function yourplugin_disable_dashboard_widgets() {
    remove_meta_box( 'dashboard_primary', 'dashboard', 'normal' );
}
add_action( 'admin_init', 'yourplugin_disable_dashboard_widgets' );

All the Code as a Plugin

If you like everything you see here, you can use the boilerplate code in this gist. Change the prefixes to something relevant, fill in the other information, and customize as needed. Drop it in the mu-plugins folder (create that folder if you don’t have it). That’ll keep it activated automatically.

Also: don’t drop any of this code in functions.php. This has nothing to do with your theme, so it shouldn’t be dependent on it.

For any of these functions, you can make the result conditional by role, permissions, etc. A little digging around should help you figure any of that out.

I hope this helps you! I’m passionate about making WordPress a CMS that users love. Luckily, it’s easy to integrate code like this that removes what we don’t want.

March 7, 2014 — 3 Comments — In Blog, Development, Tutorial, WordPress