Behat functional tests

During WordCamp Rotterdam I worked on a small bug in WP-CLI. A bug I found roughly six months ago.
The bug itself was a one line fix.
I was asked to create functional tests using behat which I didn’t even heard off.

So after checking the handbook and with help of a few others. It resulted in this pull request.
And now we wait.

ACF load user_meta cross WordPress multisite

Users are global in a multisite. And default ACF groups are per site. So if you set a pinterest url for a user on one site it will apply it for all sites. No problem. But if you set an image it will try to find that image-id on each site.

The solution.

Step 1; Limit the user acf groups only to the main site:

function wpstarter_filter_fields_group($result, $rule, $screen) {
    if ( isset( $screen['user_id'] ) && ! is_main_site() )
        return false;

    return $result;
}
add_filter('acf/location/rule_match', 'wpstarter_filter_fields_group', 10, 3);

Step 2; Get image fields for users only from the main site:

function wpstarter_load_avatar_value_cros_site( $value, $post_id, $field ) {

    if( 0 !== strpos( $post_id, 'user_' ) || is_main_site() ) {
        return $value;
    }

    switch_to_blog( get_main_site_id() );

    $value_of_main_site = acf_get_value($post_id, $field);
    $value              = acf_format_value($value_of_main_site, $post_id, $field);

    restore_current_blog();
    return $value;
}
add_filter( 'acf/format_value/type=image', 'wpstarter_load_avatar_value_cros_site', 11, 3);

The order of arguments in an if statement

Consider this dummy snippet:

if ( true === $skip || heavy_check() ){
    continue;
}

The $skip is checked first. It is very quick as it is just a simple variable check. and since this is an ‘or’ statement. As soon as $skip is true it won’t bother with the heavy_check.

Something I always suspected but today I tested this and confirmed it.

Add custom post_meta to the WordPress rest API

So I needed some metadata to be in the rest API of a custom post_type.
The following adds the subtitle to the book post_type

add_action('rest_api_init', function () {
    register_rest_field('book', 'subtitle', [
        'get_callback'    => 'get_meta_data_for_rest',
        'update_callback' => null,
        'schema'          => null,
    ]);

});

function get_meta_data_for_rest($post, $field_name, $request)
{
    // it's not always an object
    if (isset($post->id) && ! empty($post->id)) {
        $post_id = $post->id;
    } elseif (isset($post['id']) && ! empty($post['id'])) {
        $post_id = $post['id'];
    } else {
        return null;
    }

    return get_post_meta($post_id, $field_name, true);
}

Delete all empty taxonomie terms in WordPress

The code below will find and delete all empty terms of every taxonomie, including the menu.
Think before you delete, you might want to keep some empty categories.

foreach ( get_taxonomies() as $tax_slug ) {//
    $terms = get_terms( $tax_slug, array( 'hide_empty' => false ) );

    /** @var WP_Term $wp_term */
    foreach ( $terms as $wp_term ) {
        if ( 0 == $wp_term->count ) {
            wp_delete_term( $wp_term->term_id, $wp_term->taxonomy );
        }
    }
}

Regex lookahead

Regex is one of the things that I’ve always regret I didn’t learn earlier. Yes it’s complicated, but without a doubt it is worth it. There is one syntax I didn’t know yet. The lookahead

[^a]*

Match everything until you find the letter a. The a itself is not included. Should be handy to parse url’s and such