List of Functions Removed from WordPress 3.6 RC2 since Beta 3 (and Added too)

On an ongoing client project at X-Team, since the site was to launch in the summer we took the initiative to build a new site on WordPress 3.6 trunk “knowing” that it would be released before then, and so we could utilize the new Post Formats UI and functions that went along with it. Alas. Initially we thought we could still retain the functionality that hooked into the new Post Formats UI, since the announcement was that “Posts Formats is exiting core, will live as a plugin”. So we expected that the WordPress 3.6 would be released with a companion plugin that restored the Post Formats UI removed from core in Beta 4. On June 10, I tweeted:

But all I got in response were crickets. And a month and a half later at WordCamp San Francisco, it became clear that the Post Formats UI was not going anywhere and would be completely rethought, including radical (exciting) ideas from Matt where a post would not be a format, but rather could contain multiple formats:

So it became clear that with the impending release of WordPress 3.6 and the abandonment of the Post Formats UI, that we’d have to immediately update our codebase from Beta 3 to RC2, and add our own plugin to support the Post Formats UI features that we relied on. But what API functions were removed in Beta 4 form Beta 3? I didn’t find a quick answer from the Google, but came up with a quick way to grep the codebase for the list.

So given a WordPress 3.6 Beta 3 install in a given Git repo, I did:

$ wp core update --version=3.6-rc2

Then to find the list of PHP functions removed since Beta 3, all I had to do was:

$ git diff -w -- $(git status -uno | grep '\.php$' | cut -c4-) | egrep '^-function' | sort

This produces this list of PHP Functions in WordPress 3.6 Beta 3 removed as of RC2:

-function _local_storage_notice() {
-function _post_formats_fix_empty_title( $data, $postarr ) {
-function _post_formats_generate_title( $content, $post_format = '' ) {
-function _post_formats_title( $title, $post_id = 0 ) {
-function _wp_post_revision_meta_keys() {
-function _wp_preview_meta_filter( $value, $object_id, $meta_key, $single ) {
-function add_chat_detection_format( $name, $newline_regex, $delimiter_regex ) {
-function attachment_url_to_postid( $url ) {
-function confirm_another_blog_signup($domain, $path, $blog_title, $user_name, \
                                      $user_email = '', $meta = '') {
-function edit_form_image_editor() {
-function esc_sql( $sql ) {
-function get_attached_audio( $post_id = 0 ) {
-function get_attached_image_srcs( $post_id = 0 ) {
-function get_attached_images( $post_id = 0 ) {
-function get_attached_media( $type, $post_id = 0 ) {
-function get_attached_video( $post_id = 0 ) {
-function get_content_audio( &$content, $html = true, $remove = false ) {
-function get_content_chat( &$content, $remove = false ) {
-function get_content_galleries( &$content, $html = true, $remove = false, $limit = 0 ) {
-function get_content_image( &$content, $html = true, $remove = false ) {
-function get_content_images( &$content, $html = true, $remove = false, $limit = 0 ) {
-function get_content_media( $type, &$content, $html = true, $remove = false, $limit = 0 ) {
-function get_content_quote( &$content, $remove = false, $replace = '' ) {
-function get_content_url( &$content, $remove = false ) {
-function get_content_video( &$content, $html = true, $remove = false ) {
-function get_embedded_audio( &$content, $remove = false ) {
-function get_embedded_media( $type, &$content, $remove = false, $limit = 0 ) {
-function get_embedded_video( &$content, $remove = false ) {
-function get_paged_content( $content = '', $paged = 0 ) {
-function get_post_format_content_class( $format ) {
-function get_post_format_meta( $post_id = 0 ) {
-function get_post_galleries( $post_id = 0, $html = true ) {
-function get_post_galleries_images( $post_id = 0 ) {
-function get_post_gallery( $post_id = 0, $html = true ) {
-function get_post_gallery_images( $post_id = 0 ) {
-function get_the_password_form() {
-function get_the_post_format_chat( $id = 0 ) {
-function get_the_post_format_image( $attached_size = 'full', &$post = null ) {
-function get_the_post_format_media( $type, &$post = null, $limit = 0 ) {
-function get_the_post_format_quote( &$post = null ) {
-function get_the_post_format_url( $id = 0 ) {
-function get_the_remaining_content( $more_link_text = null, $strip_teaser = false ) {
-function img_html_to_post_id( $html, &$matched_html = null ) {
-function paginate_content( $content ) {
-function post_format_content_class( $format ) {
-function post_formats_compat( $content, $id = 0 ) {
-function post_submit_meta_box($post) {
-function the_post_format_audio() {
-function the_post_format_chat() {
-function the_post_format_gallery() {
-function the_post_format_image( $attached_size = 'full' ) {
-function the_post_format_quote() {
-function the_post_format_url() {
-function the_post_format_video() {
-function the_remaining_content( $more_link_text = null, $strip_teaser = false ) {
-function wp_ajax_revisions_data() {
-function wp_ajax_show_post_format_ui() {
-function wp_text_diff_with_count( $left_string, $right_string, $args = null ) {

So now I can just look at our themes and plugins to see if we use any of these functions, and then create a Beta 3 compatibility plugin to implement them.


And out of curiousity, here is a list of the PHP functions added to WordPress 3.6 since Beta 3:

$ (git diff -w -- $(git status -uno | grep '\.php$' | cut -c4-) | egrep '^\+function' | cut -c2-; cat $(git status -uall --porcelain | grep '^??' | grep '\.php$' | cut -c4-) | egrep '^function') | sort

function _canonical_charset( $charset ) {
function _local_storage_notice() {
function confirm_another_blog_signup( $domain, $path, $blog_title, $user_name, \
                                      $user_email = '', $meta = array() ) {
function edit_form_image_editor( $post ) {
function esc_sql( $data ) {
function get_attached_media( $type, $post = 0 ) {
function get_media_embedded_in_content( $content, $types = null ) {
function get_post_galleries( $post, $html = true ) {
function get_post_galleries_images( $post = 0 ) {
function get_post_gallery( $post = 0, $html = true ) {
function get_post_gallery_images( $post = 0 ) {
function get_the_password_form( $post = 0 ) {
function get_url_in_content( $content ) {
function post_submit_meta_box($post, $args = array() ) {
function twentyeleven_admin_enqueue_scripts( $hook_suffix ) {
function twentyeleven_admin_header_image() { ?>
function twentyeleven_admin_header_style() {
function twentyeleven_auto_excerpt_more( $more ) {
function twentyeleven_body_classes( $classes ) {
function twentyeleven_color_schemes() {
function twentyeleven_comment( $comment, $args, $depth ) {
function twentyeleven_content_nav( $html_id ) {
function twentyeleven_continue_reading_link() {
function twentyeleven_custom_excerpt_more( $output ) {
function twentyeleven_customize_preview_js() {
function twentyeleven_customize_register( $wp_customize ) {
function twentyeleven_enqueue_color_scheme() {
function twentyeleven_excerpt_length( $length ) {
function twentyeleven_footer_sidebar_class() {
function twentyeleven_get_default_link_color( $color_scheme = null ) {
function twentyeleven_get_default_theme_options() {
function twentyeleven_get_first_url() {
function twentyeleven_get_gallery_images() {
function twentyeleven_get_theme_options() {
function twentyeleven_header_style() {
function twentyeleven_layout_classes( $existing_classes ) {
function twentyeleven_layouts() {
function twentyeleven_option_page_capability( $capability ) {
function twentyeleven_page_menu_args( $args ) {
function twentyeleven_posted_on() {
function twentyeleven_print_link_color_style() {
function twentyeleven_settings_field_color_scheme() {
function twentyeleven_settings_field_layout() {
function twentyeleven_settings_field_link_color() {
function twentyeleven_setup() {
function twentyeleven_theme_options_add_page() {
function twentyeleven_theme_options_help() {
function twentyeleven_theme_options_init() {
function twentyeleven_theme_options_render_page() {
function twentyeleven_theme_options_validate( $input ) {
function twentyeleven_url_grabber() {
function twentyeleven_widgets_init() {
function twentyten_admin_header_style() {
function twentyten_auto_excerpt_more( $more ) {
function twentyten_comment( $comment, $args, $depth ) {
function twentyten_continue_reading_link() {
function twentyten_custom_excerpt_more( $output ) {
function twentyten_excerpt_length( $length ) {
function twentyten_get_gallery_images() {
function twentyten_page_menu_args( $args ) {
function twentyten_posted_in() {
function twentyten_posted_on() {
function twentyten_remove_gallery_css( $css ) {
function twentyten_remove_recent_comments_style() {
function twentyten_setup() {
function twentyten_widgets_init() {
function twentythirteen_admin_header_image() {
function twentythirteen_admin_header_style() {
function twentythirteen_body_class( $classes ) {
function twentythirteen_content_width() {
function twentythirteen_custom_header_fonts() {
function twentythirteen_custom_header_setup() {
function twentythirteen_customize() {
function twentythirteen_customize_preview_js() {
function twentythirteen_customize_register( $wp_customize ) {
function twentythirteen_entry_date( $echo = true ) {
function twentythirteen_entry_meta() {
function twentythirteen_fonts_url() {
function twentythirteen_get_link_url() {
function twentythirteen_header_style() {
function twentythirteen_paging_nav() {
function twentythirteen_post_nav() {
function twentythirteen_preview() {
function twentythirteen_scripts_styles() {
function twentythirteen_setup() {
function twentythirteen_switch_theme() {
function twentythirteen_the_attached_image() {
function twentythirteen_upgrade_notice() {
function twentythirteen_widgets_init() {
function twentythirteen_wp_title( $title, $sep ) {
function twentytwelve_admin_header_image() {
function twentytwelve_admin_header_style() {
function twentytwelve_body_class( $classes ) {
function twentytwelve_comment( $comment, $args, $depth ) {
function twentytwelve_content_nav( $html_id ) {
function twentytwelve_content_width() {
function twentytwelve_custom_header_fonts() {
function twentytwelve_custom_header_setup() {
function twentytwelve_customize_preview_js() {
function twentytwelve_customize_register( $wp_customize ) {
function twentytwelve_entry_meta() {
function twentytwelve_get_font_url() {
function twentytwelve_header_style() {
function twentytwelve_mce_css( $mce_css ) {
function twentytwelve_page_menu_args( $args ) {
function twentytwelve_scripts_styles() {
function twentytwelve_setup() {
function twentytwelve_widgets_init() {
function twentytwelve_wp_title( $title, $sep ) {
function wp_ajax_get_revision_diffs() {
function wp_get_revision_ui_diff( $post, $compare_from, $compare_to ) {
function wp_http_validate_url( $url ) {
function wp_prepare_revisions_for_js( $post, $selected_revision_id, $from = null ) {
function wp_refresh_post_nonces( $response, $data, $screen_id ) {
function wp_style_add_data( $handle, $key, $value ) {

Do not change the default timezone from UTC in WordPress

I discovered something a bit surprising about WordPress related to timezones: WordPress explicitly sets and expects the default timezone to be UTC (in settings.php) and the date/time functions sometimes rely on the fact that the default timezone is UTC. For instance if you do date_default_timezone_set(get_option('timezone_string')) and then later try to get a GMT timestamp from get_post_time() or get_post_modified_time(), it will fail to give you the right date.

So from calling $timestamp = get_post_time('U', true /*GMT*/), if we step up into core:

function get_post_time( $d = 'U', $gmt = false, $post = null, $translate = false ) { // returns timestamp
	$post = get_post($post);

	if ( $gmt )
		$time = $post->post_date_gmt;
	else
		$time = $post->post_date;

	$time = mysql2date($d, $time, $translate);
	return apply_filters('get_post_time', $time, $d, $gmt);
}

You can see that it is going to pass post_date_gmt into mysql2date() but that this date/time (e.g. 2013-02-19 18:22:42) does not include with it any timezone information (a sad fact about the WordPress posts schema). So then mysql2date() is passed this timezone-free date/time:

function mysql2date( $format, $date, $translate = true ) {
	if ( empty( $date ) )
		return false;

	if ( 'G' == $format )
		return strtotime( $date . ' +0000' );

	$i = strtotime( $date );

	if ( 'U' == $format )
		return $i;

	if ( $translate )
		return date_i18n( $format, $i );
	else
		return date( $format, $i );
}

And the strtotime() is going to interpret that timezone-agnostic date as the time in the current timezone! So even though the original date/time is coming from $post->post_date_gmt, it is getting passed into strtotime() with a default timezone not being UTC/GMT, and so the end resulting date/time returned is not GMT as originally requested.

If you find your code does this, the quick solution to the problem is to just reset the default timezone to UTC once you’ve finished working in the other timezone:

date_default_timezone_set(get_option('timezone_string'));
// do some stuff
date_default_timezone_set('UTC');

But a more elegant solution would be to move to using DateTime objects and specify the DateTimeZone for each.

Anyway, this is something to be aware of, as I had to pull out a few hairs (and I don’t intend to go bald).

See also: Default timezone hardcoded as UTC? (Stack Exchange)

My X-Team Superhero Identity Revealed

Tonight we at X-Team had a very special meeting: the induction ceremony for new superheroes! X-Team employees are given superhero identities, and I was next in line for induction along with Wojtek Zając and Ben King. Our meeting was extra special because five of us have been together in Los Angeles this month working for a client on-site, and so we were able to meet in person while we logged in to our chat room to join up with everyone else around the world. So my superhero identity is:

Thunderboy

Thunderboy(Weston) is a highly intelligent and technologically resourceful elemental of Nordic descent who can manipulate, control weather and transcommunicate (via electronic voice) through his thundercloud static field. With his static field, he also is able to create lightning bolts and move within them, allowing him to travel at impressive speed.

The name is extra meaningful as it was the superhero name that I went by as a kid, so things have come full circle! Along with my name and description, I was also given a badge depicting my superhero self (right), and incidentally my mask actually looks quite similar to Condorman’s, my favorite old superhero movie. Thanks so much to my coworkers at X-Team for the effort that went into this and for making me feel so part of the team. It’s truly an honor to be working with you, such a talented international team!

Here’s the slightly-abridged transcript of our chat for the induction with the unveiling of my superhero:

tine: …and we have one more superhero to induct today.
tine: this is someone who was a superhero coming in, but sealed his superhero status within the first week of working with us.
tine: someone who’s taking us all by STORM and made a BIG, BIG impression.
tine: for this superhero, we travel back to the U.S, and to the Westcoast..and we welcome…

weston: yay!
benking gave weston a high five!
david gave weston a high five!
tine gave weston a high five!
adi gave weston a high five!
marconi gave weston a high five!
hz gave weston a high five!
dargaud gave weston a high five!
wojtek gave weston a high five!
vio gave weston a high five!
tine: @weston, you shall now be known as…
tine: DRUMROLL PLEASE
marconi: druuuuuuummmmmuuummmmummm
tine: daruuuuuumdrummmmmmmdrummmm
wojtek: come on Tine we’re drumrolling here 😛
tine: druuuuuuuuuuuuuuuumdarrrummm
tine: drrrrrrrrrrr
tine: uuuuuuuuum
tine: ruum
wojtek: Tine!!! 😀
Benking faints with anxiety
tine: Thunderboy
wojtek: yay :)
marconi: la la la la la la Thunder!
tine: Thunderboy is a highly intelligent and technologically resourceful elemental of Nordic decent who can manipulate, control weather and transcommunicate (via electronic voice) through his thundercloud static field. With his static field, he also is able to create lightning bolts and move within them, allowing him to travel at impressive speeds.
weston: That’s the superhero name I had as a kid :-)
Thunderboy
vio gave weston a high five!
marconi gave weston a high five!
benking: woe nice one weston
josh gave weston a high five!
josh: nice!!
adi gave weston a high five!
hz gave weston a high five!
tine gave weston a high five!
adi: congrats @weston
tine: Welcome to the league, @weston!
weston: Awesome, I like it!
weston: Thanks all!
marconi can’t wait to see the new superheroes with their new avatars :)
tine: @wojtek, @benking, @weston – you are all amazing, and well-deserving of your new superhero statuses. Wield your new powers with care, but put them to good use!
dave: Welcome!!! The league has gone to a whole new level with these new heroes!

ECMAScript Proposal: Named Function Parameters

I recently ran across the ES wiki which is documenting proposals and features for new versions of ECMAScript (JavaScript). I was excited to see the spread operator...” which basically brings Perl-style lists to JavaScript. I was also excited to see the spread-related rest parameters which basically implement Python’s positional parameter glob *args; however, I did not see something equivalent to Python’s named parameter glob **kwargs (see on Python Docs).

I’ve been giving thought to passing in named arguments to function calls in JavaScript, eliminating the need for the current pattern of wrapping named arguments in an object, like:

function foo(kwargs){
    if(kwargs.z === undefined)
        kwargs.z = 3; //default value
    return [kwargs.x, kwargs.y, kwargs.z];
}
foo({z:3, y:2, x:1}); //=> [1, 2, 3]

Instead of this, I’d love to be able discretely define what arguments I’m expecting in a positional list, but then also allow them to be passed in as named arguments:

function foo(x, y, z){
    return [x, y, z];
}
foo(1, 2, 3) === foo(z:3, x:1, y:2); //=> [1, 2, 3]

This could also work with the ES proposal for parameter default values:

function foo(x, y, z = 3){
    return [x, y, z];
}
foo(1, 2) === foo(y:2, x:1); //=> [1, 2, 3]

Although the current proposal has a requirement that only trailing formal parameters may have default values specified, this shouldn’t be necessary when named parameters are used:

function foo(x = 1, y, z){
    return [x, y, z];
}
foo(z:3, y:2); //=> [1, 2, 3]

Furthermore, although the current spread proposal only works with arrays, it could also work with objects for named parameters:

var kwargs = {y:2, x:1, z:3};
foo(...kwargs); //=> [1,2,3]

Finally, the rest parameters proposal uses spread to implement the rough equivalent of Python’s positional parameter glob (*args), but I’m not sure how it could also be applied to named parameters to support Python’s **kwargs at the same time—I’m not sure how named rest parameters would work. For example in Python:

def foo(x, *args, **kwargs):
    return [x, args[0], kwargs['z']]
foo(1, 2, z=3); //=> [1, 2, 3]

Python has the * to prefix positional parameter globs and ** to prefix named parameter globs, but so far ECMAScript only has one prefix the “...” spread operator.

These are just some rough ideas about how JavaScript could support named parameters. I’m sure there things I’ve missed and implications I haven’t thought of, but I wanted to get my thoughts out there. What do you think?