Presentation: Welcome to the Family (WordCamp Toronto 2012)

Welcome to the Family

Becoming an healthy, active member of the WordPress community

WordCamp Orlando (photo from WordCamp Central)

Mohammad (Mo) Jangda

  • Code Wrangler with Automattic ( VIP)
  • batmoo
  • Twitter: @mjangda

If you use WordPress, you’re part of a family.

A very, very big one.

56,000,000 sites

17% of the web

Millions of users

Of the three most important people in WordPress,
the most important one is…


The very fabric of the WordPress community relies on community participation

Families only function if everyone pitches in. Otherwise…

WordPress is FreeAsInSpeech (not FreeAsInBeer)

The Great Uncle Ben once said, “With great power…”


Lots of ways to be a healthy, active member of the community.

Doesn’t matter if you’re a developer, blogger, business, superhero, designer, site owner, photographer, enterprise, artist, freelancer, writer, …

The most important thing is that you do something.
And you do it with the interests of the community in mind.
And don’t do stupid things like cause infighting.

How to give back?

Use WordPress

Even though it’s not the NBT (“Next Big Thing”).

Not just core, but everything else (plugins, themes, tools, APIs etc.)

Give feedback, criticism, or even just a “thanks”.


Share WordPress

Help the family grow. Tell everyone about it.

friends, family, strangers, everyone!

I got SWAG

Share Yourself

Docs: Codex or Tutorials

Help someone




(Meetup Group, WordCamps, conferences, library, etc.)

Share your code

Do the Open Source thing

Help Break WordPress

Beta test (3.5 Beta 1), Report bugs

Help Make WordPress


Patches, plugins, themes, tools, unit tests, etc.


Patches, themes, UI designs, UX testing, etc.



Someone else?

Test patches, copy editing, help text, etc.


For the feel-good feeling

To Learn

Example: free code review


Not just in the spiritual sense

Social, Financial Karma

Most importantly…

it’s necessary for the the continuity of the WordPress Project


You can’t spell WurdPress without a U.

Thanks. | @mjangda

Managing Your Editorial Workflow (WordCamp Toronto 2011)

The video of presentation at WordCamp Toronto 2011 on “Managing your Editorial Workflow” where I talk mostly about Edit Flow.

Looks like the video was cut off, which is probably a good thing since it wasn’t really my best performance (being my first WordCamp presentation and all). I also flail my arms alot.

Mo Jangda: Managing Your Editorial Workflow |

WordPress Debugging (WordCamp NYC 2012 Talk)

Here’s my presentation slides from WordCamp NYC 2012. Click on the slide below to go full-screen and arrow keys to navigate.


The end goal of debugging is to find the causes to cute (and not-so-cute) bugs so we can squish them.

Who am I?

  • Mohammad (Mo) Jangda
  • Toronto, ON
  • Code Wrangler, VIP at Automattic
  • Ice Cream fan
  • batmoo (.org)
  • @mjangda

When you debug, you work similar to a doctor or an investigator.

On a really high-level

  • Determine the problem
  • Gather information
  • Analyze the symptoms
  • Rule out improbable causes
  • Make educated or exact guesses about the root cause(s)
  • …and then fix the problem

Knowledge of the domain is important

If you don’t have a good understanding of WordPress (or javascript, or servers, or etc.), your ability to analyze the demonstrated symptoms is limited.

A good understanding of the problem is important

  • The more information we have the better suited we are to fix the problem.
  • If we don’t have enough information, we should gather more.

Collecting the right information

  • “I did, I saw, I expected.”
  • Reproduction steps, screenshots, environment data
  • Common patterns between the symptoms

Collect more than you need, then filter out the garbage.

It’s important to check all your bases and avoid letting assumptions trap you (“oh, it can’t be because of this, because of that…”)

5 Whys

Asking “Why?” is one of your most powerful tools!

The Problem: The YouTube video in my post isn’t showing up.

  • Why? It’s not being rendered on the page.
  • Why? The shortcode callback isn’t outputting anything.
  • Why? The attribute check is failing.
  • Why? The ID has a hyphen in it.
  • Why? YouTube changed its IDs.

(Not limited to 5!)

Always go to the source!

Start at the point of origin for the symptoms and work backwards until you pinpoint the cause of the bug.

Fatal error: Call to undefined function give_me_some_seos() in /Users/moo/Sites/wp/wp-content/themes/twentyeleven/functions.php on line 76

Point of origin

We need to determine where the problem is occurring and eventually originating:

  • server-level
  • database-level
  • application-level (server or client-side)
  • user-level

This will drive our investigation.


WordPress makes debugging easy.

Many built-in tools. More pluggable ones.

defined( ‘CONSTANTS’ );

define( 'WP_DEBUG', true );

Enables error reporting.

If your development environment does not have this set to true, you’re _doing_it_wrong().

defined( ‘CONSTANTS’ );

define( 'WP_DEBUG_DISPLAY', true ); // display_errors
define( 'WP_DEBUG_LOG', '/tmp/php_errors.log' ); // write errors to file

defined( ‘CONSTANTS’ );

Debugging SQL:

define( 'SAVEQUERIES', true );

Debugging CSS and JS:

define( 'SCRIPT_DEBUG', true );
define( 'CONCATENATE_SCRIPTS', false );
define( 'COMPRESS_SCRIPTS', false );
define( 'COMPRESS_CSS', false );
define( 'ENFORCE_GZIP', false );

Debug Bar

Firebug for your WordPress

If your development environment does not have this set to installed and activated, you’re _doing_it_wrong().

Debug Bar Extender

Variable trace, performance profiling, and more.

Debug Bar Extender

if ( class_exists( 'Debug_Bar_Extender' ) ) {
        add_action( 'wp_head', 'my_debug_trace_id' );
        add_action( 'comments_template', 'my_debug_trace_id' );
        add_action( 'wp_footer', 'my_debug_trace_id' );
        function my_debug_trace_id() {
                $post_id = get_the_ID();
                Debug_Bar_Extender::instance()->trace_var( $post_id, 'post_id via get_the_ID()' );

Debug Bar Extender

Profiler example.

Debug Bar: Roll Your Own

// Tracks remote requests made using the WordPress HTTP API and displays their results

class WPCOM_Debug_Bar_Remote_Requests extends Debug_Bar_Panel {
	var $ignore_urls = array(
	var $requests = array();
	var $status_counts = array();
	var $current_request = array();

	function init() {
		$this->title( __('Remote Requests', 'debug-bar') );

		add_filter( 'http_request_args', array( $this, 'log_http_requests' ), 99, 2 ); // after all args have been set up
		add_action( 'http_api_debug', array( $this, 'log_http_request_result' ), 0, 5 ); // as soon as it's complete

		$this->status_counts = array(
			'Informational (1xx)' => 0,
			'Success (2xx)' => 0,
			'Multiple Choices (3xx)' => 0,
			'Client Error (4xx)' => 0,
			'Server Error (5xx)' => 0,
			'Unknown' => 0,
	function render() {
		global $wp;
		<div id='debug-bar-remote-requests'>

				<span>Total Time</span>
				<?php echo number_format( $this->total_time, 2 ) . 's'; ?>
// ...

Other Developer Plugins

  • Debug bar Transients
  • Log Deprecated Notices
  • Monster Widget
  • Rewrite Rule Inspector


  • Hardcoded checkpoints (var_dump) (don’t discount this; it’s ghetto but powerful)
  • error_log (tail + xmpp on
  • debug_backtrace
  • alert / console.log (for javascript)
  • Roll your own…


Index: capabilities.php
--- capabilities.php	(revision 20851)
+++ capabilities.php	(working copy)
@@ -1314,6 +1314,10 @@
 	if ( ! isset( $wp_roles ) )
 		$wp_roles = new WP_Roles();
+	// Debug
+	echo 'Adding role:<br/>';
+	var_dump( $role, $display_name, $capabilities );
 	return $wp_roles->add_role( $role, $display_name, $capabilities );


Index: capabilities.php
--- capabilities.php	(revision 20851)
+++ capabilities.php	(working copy)
@@ -1314,6 +1314,10 @@
 	if ( ! isset( $wp_roles ) )
 		$wp_roles = new WP_Roles();
+	// Debug
+	error_log( 'Adding role: ' . var_export( array( $role, $display_name, $capabilities ), true ) );
 	return $wp_roles->add_role( $role, $display_name, $capabilities );

Homegrown: sekret “all” filter

add_action( 'all', function() {
    var_dump( current_filter() );
} );

Homegrown: dump all callbacks for a hook

function debug_get_functions_for_hook( $hook ) {
	global $wp_filter;

	if( ! isset( $wp_filter[$hook] ) )

	$functions = array();
	foreach( (array) $wp_filter[$hook] as $key => $actions ) {
		$functions['priority_' . $key] = array_keys( $actions );
	ksort( $functions );
	return $functions;
Mfields::dump_hook( 'the_content' );

Non-WordPress Tools

  • Web Inspector / Firebug
  • curl / Charles
  • Xdebug and integrated debugging for IDEs


Let’s work through some examples!

Problem: The Fatal Whitescreen

Problem: The Fatal Whitescreen

With define( 'WP_DEBUG', true );:

(in production, look at your error log)

Problem: The Fatal Whitescreen

Is the function defined anywhere?

$ ack "give_me_magic_and_seos"

Problem: Filters gone bad

Content showing for some posts but not others.

Problem: Filters gone bad

Content showing for some posts but not others.

Problem: Filters gone bad

Step 0. Verify the post content!

Problem: Filters gone bad

Step 1. Where and how is the content being output?

Goto our theme, content.php:

<div class="entry-content">
    <?php the_content( __( 'Continue reading <span class="meta-nav">&rarr;</span>', 'twentyeleven' ) ); ?>
    <?php wp_link_pages( array( 'before' => '<div class="page-link"><span>' . __( 'Pages:', 'twentyeleven' ) . '</span>', 'after' => '</div>' ) ); ?>
</div><!-- .entry-content -->

Problem: Filters gone bad

Step 2. What does the_content() do?

Goto core:

$content = get_the_content($more_link_text, $stripteaser);
$content = apply_filters('the_content', $content);

Problem: Filters gone bad

Step 3. What is manipulating the_content()?

var_dump( debug_get_functions_for_hook( 'the_content' ) );

Here's what we get:
array(4) {
    ["priority_1"] =>
        array(1) { [0]=> string(14) "polldaddy_link" }
    ["priority_10"] =>
        array(7) { [0]=> string(11) "wptexturize" [1]=> string(15) "convert_smilies" [2]=> string(13) "convert_chars" [3]=> string(7) "wpautop" [4]=> string(17) "shortcode_unautop" [5]=> string(18) "prepend_attachment" [6]=> string(25) "my_content_with_thumbnail" }
    ["priority_11"] =>
        array(2) { [0]=> string(16) "capital_P_dangit" [1]=> string(12) "do_shortcode" }
    ["priority_8"] =>
        array(2) { [0]=> string(45) "0000000072f50cfc0000000022e7a2b6run_shortcode" [1]=> string(41) "0000000072f50cfc0000000022e7a2b6autoembed" } }

Problem: Filters gone bad

Step 4. Investigate all callbacks.

add_filter( 'the_content', 'my_content_with_thumbnail' );

function my_content_with_thumbnail( $content ) {
        if ( has_post_thumbnail() ) {
                return get_the_post_thumbnail() . $content;

Problem: Comments disappearing!

Comments for a post (in fact, many posts) are “disappearing” when submitted.

Questions to ask:

* Did they actually disappear?
* Are they in the database?
* Are they flagged as spam?
* Are they being fetched correctly?
* Are they being fetched at all?
* Are they attached to the correct post?

Not all problems are obvious or visible

For example: cron event fails… but only sometimes.

How do we investigate these? Get Creative :)

(Remote logging; hacks, hacks, hacks)

Debugging is an art

  • Many right ways to do it. Many wrong (but the only) ways to do it.
  • Investigate, distill, hypothesize, test, conclude, solve.
  • Understand your domain and continually learn.
  • Understand and use your tools.

Posted from New York, New York, United States.

On $wpdb->prepare

If you do the following, you’re a terrible person:

$query = "SELECT ID from {$wpdb->posts} WHERE ID = %d";
$query = $wpdb->prepare( $query, $value );

There is absolutely no reason for prepare to be on a separate line.

Here’s how you do it the right way:

$query = $wpdb->prepare( "SELECT ID from {$wpdb->posts} WHERE ID = %d", $value );

One line. Simple, easy to read, and not confusing.

WordPress Distraction-Free Skin: Terminal/Matrix

Just Write! Like you're in the Matrix!

Because all the cool kids want to feel like they’re writing posts in the Matrix. (Inspired by Zen)


View on Github

Dogfooding Edit Flow

Note: Most of the code here is specific to my environment on Webfaction, github and for use with WordPress plugins. You can make it work for other setups (i.e. different hosts, local gits, or even SVN) but will involve some tweaking.

Scott recently had a great idea to run the bleeding edge release of Edit Flow on our official site. I usually do this for most of my plugins before releasing, though, it’s a manual process: FTP up the latest code and give it a test run. That’s not fun.

Here’s a far better, automatized way to keep your repo up-to-date. You can either use cron or githooks. Pick your poison.

Continue reading