Filter Hook Returning Blank When Used Twice

This is a pretty lengthy question, so bare with me.

In a plugin I’ve written that allows users to easily create new meta boxes, I have a function that uses a switch() to return the appropriate HTML for the kind of meta field being added. The function looks like this:

Read More
// displays the requested field type
function ecpt_render_field($field, $meta) {

    global $wp_version, $post, $ecpt_options;

    switch($field['type']) :

        case 'text' :
            $field_html = '<input type="text" name="' . $field['id'] . '" id="' . $field['id'] . '" value="' . stripslashes($meta) . '" size="30" style="width:97%" /><br/>' . __(stripslashes($field['desc']));
            break;

            /*****************************************************************
            * lots of case statements here have been removed for this example
            ******************************************************************/

    case 'checkbox' :
        $field_html = '<input type="checkbox" name="' . $field['id'] . '" id="' . $field['id'] . '" ' . checked(!empty($meta), true, false) .'/><div class="ecpt_description">' . __(stripslashes($field['desc'])) . '</div>';
        break;      

    endswitch;  

    if(has_filter('ecpt_fields_html')) {
        // this adds any addon fields (from plugins) to the array
        $field_html = apply_filters('ecpt_fields_html', $field, $field_html, $meta);
    }   

    // return the final field
    return $field_html;
}

$field is an array that contains all of the information for the field (id, type, class, etc). $meta is the value stored in the post meta.

At the end of the function there is a check for the existence of the “ecpt_fields_html” filter. This is a filter I’ve setup to allow additional meta field types to be registered via other plugins.

An example function that registers additional field types (successfully), looks like this:

// generates the HTML for the additional fields
function ecpt_bonus_fields_html($field, $field_html, $meta) {

    switch($field['type']) :

        case 'taxonomy' :
            // returns the options html for select fields
            $field_options = ecpt_get_field_options($field, $meta);
            $field_html =  '<select name="' . $field['id'] . '" id="' . $field['id'] . '">' . $field_options . '</select><br/>' . $field['desc'];
            break;

        case 'separator' :
            $field_html = '<hr/>';
            break;          

        case 'colorpicker' :
            if (empty($meta)) $meta = '#';
            $field_html = "<input class='ecpt-color' type='text' name='" . $field['id'] . "' id='" . $field['id'] . "' value='" . $meta . "' size='8' />
                    <a href='#' class='ecpt-color-select' rel='" . $field['id'] . "'>" . __('Select a color') . "</a>
                    <a href='#' class='ecpt-color-select' style='display: none;'>" . __('Hide Picker') . "</a>
                    <div style='display:none; position: absolute; background: #f0f0f0; border: 1px solid #ccc; z-index: 100;' class='ecpt-color-picker' rel='" . $field['id'] . "'></div>";
            break;

        default :
            $field_html = $field_html;

    endswitch;

    return $field_html;
}
add_filter('ecpt_fields_html', 'ecpt_bonus_fields_html', 10, 3);

This function to register extra field types works exactly like the first one.

Now, let’s say that I have the the function above activated in an add-on plugin (everything works fine), and then I setup a second plugin that has a second function that registers more field types (this new second function is structured exactly like the filter function above). If I do this, both of the filter functions that register new field types fail completely. They don’t throw any errors, but the “return $field_html;” statement simply returns nothing at all.

The second filter function looks like this:

// generates the HTML for the additional fields
function ecpt_sample_fields_html($field, $field_html, $meta) {

    switch($field['type']) :

        case 'textblock' :
            $field_html = 'this should be shown in the metabox, but is not';
        break;          

    endswitch;

    return $field_html;
}
add_filter('ecpt_fields_html', 'ecpt_sample_fields_html', 10, 3);

Both filter functions work perfectly when the other is not active, but if both are active, then the $field_html = apply_filters(‘ecpt_fields_html’, $field, $field_html, $meta); in the very first function results in nothing, just blank.

Alright, now is where it gets a little stranger. I have an almost identical set of functions / filters setup that display the labels for the field types in the meta box. They work perfectly fine.

In the core plugin, the function that setups the label for each field looks like this:

// run the label through a filter. This allows us to modify/remove the label for any field type
function ecpt_field_label($field) {
    $label = '<label for="' . $field['id'] . '">' . __(stripslashes($field['name'])) . '</label>';
    // the ecpt_field_label_filter allows the field label output to be altered for any field type
    if(has_filter('ecpt_field_label_filter')) {
        $label = apply_filters('ecpt_field_label_filter', $label, $field);
    }
    return $label;
}

And the filter function that allows the label HTML to be changed for fields registered with other plugins looks like this:

// modify the labels for the bonus fields (if needed)
function ecpt_bonus_fields_labels($label, $field) {

    if($field['type'] == 'separator') {
        // removes the label for the separator field
        return;
    }
    if($field['type'] == 'header') {
        return '<h4>' . $label . '</h4>';
    }
    return $label;
}
add_filter('ecpt_field_label_filter', 'ecpt_bonus_fields_labels', 10, 2);

This works perfectly fine, even when I setup a second label filter function (remember, setting up the second function for the field types is what caused it to break). So my second filter function for the labels looks like this:

// modify the labels for the bonus fields (if needed)
function ecpt_sample_field_labels($label, $field) {

    if($field['type'] == 'textblock') {
        return '<strong>' . $label . '</strong>';
    }
    return $label;
}
add_filter('ecpt_field_label_filter', 'ecpt_sample_field_labels', 10, 2);

The only difference (aside from using switch() and i() statements) is that the filter types filter has 3 parameters and the field labels filter has 2. At least that is the only difference I can find.

Below are screenshots that illustrates the issue.

Only the first filter function is active, used to register the Color field

Both filter functions are active. The field labels work, but not the input fields

Related posts

Leave a Reply

1 comment