→ How to Create Custom Facet Types

Introduction

FacetWP includes support for creating your own facet types. The following example is used to build a Select2 facet type, which is an enhanced version of the Dropdown facet type.

Register the Facet Type

Add your custom facet type to the $facet_types array.

function prefix_facet_types( $facet_types ) {
    $facet_types['select2'] = new FacetWP_Facet_Select2();
    return $facet_types;
}
add_filter( 'facetwp_facet_types', 'prefix_facet_types' );

The Facet Class

The facet code goes into its own class. Each facet has several methods (see below).

__construct()

Define your facet’s label within this method.

function __construct() {
    $this->label = __( 'Select2', 'fwp' );
}

load_values( $params )

(optional) Load facet values from the database. This method is used primarily for Checkbox and Dropdown facets. The returned data is passed into render() via $params['values'].

function load_values( $params ) {
    global $wpdb;

    $facet = $params['facet'];
    $where_clause = $params['where_clause'];

    // Orderby
    $orderby = 'counter DESC, f.facet_display_value ASC';
    if ( 'display_value' == $facet['orderby'] ) {
        $orderby = 'f.facet_display_value ASC';
    }
    elseif ( 'raw_value' == $facet['orderby'] ) {
        $orderby = 'f.facet_value ASC';
    }

    // Limit
    $limit = ctype_digit( $facet['count'] ) ? $facet['count'] : 10;

    $sql = "
    SELECT f.facet_value, f.facet_display_value, COUNT(*) AS counter
    FROM {$wpdb->prefix}facetwp_index f
    WHERE f.facet_name = '{$facet['name']}' $where_clause
    GROUP BY f.facet_value
    ORDER BY $orderby
    LIMIT $limit";

    return $wpdb->get_results( $sql );
}

render( $params )

Generate the output HTML for this facet type.

function render( $params ) {

    $output = '';
    $facet = $params['facet'];
    $values = (array) $params['values'];
    $selected_values = (array) $params['selected_values'];

    foreach ( $values as $result ) {
        $selected = in_array( $result->facet_value, $selected_values ) ? ' selected' : '';
        $display_value = "$result->facet_display_value ($result->counter)";
        $output .= '<option value="' . $result->facet_value . '"' . $selected . '>' . $display_value . '</option>';
    }

    $output .= '</select>';
    return $output;
}

filter_posts( $params )

This method returns an array of post IDs that match the facet’s criteria.

function filter_posts( $params ) {
    global $wpdb;

    $facet = $params['facet'];
    $selected_values = $params['selected_values'];
    $selected_values = is_array( $selected_values ) ? $selected_values[0] : $selected_values;

    $sql = "
    SELECT DISTINCT post_id FROM {$wpdb->prefix}facetwp_index
    WHERE facet_name = '{$facet['name']}' AND facet_value IN ('$selected_values')";
    return $wpdb->get_col( $sql );
}

admin_scripts()

Output any scripts or CSS for the admin settings page. This method contains Javascript logic for handling the loading/saving of facet settings.

function admin_scripts() {
?>
<script>
(function($) {
    wp.hooks.addAction('facetwp/load/select2', function($this, obj) {
        $this.find('.facet-source').val(obj.source);
        $this.find('.facet-orderby').val(obj.orderby);
        $this.find('.facet-count').val(obj.count);
    });

    wp.hooks.addFilter('facetwp/save/select2', function($this, obj) {
        obj['source'] = $this.find('.facet-source').val();
        obj['orderby'] = $this.find('.facet-orderby').val();
        obj['count'] = $this.find('.facet-count').val();
        return obj;
    });
})(jQuery);
</script>
<?php
}

front_scripts()

Output any scripts or CSS for public-facing facet pages. This method contains Javascript logic for handling facet interaction.

function front_scripts() {
?>
<script>
(function($) {
    wp.hooks.addAction('facetwp/refresh/select2', function($this, facet_name) {
        FWP.facets[facet_name] = $this.find('.facetwp-select2').val() || '';
    });

    wp.hooks.addAction('facetwp/ready', function() {
        $(document).on('change', '.facetwp-facet .facetwp-select2', function() {
            $(this).select2('destroy');
            FWP.refresh();
        });
    });

    $(document).on('facetwp-loaded', function() {
        $('.facetwp-select2').select2({
            width: 'element'
        });
    });
})(jQuery);
</script>
<?php
}

settings_html()

(optional) Output admin settings HTML.

function settings_html() {
?>
        <tr>
            <td><?php _e('Sort by', 'fwp'); ?>:</td>
            <td>
                <select class="facet-orderby">
                    <option value="count">Facet Count</option>
                    <option value="display_value">Display Value</option>
                    <option value="raw_value">Raw Value</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>
                <?php _e('Count', 'fwp'); ?>:
                <span class="icon-question" title="The number of items to show">?</span>
            </td>
            <td><input type="text" class="facet-count" value="10" /></td>
        </tr>
<?php
}