Presentation: Welcome to the Family (WordCamp Toronto 2012)

[presentation]

[slide]

Welcome to the Family

Becoming an healthy, active member of the WordPress community

WordCamp Orlando (photo from WordCamp Central)

[/slide]

[slide]

Mohammad (Mo) Jangda

  • Code Wrangler with Automattic (WordPress.com VIP)
  • batmoo@gmail.com
  • WordPress.org: batmoo
  • Twitter: @mjangda

[/slide]

[slide]

http://build.codepoet.com

[/slide]

[slide]

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

A very, very big one.

[/slide]

[slide]

56,000,000 sites

17% of the web

Millions of users

[/slide]

[slide]

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

[/slide]

[slide]

YOU!

[/slide]

[slide]

The very fabric of the WordPress community relies on community participation

Families only function if everyone pitches in. Otherwise…

[/slide]

[slide]

[/slide]

[slide]

WordPress is FreeAsInSpeech (not FreeAsInBeer)

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

[/slide]

[slide]

DON’T DO THIS

[/slide]

[slide]

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.
[/slide]

[slide]

How to give back?

[/slide]

[slide]

Use WordPress

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

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

[/slide]

[slide]

[/slide]

[slide]

[/slide]

[slide]

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

[/slide]

[slide]

Donate

[/slide]

[slide]

Share WordPress

Help the family grow. Tell everyone about it.

friends, family, strangers, everyone!

[/slide]

[slide]

I got SWAG

[/slide]

[slide]

[/slide]

[slide]

Share Yourself

Docs: Codex or Tutorials

Help someone

[/slide]

[slide]
Forums
http://wordpress.org/support/

StackExchange
http://wordpress.stackexchange.com/

Twitter
http://twitter

(Meetup Group, WordCamps, conferences, library, etc.)
[/slide]

[slide]

Share your code

Do the Open Source thing

[/slide]

[slide]

Help Break WordPress

Beta test (3.5 Beta 1), Report bugs

[/slide]

[slide]

Help Make WordPress

make.wordpress.org

[/slide]

[slide]

Developer?

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

Designer?

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

Multilingual?

Translations

Someone else?

Test patches, copy editing, help text, etc.
[/slide]

[slide]

http://make.wordpress.org/core/handbook/

[/slide]

[slide]

Why?

[/slide]

[slide]

For the feel-good feeling

[/slide]

[slide]

To Learn

Example: free code review

[/slide]

[slide]

Karma

Not just in the spiritual sense

Social, Financial Karma

[/slide]

[slide]

Most importantly…

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

[/slide]

[slide]

YOU!

[/slide]

[slide]

You can’t spell WurdPress without a U.

[/slide]

[slide]

Thanks.

batmoo@gmail.com | @mjangda

[/slide]

[/presentation]

Review: Peter Nimble and His Fantastic Eyes

Peter Nimble and His Fantastic Eyes
Peter Nimble and His Fantastic Eyes by Jonathan Auxier
My rating: 3 of 5 stars

This was a fun read but I had a hard time getting into it. The narration was a bit inconsistent, the dialog and characters seemed a bit forced. And I had a hard time getting over the fact that what seems obviously like a children’s book has so much blood.

Also, “I seen this movie before”. It’s called Star Wars ;)

View all my reviews

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.

[wpvideo qDTbwS5Y]

Mo Jangda: Managing Your Editorial Workflow | WordPress.tv.

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.

[presentation]
[slide]

Debugging

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


[/slide]

[slide]

Who am I?

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

[/slide]

[slide]

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


[/slide]

[slide]

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

[/slide]

[slide]

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.

[/slide]

[slide]

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.

[/slide]

[slide]

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…”)
[/slide]

[slide]

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!)

http://en.wikipedia.org/wiki/5_Whys
[/slide]

[slide]

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

[/slide]

[slide]

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.
[/slide]

[slide]

Tools

WordPress makes debugging easy.

Many built-in tools. More pluggable ones.
[/slide]

[slide]

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().
[/slide]

[slide]

defined( ‘CONSTANTS’ );

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

[/slide]
[slide]
On OS X, use console.app: http://zroger.com/2009/07/quick-tip-use-console-app-to-view-mamp-logs-in-osx/

[/slide]

[slide]

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 );

[/slide]

[slide]

Debug Bar

Firebug for your WordPress

http://wordpress.org/extend/plugins/debug-bar/

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

[slide]

[/slide]

[slide]

[/slide]

[slide]

Debug Bar Extender

Variable trace, performance profiling, and more.

http://wordpress.org/extend/plugins/debug-bar-extender/

[/slide]

[slide]

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()' );
        }
}

[/slide]

[slide]

Debug Bar Extender

Profiler example.
[/slide]

[slide]

Debug Bar Extensions: Console

http://wordpress.org/extend/plugins/debug-bar-console/


[/slide]

[slide]

Debug Bar Extensions: Cron

http://wordpress.org/extend/plugins/debug-bar-cron/


[/slide]

[slide]

Debug Bar: Roll Your Own

<?php
// 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(
		'http://127.0.0.1/wp-cron.php?doing_wp_cron',
	);
	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'>

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

[/slide]

[slide]

Other Developer Plugins

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

[/slide]

[slide]

Developer Plugin

https://github.com/automattic/developer/


[/slide]

[slide]

Homegrown

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

[/slide]

[slide]

var_dump

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 );
 }

[/slide]

[slide]

error_log

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 );
 }

[/slide]

[slide]

Homegrown: sekret “all” filter

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

[/slide]

[slide]

Homegrown: dump all callbacks for a hook

function debug_get_functions_for_hook( $hook ) {
	global $wp_filter;

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

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

[/slide]

[slide]
Mfields::dump_hook( 'the_content' );


[/slide]

[slide]

Non-WordPress Tools

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

[/slide]

[slide]

Xdebug


[/slide]

[slide]
Let’s work through some examples!
[/slide]

[slide]

Problem: The Fatal Whitescreen

[/slide]

[slide]

Problem: The Fatal Whitescreen

With define( 'WP_DEBUG', true );:

(in production, look at your error log)
[/slide]

[slide]

Problem: The Fatal Whitescreen

Is the function defined anywhere?

$ ack "give_me_magic_and_seos"
[/slide]

[slide]

Problem: Filters gone bad

Content showing for some posts but not others.


[/slide]

[slide]

Problem: Filters gone bad

Content showing for some posts but not others.


[/slide]

[slide]

Problem: Filters gone bad

Step 0. Verify the post content!
[/slide]

[slide]

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 -->

[/slide]

[slide]

Problem: Filters gone bad

Step 2. What does the_content() do?

Goto core: http://core.trac.wordpress.org/browser/tags/3.3.1/wp-includes/post-template.php#L157

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

[/slide]

[slide]

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" } }
*/

[/slide]

[slide]

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;
        }
        // THIS IS OUR PROBLEM! A MISSING RETURN!
}

[/slide]

[slide]

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?
[/slide]

[slide]

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)
[/slide]

[slide]

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.

[/slide]

[slide]

Questions?

[/slide]

[/presentation]

The need to code | jacquesmattheij.com

It’s like a drug. I’m still fascinated by it, even almost 30 years to the day later I still read about languages, new ways to solve old problems, all kinds of developments in software and hardware as though it is the first time that I hear about these things. It is a fascinating world, the world of software.

Jacques Mattheij

JavaScript Countdown Timer

I was in search of a JavaScript countdown timer (mainly because I’m too lazy to build it out myself — and because I’m sure millions before me have done the same), but Google wasn’t doing me much good. Most scripts would modify the DOM, directly but not make it easy to programmatically intercept the remaining time.

So, I picked one of the cleanest scripts and cleaned it up a bit.


/**
 * A sweet js countdown timer with a custom callback that gives you a JSON object!
 * Heavily modified code originally found on http://www.ricocheting.com/code/javascript/html-generator/countdown-timer
 *
 * @param string|Date String representation of when to countdown to. Date objects probably work too
 * @param callback Function triggered when the interval has passed
 * @param int Number of milliseconds for the timeout. Defaults to 1000 (1 second)
 *
 * @return object Returns a JSON object with properties: days, hours, minutes, seconds
 */
timer = function(endDate, callback, interval) {
    endDate = new Date(endDate);
    interval = interval || 1000;

    var currentDate = new Date()
        , millisecondDiff = endDate.getTime() - currentDate.getTime() // get difference in milliseconds
        , timeRemaining = {
            days: 0
            , hours: 0
            , minutes: 0
            , seconds: 0
        }
        ;

    if(millisecondDiff > 0) {
        millisecondDiff = Math.floor( millisecondDiff/1000 ); // kill the "milliseconds" so just secs

		timeRemaining.days = Math.floor( millisecondDiff/86400 ); // days
		millisecondDiff = millisecondDiff % 86400;

		timeRemaining.hours = Math.floor( millisecondDiff/3600 ); // hours
		millisecondDiff = millisecondDiff % 3600;

		timeRemaining.minutes = Math.floor( millisecondDiff/60 ); // minutes
		millisecondDiff = millisecondDiff % 60;

		timeRemaining.seconds = Math.floor(millisecondDiff); // seconds

        setTimeout(function() {
            timer(endDate, callback);
        }, interval);
    }
    
    callback(timeRemaining);
}

It’s easy to use! You specify an end date (as a string, though Date object’s should work as well) and pass in a callback that gets triggered at a set interval. The callback receives a JSON object with properties for days, hours, minutes and seconds. You can pass in a custom interval if you want the callback triggered at a different period. Examples below.


timer('2011-12-31', function(timeRemaining) {
	console.log('Timer 1:', timeRemaining);
});

// This will run every minute, instead of every second
timer('2012-12-31', function(timeRemaining) {
	console.log('Timer 2:', timeRemaining);
}, 60000);

Interested? See it in action: http://jsfiddle.net/mjangda/vGv7J/1/