How to Create Custom Facet Types
Introduction
FacetWP includes support for creating your own facet types.
Register the Facet Type
add_filter( 'facetwp_facet_types', function( $facet_types ) { $facet_types['links'] = new FacetWP_Facet_Links(); return $facet_types; });
The Facet Class
Method | Purpose |
---|---|
__construct() | Set the facet type’s label and any custom hooks |
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'] . |
render( $params ) | Generate the output HTML for this facet type. |
filter_posts( $params ) | This method returns an array of post IDs that match the selected values for this facet. |
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. |
front_scripts() | Output any scripts or CSS for public-facing facet pages. This method contains Javascript logic for handling facet interaction. |
settings_html() | (optional) Output admin settings HTML. |
Full Example
Below is a Links facet type, which is a minimal version of our Checkboxes facet type.
<?php class FacetWP_Facet_Links { function __construct() { $this->label = __( 'Links', 'fwp' ); } /** * Load the available choices */ function load_values( $params ) { global $wpdb; $facet = $params['facet']; $from_clause = $wpdb->prefix . 'facetwp_index f'; $where_clause = $params['where_clause']; // Count setting $limit = ctype_digit( $facet['count'] ) ? $facet['count'] : 10; $from_clause = apply_filters( 'facetwp_facet_from', $from_clause, $facet ); $where_clause = apply_filters( 'facetwp_facet_where', $where_clause, $facet ); $sql = " SELECT f.facet_value, f.facet_display_value, f.term_id, f.parent_id, f.depth, COUNT(DISTINCT f.post_id) AS counter FROM $from_clause WHERE f.facet_name = '{$facet['name']}' $where_clause GROUP BY f.facet_value ORDER BY f.depth, counter DESC, f.facet_display_value ASC LIMIT $limit"; return $wpdb->get_results( $sql, ARRAY_A ); } /** * Generate the output HTML */ function render( $params ) { $output = ''; $facet = $params['facet']; $values = (array) $params['values']; $selected_values = (array) $params['selected_values']; $key = 0; foreach ( $values as $key => $result ) { $selected = in_array( $result['facet_value'], $selected_values ) ? ' checked' : ''; $selected .= ( 0 == $result['counter'] && '' == $selected ) ? ' disabled' : ''; $output .= '<div class="facetwp-link' . $selected . '" data-value="' . esc_attr( $result['facet_value'] ) . '">'; $output .= esc_html( $result['facet_display_value'] ) . ' <span class="facetwp-counter">(' . $result['counter'] . ')</span>'; $output .= '</div>'; } return $output; } /** * Return array of post IDs matching the selected values * using the wp_facetwp_index table */ function filter_posts( $params ) { global $wpdb; $output = []; $facet = $params['facet']; $selected_values = $params['selected_values']; $sql = $wpdb->prepare( "SELECT DISTINCT post_id FROM {$wpdb->prefix}facetwp_index WHERE facet_name = %s", $facet['name'] ); foreach ( $selected_values as $key => $value ) { $results = facetwp_sql( $sql . " AND facet_value IN ('$value')", $facet ); $output = ( $key > 0 ) ? array_intersect( $output, $results ) : $results; if ( empty( $output ) ) { break; } } return $output; } /** * Load and save facet settings */ function admin_scripts() { ?> <script> (function($) { FWP.hooks.addAction('facetwp/load/links', function($this, obj) { $this.find('.facet-source').val(obj.source); $this.find('.facet-count').val(obj.count); }); FWP.hooks.addFilter('facetwp/save/links', function(obj, $this) { obj['source'] = $this.find('.facet-source').val(); obj['count'] = $this.find('.facet-count').val(); return obj; }); })(jQuery); </script> <?php } /** * Parse the facet selections + other front-facing handlers */ function front_scripts() { ?> <script> (function($) { FWP.hooks.addAction('facetwp/refresh/links', function($this, facet_name) { var selected_values = []; $this.find('.facetwp-link.checked').each(function() { selected_values.push($(this).attr('data-value')); }); FWP.facets[facet_name] = selected_values; }); FWP.hooks.addFilter('facetwp/selections/links', function(output, params) { var choices = []; $.each(params.selected_values, function(idx, val) { var choice = params.el.find('.facetwp-link[data-value="' + val + '"]').clone(); choice.find('.facetwp-counter').remove(); choices.push({ value: val, label: choice.text() }); }); return choices; }); $(document).on('click', '.facetwp-type-links .facetwp-link:not(.disabled)', function() { $(this).toggleClass('checked'); FWP.autoload(); }); })(jQuery); </script> <?php } /** * Admin settings HTML */ function settings_html() { ?> <tr> <td> <?php _e('Count', 'fwp'); ?>: <div class="facetwp-tooltip"> <span class="icon-question">?</span> <div class="facetwp-tooltip-content"><?php _e( 'The maximum number of facet choices to show', 'fwp' ); ?></div> </div> </td> <td><input type="text" class="facet-count" value="10" /></td> </tr> <?php } }