| @@ -7,13 +7,13 @@ | ||
| 7 | 7 | */ |
| 8 | 8 | |
| 9 | 9 | namespace ElasticPress\Feature\Facets; |
| 10 | 10 | |
| 11 | -use ElasticPress\Feature as Feature; | |
| 12 | -use ElasticPress\Features as Features; | |
| 13 | -use ElasticPress\Utils as Utils; | |
| 14 | -use ElasticPress\FeatureRequirementsStatus as FeatureRequirementsStatus; | |
| 15 | -use ElasticPress\Indexables as Indexables; | |
| 11 | +use ElasticPress\Feature; | |
| 12 | +use ElasticPress\Features; | |
| 13 | +use ElasticPress\Indexables; | |
| 14 | +use ElasticPress\REST; | |
| 15 | +use ElasticPress\Utils; | |
| 16 | 16 | |
| 17 | 17 | if ( ! defined( 'ABSPATH' ) ) { |
| 18 | 18 | exit; // Exit if accessed directly. |
| 19 | 19 | } |
| @@ -21,16 +21,15 @@ | ||
| 21 | 21 | /** |
| 22 | 22 | * Facets feature class |
| 23 | 23 | */ |
| 24 | 24 | class Facets extends Feature { |
| 25 | - | |
| 26 | 25 | /** |
| 27 | - * Block instance. | |
| 26 | + * Facet types (taxonomy, meta fields, etc.) | |
| 28 | 27 | * |
| 29 | - * @since 4.2.0 | |
| 30 | - * @var Block | |
| 28 | + * @since 4.3.0 | |
| 29 | + * @var array | |
| 31 | 30 | */ |
| 32 | - public $block; | |
| 31 | + public $types = []; | |
| 33 | 32 | |
| 34 | 33 | /** |
| 35 | 34 | * Initialize feature setting it's config |
| 36 | 35 | * |
| @@ -38,14 +37,10 @@ | ||
| 38 | 37 | */ |
| 39 | 38 | public function __construct() { |
| 40 | 39 | $this->slug = 'facets'; |
| 41 | 40 | |
| 42 | - $this->title = esc_html__( 'Facets', 'elasticpress' ); | |
| 41 | + $this->group = 'core-search'; | |
| 43 | 42 | |
| 44 | - $this->summary = __( 'Add controls to your website to filter content by one or more taxonomies.', 'elasticpress' ); | |
| 45 | - | |
| 46 | - $this->docs_url = __( 'https://elasticpress.zendesk.com/hc/en-us/articles/360050447492-Configuring-ElasticPress-via-the-Plugin-Dashboard#facets', 'elasticpress' ); | |
| 47 | - | |
| 48 | 43 | $this->requires_install_reindex = false; |
| 49 | 44 | |
| 50 | 45 | $this->default_settings = [ |
| 51 | 46 | 'match_type' => 'all', |
| @@ -50,64 +45,119 @@ | ||
| 50 | 45 | $this->default_settings = [ |
| 51 | 46 | 'match_type' => 'all', |
| 52 | 47 | ]; |
| 53 | 48 | |
| 49 | + $types = [ | |
| 50 | + 'taxonomy' => __NAMESPACE__ . '\Types\Taxonomy\FacetType', | |
| 51 | + ]; | |
| 52 | + | |
| 53 | + if ( version_compare( get_bloginfo( 'version' ), '5.8', '>=' ) ) { | |
| 54 | + $types['meta'] = __NAMESPACE__ . '\Types\Meta\FacetType'; | |
| 55 | + $types['meta-range'] = __NAMESPACE__ . '\Types\MetaRange\FacetType'; | |
| 56 | + $types['post-type'] = __NAMESPACE__ . '\Types\PostType\FacetType'; | |
| 57 | + $types['date'] = __NAMESPACE__ . '\Types\Date\FacetType'; | |
| 58 | + | |
| 59 | + } | |
| 60 | + | |
| 61 | + /** | |
| 62 | + * Filter the Facet types available. | |
| 63 | + * | |
| 64 | + * ``` | |
| 65 | + * add_filter( | |
| 66 | + * 'ep_facet_types', | |
| 67 | + * function ( $types ) { | |
| 68 | + * $types['post_type'] = '\MyPlugin\PostType'; | |
| 69 | + * return $types; | |
| 70 | + * } | |
| 71 | + * ); | |
| 72 | + * ``` | |
| 73 | + * | |
| 74 | + * @since 4.3.0 | |
| 75 | + * @hook ep_facet_types | |
| 76 | + * @param {array} $types Array of types available. Keys are slugs, values are class names. | |
| 77 | + * @return {array} New array of types available | |
| 78 | + */ | |
| 79 | + $types = apply_filters( 'ep_facet_types', $types ); | |
| 80 | + | |
| 81 | + foreach ( $types as $type => $class ) { | |
| 82 | + if ( is_a( $class, __NAMESPACE__ . '\FacetType', true ) ) { | |
| 83 | + $this->types[ $type ] = new $class(); | |
| 84 | + } | |
| 85 | + } | |
| 86 | + | |
| 54 | 87 | parent::__construct(); |
| 55 | 88 | } |
| 56 | 89 | |
| 57 | 90 | /** |
| 91 | + * Sets i18n strings. | |
| 92 | + * | |
| 93 | + * @return void | |
| 94 | + * @since 5.2.0 | |
| 95 | + */ | |
| 96 | + public function set_i18n_strings(): void { | |
| 97 | + $this->title = esc_html__( 'Filters', 'elasticpress' ); | |
| 98 | + | |
| 99 | + $this->summary = '<p>' . | |
| 100 | + ( wp_is_block_theme() | |
| 101 | + ? sprintf( | |
| 102 | + /* translators: Site Editor URL */ | |
| 103 | + __( 'Adds <a href="%s">filter blocks</a> that administrators can add to the website’s templates and template parts, so that visitors can filter applicable content and search results by one or more taxonomy terms, metafields, and date ranges.', 'elasticpress' ), | |
| 104 | + esc_url( admin_url( 'site-editor.php' ) ) | |
| 105 | + ) | |
| 106 | + : sprintf( | |
| 107 | + /* translators: Widgets Edit Screen URL */ | |
| 108 | + __( 'Adds <a href="%s">filter widgets</a> that administrators can add to the website’s sidebars (widgetized areas), so that visitors can filter applicable content and search results by one or more taxonomy terms, metafields, and date ranges.', 'elasticpress' ), | |
| 109 | + esc_url( admin_url( 'widgets.php' ) ) | |
| 110 | + ) | |
| 111 | + ) . '</p>'; | |
| 112 | + | |
| 113 | + $this->docs_url = __( 'https://www.elasticpress.io/resources/articles/configuring-elasticpress-via-the-plugin-dashboard/#filters', 'elasticpress' ); | |
| 114 | + } | |
| 115 | + | |
| 116 | + /** | |
| 58 | 117 | * Setup hooks and filters for feature |
| 59 | 118 | * |
| 60 | 119 | * @since 2.5 |
| 61 | 120 | */ |
| 62 | 121 | public function setup() { |
| 63 | - global $pagenow; | |
| 64 | - | |
| 65 | - // This feature should not run while in the editor. | |
| 66 | - if ( in_array( $pagenow, [ 'post-new.php', 'post.php' ], true ) ) { | |
| 67 | - return; | |
| 122 | + foreach ( $this->types as $type => $class ) { | |
| 123 | + $this->types[ $type ]->setup(); | |
| 68 | 124 | } |
| 69 | 125 | |
| 70 | - add_action( 'widgets_init', [ $this, 'register_widgets' ] ); | |
| 126 | + add_filter( 'widget_types_to_hide_from_legacy_widget_block', [ $this, 'hide_legacy_widget' ] ); | |
| 71 | 127 | add_action( 'ep_valid_response', [ $this, 'get_aggs' ], 10, 4 ); |
| 128 | + add_action( 'wp_enqueue_scripts', [ $this, 'front_scripts' ] ); | |
| 129 | + add_action( 'enqueue_block_editor_assets', [ $this, 'front_scripts' ] ); | |
| 130 | + add_action( 'ep_feature_box_settings_facets', [ $this, 'settings' ], 10, 1 ); | |
| 72 | 131 | add_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ], 10, 3 ); |
| 73 | 132 | add_action( 'pre_get_posts', [ $this, 'facet_query' ] ); |
| 74 | - add_action( 'admin_enqueue_scripts', [ $this, 'admin_scripts' ] ); | |
| 75 | - add_action( 'wp_enqueue_scripts', [ $this, 'front_scripts' ] ); | |
| 76 | - add_action( 'ep_feature_box_settings_facets', [ $this, 'settings' ], 10, 1 ); | |
| 77 | - | |
| 78 | - $this->block = new Block(); | |
| 79 | - $this->block->setup(); | |
| 133 | + add_filter( 'ep_post_filters', [ $this, 'apply_facets_filters' ], 10, 3 ); | |
| 134 | + add_action( 'rest_api_init', [ $this, 'setup_endpoints' ] ); | |
| 80 | 135 | } |
| 81 | 136 | |
| 82 | 137 | /** |
| 83 | - * Dashboard facet settings | |
| 138 | + * Unsetup Facets related hooks | |
| 84 | 139 | * |
| 85 | - * @since 2.5 | |
| 140 | + * @since 5.1.0 | |
| 86 | 141 | */ |
| 87 | - public function output_feature_box_settings() { | |
| 88 | - $settings = $this->get_settings(); | |
| 89 | - | |
| 90 | - if ( ! $settings ) { | |
| 91 | - $settings = []; | |
| 92 | - } | |
| 93 | - | |
| 94 | - $settings = wp_parse_args( $settings, $this->default_settings ); | |
| 95 | - ?> | |
| 96 | - <div class="field"> | |
| 97 | - <div class="field-name status"><?php esc_html_e( 'Match Type', 'elasticpress' ); ?></div> | |
| 98 | - <div class="input-wrap"> | |
| 99 | - <label><input name="settings[match_type]" type="radio" <?php checked( $settings['match_type'], 'all' ); ?> value="all"><?php echo wp_kses_post( __( 'Show any content tagged to <strong>all</strong> selected terms', 'elasticpress' ) ); ?></label><br> | |
| 100 | - <label><input name="settings[match_type]" type="radio" <?php checked( $settings['match_type'], 'any' ); ?> value="any"><?php echo wp_kses_post( __( 'Show all content tagged to <strong>any</strong> selected term', 'elasticpress' ) ); ?></label> | |
| 101 | - <p class="field-description"><?php esc_html_e( '"All" will only show content that matches all facets. "Any" will show content that matches any facet.', 'elasticpress' ); ?></p> | |
| 102 | - </div> | |
| 103 | - </div> | |
| 104 | - <?php | |
| 142 | + public function tear_down() { | |
| 143 | + remove_filter( 'widget_types_to_hide_from_legacy_widget_block', [ $this, 'hide_legacy_widget' ] ); | |
| 144 | + remove_action( 'ep_valid_response', [ $this, 'get_aggs' ] ); | |
| 145 | + remove_action( 'wp_enqueue_scripts', [ $this, 'front_scripts' ] ); | |
| 146 | + remove_action( 'enqueue_block_editor_assets', [ $this, 'front_scripts' ] ); | |
| 147 | + remove_action( 'ep_feature_box_settings_facets', [ $this, 'settings' ] ); | |
| 148 | + remove_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ] ); | |
| 149 | + remove_action( 'pre_get_posts', [ $this, 'facet_query' ] ); | |
| 150 | + remove_filter( 'ep_post_filters', [ $this, 'apply_facets_filters' ] ); | |
| 151 | + remove_action( 'rest_api_init', [ $this, 'setup_endpoints' ] ); | |
| 105 | 152 | } |
| 106 | 153 | |
| 107 | 154 | /** |
| 108 | - * If we are doing or matches, we need to remove filters from aggs | |
| 155 | + * If we are doing `or` matches, we need to remove filters from aggs. | |
| 109 | 156 | * |
| 157 | + * By default, the same filters applied to the main query are applied to aggregations. | |
| 158 | + * If doing `or` matches, those should be removed so we get a broader set of results. | |
| 159 | + * | |
| 110 | 160 | * @param array $args ES arguments |
| 111 | 161 | * @param array $query_args Query arguments |
| 112 | 162 | * @param WP_Query $query WP Query instance |
| 113 | 163 | * @since 2.5 |
| @@ -113,49 +163,45 @@ | ||
| 113 | 163 | * @since 2.5 |
| 114 | 164 | * @return array |
| 115 | 165 | */ |
| 116 | 166 | public function set_agg_filters( $args, $query_args, $query ) { |
| 167 | + // Not a facetable query | |
| 117 | 168 | if ( empty( $query_args['ep_facet'] ) ) { |
| 118 | 169 | return $args; |
| 119 | 170 | } |
| 120 | 171 | |
| 121 | - // @todo For some reason these are appearing in the query args, need to investigate | |
| 122 | - unset( $query_args['category_name'] ); | |
| 123 | - unset( $query_args['cat'] ); | |
| 124 | - unset( $query_args['tag'] ); | |
| 125 | - unset( $query_args['tag_id'] ); | |
| 126 | - unset( $query_args['taxonomy'] ); | |
| 127 | - unset( $query_args['term'] ); | |
| 172 | + if ( 'any' === $this->get_match_type() ) { | |
| 173 | + add_filter( 'ep_post_filters', [ $this, 'remove_facets_filter' ], 11 ); | |
| 174 | + } | |
| 128 | 175 | |
| 129 | - $facet_query_args = $query_args; | |
| 176 | + /** | |
| 177 | + * This flag is used to differentiate filters being applied to the query and to its aggregations. | |
| 178 | + */ | |
| 179 | + $query_args['ep_facet_adding_agg_filters'] = true; | |
| 130 | 180 | |
| 131 | - $settings = $this->get_settings(); | |
| 181 | + /** | |
| 182 | + * Filter WP query arguments that will be used to build the aggregations filter. | |
| 183 | + * | |
| 184 | + * The returned `$query_args` will be used to build the aggregations filter passing | |
| 185 | + * it through `Indexable\Post\Post::format_args()`. | |
| 186 | + * | |
| 187 | + * @hook ep_facet_agg_filters | |
| 188 | + * @since 4.3.0 | |
| 189 | + * @param {array} $query_args Query arguments | |
| 190 | + * @param {array} $args ES arguments | |
| 191 | + * @param {array} $query WP Query instance | |
| 192 | + * @return {array} New facets aggregations | |
| 193 | + */ | |
| 194 | + $query_args = apply_filters( 'ep_facet_agg_filters', $query_args, $args, $query ); | |
| 132 | 195 | |
| 133 | - $settings = wp_parse_args( | |
| 134 | - $settings, | |
| 135 | - array( | |
| 136 | - 'match_type' => 'all', | |
| 137 | - ) | |
| 138 | - ); | |
| 196 | + remove_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ], 10, 3 ); | |
| 197 | + $facet_formatted_args = Indexables::factory()->get( 'post' )->format_args( $query_args, $query ); | |
| 198 | + add_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ], 10, 3 ); | |
| 139 | 199 | |
| 140 | - if ( ! empty( $facet_query_args['tax_query'] ) ) { | |
| 141 | - remove_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ], 10, 3 ); | |
| 200 | + remove_filter( 'ep_post_filters', [ $this, 'remove_facets_filter' ], 11 ); | |
| 142 | 201 | |
| 143 | - foreach ( $facet_query_args['tax_query'] as $key => $taxonomy ) { | |
| 144 | - if ( is_array( $taxonomy ) ) { | |
| 145 | - if ( 'any' === $settings['match_type'] ) { | |
| 146 | - unset( $facet_query_args['tax_query'][ $key ] ); | |
| 147 | - } | |
| 148 | - } | |
| 149 | - } | |
| 202 | + $args['aggs']['terms']['filter'] = $facet_formatted_args['post_filter']; | |
| 150 | 203 | |
| 151 | - $facet_formatted_args = Indexables::factory()->get( 'post' )->format_args( $facet_query_args, $query ); | |
| 152 | - | |
| 153 | - $args['aggs']['terms']['filter'] = $facet_formatted_args['post_filter']; | |
| 154 | - | |
| 155 | - add_filter( 'ep_post_formatted_args', [ $this, 'set_agg_filters' ], 10, 3 ); | |
| 156 | - } | |
| 157 | - | |
| 158 | 204 | return $args; |
| 159 | 205 | } |
| 160 | 206 | |
| 161 | 207 | /** |
| @@ -164,17 +210,12 @@ | ||
| 164 | 210 | * @param string $hook WP hook |
| 165 | 211 | * @since 2.5 |
| 166 | 212 | */ |
| 167 | 213 | public function admin_scripts( $hook ) { |
| 168 | - if ( 'widgets.php' !== $hook ) { | |
| 169 | - return; | |
| 170 | - } | |
| 171 | - | |
| 172 | - wp_enqueue_style( | |
| 173 | - 'elasticpress-facets-admin', | |
| 174 | - EP_URL . 'dist/css/facets-admin-styles.min.css', | |
| 175 | - Utils\get_asset_info( 'facets-admin-styles', 'dependencies' ), | |
| 176 | - Utils\get_asset_info( 'facets-admin-styles', 'version' ) | |
| 214 | + _doing_it_wrong( | |
| 215 | + __METHOD__, | |
| 216 | + esc_html__( 'Facets no longer require admin styles.', 'elasticpress' ), | |
| 217 | + '4.7.0' | |
| 177 | 218 | ); |
| 178 | 219 | } |
| 179 | 220 | |
| 180 | 221 | /** |
| @@ -184,17 +225,19 @@ | ||
| 184 | 225 | */ |
| 185 | 226 | public function front_scripts() { |
| 186 | 227 | wp_register_script( |
| 187 | 228 | 'elasticpress-facets', |
| 188 | - EP_URL . 'dist/js/facets-script.min.js', | |
| 229 | + EP_URL . 'dist/js/facets-script.js', | |
| 189 | 230 | Utils\get_asset_info( 'facets-script', 'dependencies' ), |
| 190 | 231 | Utils\get_asset_info( 'facets-script', 'version' ), |
| 191 | 232 | true |
| 192 | 233 | ); |
| 193 | 234 | |
| 235 | + wp_set_script_translations( 'elasticpress-facets', 'elasticpress' ); | |
| 236 | + | |
| 194 | 237 | wp_register_style( |
| 195 | 238 | 'elasticpress-facets', |
| 196 | - EP_URL . 'dist/css/facets-styles.min.css', | |
| 239 | + EP_URL . 'dist/css/facets-styles.css', | |
| 197 | 240 | Utils\get_asset_info( 'facets-styles', 'dependencies' ), |
| 198 | 241 | Utils\get_asset_info( 'facets-styles', 'version' ) |
| 199 | 242 | ); |
| 200 | 243 | } |
| @@ -208,20 +251,32 @@ | ||
| 208 | 251 | */ |
| 209 | 252 | public function is_facetable( $query ) { |
| 210 | 253 | |
| 211 | 254 | /** |
| 212 | - * Bypass the standard checks and set a query to be facetable | |
| 255 | + * Bypass the standard checks and set a query to be facetable. | |
| 213 | 256 | * |
| 257 | + * @deprecated 5.3.0 Use the 'ep_is_facetable' argument in WP_Query instead. | |
| 258 | + * | |
| 214 | 259 | * @hook ep_is_facetable |
| 215 | 260 | * @param {bool} $bypass Defaults to false. |
| 216 | 261 | * @param {WP_Query} $query The current WP_Query. |
| 217 | 262 | * @return {bool} true to bypass, false to ignore |
| 218 | 263 | */ |
| 219 | - if ( \apply_filters( 'ep_is_facetable', false, $query ) ) { | |
| 264 | + if ( apply_filters_deprecated( | |
| 265 | + 'ep_is_facetable', | |
| 266 | + [ false, $query ], | |
| 267 | + 'ElasticPress 5.3.0', | |
| 268 | + 'WP_Query->ep_is_facetable argument' | |
| 269 | + ) ) { | |
| 220 | 270 | return true; |
| 221 | 271 | } |
| 222 | 272 | |
| 223 | - if ( is_admin() ) { | |
| 273 | + $ep_is_facetable = $query->get( 'ep_is_facetable', null ); | |
| 274 | + if ( null !== $ep_is_facetable ) { | |
| 275 | + return (bool) $ep_is_facetable; | |
| 276 | + } | |
| 277 | + | |
| 278 | + if ( is_admin() || is_feed() ) { | |
| 224 | 279 | return false; |
| 225 | 280 | } |
| 226 | 281 | |
| 227 | 282 | if ( defined( 'WP_CLI' ) && WP_CLI ) { |
| @@ -263,20 +318,28 @@ | ||
| 263 | 318 | if ( ! $this->is_facetable( $query ) ) { |
| 264 | 319 | return; |
| 265 | 320 | } |
| 266 | 321 | |
| 267 | - $taxonomies = get_taxonomies( array( 'public' => true ), 'object' ); | |
| 322 | + // If any filter was selected, there is no reason to prepend the list with sticky posts. | |
| 323 | + $selected_filters = $this->get_selected(); | |
| 324 | + if ( ! empty( array_filter( $selected_filters ) ) ) { | |
| 325 | + $query->set( 'ignore_sticky_posts', true ); | |
| 326 | + } | |
| 268 | 327 | |
| 269 | 328 | /** |
| 270 | - * Filter taxonomies made available for faceting | |
| 329 | + * Filter facet aggregations. | |
| 271 | 330 | * |
| 272 | - * @hook ep_facet_include_taxonomies | |
| 273 | - * @param {array} $taxonomies Taxonomies | |
| 274 | - * @return {array} New taxonomies | |
| 331 | + * This is used by facet types to add their own aggregations to the | |
| 332 | + * general facet. | |
| 333 | + * | |
| 334 | + * @hook ep_facet_wp_query_aggs_facet | |
| 335 | + * @since 4.3.0 | |
| 336 | + * @param {array} $facets Facets aggregations | |
| 337 | + * @return {array} New facets aggregations | |
| 275 | 338 | */ |
| 276 | - $taxonomies = apply_filters( 'ep_facet_include_taxonomies', $taxonomies ); | |
| 339 | + $facets = apply_filters( 'ep_facet_wp_query_aggs_facet', [] ); | |
| 277 | 340 | |
| 278 | - if ( empty( $taxonomies ) ) { | |
| 341 | + if ( empty( $facets ) ) { | |
| 279 | 342 | return; |
| 280 | 343 | } |
| 281 | 344 | |
| 282 | 345 | $query->set( 'ep_integrate', true ); |
| @@ -281,37 +344,8 @@ | ||
| 281 | 344 | |
| 282 | 345 | $query->set( 'ep_integrate', true ); |
| 283 | 346 | $query->set( 'ep_facet', true ); |
| 284 | 347 | |
| 285 | - $facets = []; | |
| 286 | - | |
| 287 | - /** | |
| 288 | - * Retrieve aggregations based on a custom field. This field must exist on the mapping. | |
| 289 | - * Values available out-of-the-box are: | |
| 290 | - * - slug (default) | |
| 291 | - * - term_id | |
| 292 | - * - name | |
| 293 | - * - parent | |
| 294 | - * - term_taxonomy_id | |
| 295 | - * - term_order | |
| 296 | - * - facet (retrieves a JSON representation of the term object) | |
| 297 | - * | |
| 298 | - * @since 3.6.0 | |
| 299 | - * @hook ep_facet_use_field | |
| 300 | - * @param {string} $field The term field to use | |
| 301 | - * @return {string} The chosen term field | |
| 302 | - */ | |
| 303 | - $facet_field = apply_filters( 'ep_facet_use_field', 'slug' ); | |
| 304 | - | |
| 305 | - foreach ( $taxonomies as $slug => $taxonomy ) { | |
| 306 | - $facets[ $slug ] = array( | |
| 307 | - 'terms' => array( | |
| 308 | - 'size' => apply_filters( 'ep_facet_taxonomies_size', 10000, $taxonomy ), | |
| 309 | - 'field' => 'terms.' . $slug . '.' . $facet_field, | |
| 310 | - ), | |
| 311 | - ); | |
| 312 | - } | |
| 313 | - | |
| 314 | 348 | $aggs = array( |
| 315 | 349 | 'name' => 'terms', |
| 316 | 350 | 'use-filter' => true, |
| 317 | 351 | 'aggs' => $facets, |
| @@ -317,50 +351,12 @@ | ||
| 317 | 351 | 'aggs' => $facets, |
| 318 | 352 | ); |
| 319 | 353 | |
| 320 | 354 | $query->set( 'aggs', $aggs ); |
| 321 | - | |
| 322 | - $selected_filters = $this->get_selected(); | |
| 323 | - | |
| 324 | - $settings = $this->get_settings(); | |
| 325 | - | |
| 326 | - $settings = wp_parse_args( | |
| 327 | - $settings, | |
| 328 | - array( | |
| 329 | - 'match_type' => 'all', | |
| 330 | - ) | |
| 331 | - ); | |
| 332 | - | |
| 333 | - $tax_query = $query->get( 'tax_query', [] ); | |
| 334 | - | |
| 335 | - // Account for taxonomies that should be woocommerce attributes, if WC is enabled | |
| 336 | - $attribute_taxonomies = []; | |
| 337 | - if ( function_exists( 'wc_attribute_taxonomy_name' ) ) { | |
| 338 | - $all_attr_taxonomies = wc_get_attribute_taxonomies(); | |
| 339 | - | |
| 340 | - foreach ( $all_attr_taxonomies as $attr_taxonomy ) { | |
| 341 | - $attribute_taxonomies[ $attr_taxonomy->attribute_name ] = wc_attribute_taxonomy_name( $attr_taxonomy->attribute_name ); | |
| 342 | - } | |
| 343 | - } | |
| 344 | - | |
| 345 | - foreach ( $selected_filters['taxonomies'] as $taxonomy => $filter ) { | |
| 346 | - $tax_query[] = [ | |
| 347 | - 'taxonomy' => isset( $attribute_taxonomies[ $taxonomy ] ) ? $attribute_taxonomies[ $taxonomy ] : $taxonomy, | |
| 348 | - 'field' => 'slug', | |
| 349 | - 'terms' => array_keys( $filter['terms'] ), | |
| 350 | - 'operator' => ( 'any' === $settings['match_type'] ) ? 'or' : 'and', | |
| 351 | - ]; | |
| 352 | - } | |
| 353 | - | |
| 354 | - if ( ! empty( $selected_filters['taxonomies'] ) && 'any' === $settings['match_type'] ) { | |
| 355 | - $tax_query['relation'] = 'or'; | |
| 356 | - } | |
| 357 | - | |
| 358 | - $query->set( 'tax_query', $tax_query ); | |
| 359 | 355 | } |
| 360 | 356 | |
| 361 | 357 | /** |
| 362 | - * Hacky. Save aggregation data for later in a global | |
| 358 | + * Get aggregations from Elasticsearch response and store on query object | |
| 363 | 359 | * |
| 364 | 360 | * @param array $response ES response |
| 365 | 361 | * @param array $query Prepared Elasticsearch query |
| 366 | 362 | * @param array $query_args Current WP Query arguments |
| @@ -367,16 +363,14 @@ | ||
| 367 | 363 | * @param mixed $query_object Could be WP_Query, WP_User_Query, etc. |
| 368 | 364 | * @since 2.5 |
| 369 | 365 | */ |
| 370 | 366 | public function get_aggs( $response, $query, $query_args, $query_object ) { |
| 371 | - if ( empty( $query_object ) || 'WP_Query' !== get_class( $query_object ) || ! $this->is_facetable( $query_object ) ) { | |
| 367 | + if ( empty( $query_object ) || ! $query_object instanceof \WP_Query || ! $this->is_facetable( $query_object ) ) { | |
| 372 | 368 | return; |
| 373 | 369 | } |
| 374 | 370 | |
| 375 | - $GLOBALS['ep_facet_aggs'] = false; | |
| 376 | - | |
| 377 | 371 | if ( ! empty( $response['aggregations'] ) ) { |
| 378 | - $GLOBALS['ep_facet_aggs'] = []; | |
| 372 | + $processed_aggs = []; | |
| 379 | 373 | |
| 380 | 374 | if ( isset( $response['aggregations']['terms'] ) && is_array( $response['aggregations']['terms'] ) ) { |
| 381 | 375 | foreach ( $response['aggregations']['terms'] as $key => $agg ) { |
| 382 | 376 | if ( 'doc_count' === $key ) { |
| @@ -382,23 +376,105 @@ | ||
| 382 | 376 | if ( 'doc_count' === $key ) { |
| 383 | 377 | continue; |
| 384 | 378 | } |
| 385 | 379 | |
| 386 | - if ( ! is_array( $agg ) || empty( $agg['buckets'] ) ) { | |
| 380 | + if ( ! is_array( $agg ) || ( empty( $agg['buckets'] ) && empty( $agg['value'] ) ) ) { | |
| 387 | 381 | continue; |
| 388 | 382 | } |
| 389 | 383 | |
| 390 | - $GLOBALS['ep_facet_aggs'][ $key ] = []; | |
| 384 | + $processed_aggs[ $key ] = []; | |
| 391 | 385 | |
| 386 | + if ( ! empty( $agg['value'] ) ) { | |
| 387 | + $processed_aggs[ $key ] = $agg['value']; | |
| 388 | + continue; | |
| 389 | + } | |
| 390 | + | |
| 392 | 391 | foreach ( $agg['buckets'] as $bucket ) { |
| 393 | - $GLOBALS['ep_facet_aggs'][ $key ][ $bucket['key'] ] = $bucket['doc_count']; | |
| 392 | + $processed_aggs[ $key ][ $bucket['key'] ] = $bucket['doc_count']; | |
| 394 | 393 | } |
| 395 | 394 | } |
| 396 | 395 | } |
| 396 | + | |
| 397 | + $this->set_query_aggregations( $query_object, $processed_aggs ); | |
| 397 | 398 | } |
| 398 | 399 | } |
| 399 | 400 | |
| 400 | 401 | /** |
| 402 | + * Set aggregation data for a query. | |
| 403 | + * | |
| 404 | + * @since 5.3.0 | |
| 405 | + * @param \WP_Query $query The WP_Query object to store data for | |
| 406 | + * @param array $aggregations The aggregation data to store | |
| 407 | + */ | |
| 408 | + public function set_query_aggregations( $query, $aggregations ): void { | |
| 409 | + // Store aggregations on the query object | |
| 410 | + $query->ep_aggregations = $aggregations; | |
| 411 | + | |
| 412 | + if ( $query->is_main_query() && $this->should_sync_to_global( $query ) ) { | |
| 413 | + _doing_it_wrong( | |
| 414 | + __METHOD__, | |
| 415 | + esc_html__( 'The global variable $GLOBALS[\'ep_facet_aggs\'] is deprecated. Access aggregation data directly from the query object using $query->ep_aggregations or the Facets feature methods get_query_aggregations() and get_facet_aggregation().', 'elasticpress' ), | |
| 416 | + 'ElasticPress 5.3.0' | |
| 417 | + ); | |
| 418 | + | |
| 419 | + $GLOBALS['ep_facet_aggs'] = $aggregations; | |
| 420 | + } | |
| 421 | + } | |
| 422 | + | |
| 423 | + /** | |
| 424 | + * Get aggregation data for a specific query | |
| 425 | + * | |
| 426 | + * @since 5.3.0 | |
| 427 | + * @param \WP_Query $query The WP_Query object | |
| 428 | + * @return array|false Aggregation data or false if not found | |
| 429 | + */ | |
| 430 | + public function get_query_aggregations( $query ) { | |
| 431 | + if ( $query instanceof \WP_Query && isset( $query->ep_aggregations ) && false !== $query->ep_aggregations ) { | |
| 432 | + return $query->ep_aggregations; | |
| 433 | + } | |
| 434 | + // Fallback to global variable | |
| 435 | + return $GLOBALS['ep_facet_aggs'] ?? false; | |
| 436 | + } | |
| 437 | + | |
| 438 | + /** | |
| 439 | + * Get aggregation data for a specific facet within a query | |
| 440 | + * | |
| 441 | + * @since 5.3.0 | |
| 442 | + * @param \WP_Query $query The WP_Query object | |
| 443 | + * @param string $facet_name The name of the facet to retrieve | |
| 444 | + * @return array|false Facet aggregation data or false if not found | |
| 445 | + */ | |
| 446 | + public function get_facet_aggregation( $query, $facet_name ) { | |
| 447 | + $aggregations = $this->get_query_aggregations( $query ); | |
| 448 | + | |
| 449 | + if ( false === $aggregations || ! isset( $aggregations[ $facet_name ] ) ) { | |
| 450 | + return false; | |
| 451 | + } | |
| 452 | + | |
| 453 | + return $aggregations[ $facet_name ]; | |
| 454 | + } | |
| 455 | + | |
| 456 | + /** | |
| 457 | + * Determine if aggregations should be synced to global variable | |
| 458 | + * | |
| 459 | + * @since 5.3.0 | |
| 460 | + * @param \WP_Query $query The query to evaluate | |
| 461 | + * @return bool True if should sync to global, false otherwise | |
| 462 | + */ | |
| 463 | + protected function should_sync_to_global( $query ) { | |
| 464 | + /** | |
| 465 | + * Filter whether to sync query aggregations to global variable | |
| 466 | + * | |
| 467 | + * @since 5.3.0 | |
| 468 | + * @hook ep_facet_sync_aggregations_to_global | |
| 469 | + * @param {bool} $sync Whether to sync (default: false) | |
| 470 | + * @param {WP_Query} $query The query object | |
| 471 | + * @return {bool} Whether to sync aggregations to global variable | |
| 472 | + */ | |
| 473 | + return apply_filters( 'ep_facet_sync_aggregations_to_global', false, $query ); | |
| 474 | + } | |
| 475 | + | |
| 476 | + /** | |
| 401 | 477 | * Get currently selected facets from query args |
| 402 | 478 | * |
| 403 | 479 | * @since 2.5 |
| 404 | 480 | * @return array |
| @@ -403,22 +479,28 @@ | ||
| 403 | 479 | * @since 2.5 |
| 404 | 480 | * @return array |
| 405 | 481 | */ |
| 406 | 482 | public function get_selected() { |
| 407 | - $filters = array( | |
| 408 | - 'taxonomies' => [], | |
| 409 | - ); | |
| 483 | + $allowed_args = $this->get_allowed_query_args(); | |
| 410 | 484 | |
| 411 | - $allowed_args = $this->get_allowed_query_args(); | |
| 412 | - $filter_name = $this->get_filter_name(); | |
| 485 | + $filters = []; | |
| 486 | + $filter_names = []; | |
| 487 | + foreach ( $this->types as $type_obj ) { | |
| 488 | + $filter_names[ $type_obj->get_filter_name() ] = $type_obj; | |
| 489 | + } | |
| 413 | 490 | |
| 414 | 491 | foreach ( $_GET as $key => $value ) { // phpcs:ignore WordPress.Security.NonceVerification |
| 415 | - if ( 0 === strpos( $key, $filter_name ) ) { | |
| 416 | - $taxonomy = str_replace( $filter_name, '', $key ); | |
| 492 | + $key = sanitize_key( $key ); | |
| 417 | 493 | |
| 418 | - $filters['taxonomies'][ $taxonomy ] = array( | |
| 419 | - 'terms' => array_fill_keys( array_map( 'trim', explode( ',', trim( $value, ',' ) ) ), true ), | |
| 420 | - ); | |
| 494 | + foreach ( $filter_names as $filter_name => $type_obj ) { | |
| 495 | + if ( 0 === strpos( $key, $filter_name ) ) { | |
| 496 | + if ( empty( $value ) ) { | |
| 497 | + continue; | |
| 498 | + } | |
| 499 | + $facet = str_replace( $filter_name, '', $key ); | |
| 500 | + | |
| 501 | + $filters = $type_obj->format_selected( $facet, $value, $filters ); | |
| 502 | + } | |
| 421 | 503 | } |
| 422 | 504 | |
| 423 | 505 | if ( in_array( $key, $allowed_args, true ) ) { |
| 424 | 506 | $filters[ $key ] = $value; |
| @@ -424,9 +506,17 @@ | ||
| 424 | 506 | $filters[ $key ] = $value; |
| 425 | 507 | } |
| 426 | 508 | } |
| 427 | 509 | |
| 428 | - return $filters; | |
| 510 | + /** | |
| 511 | + * Filter selected filters. | |
| 512 | + * | |
| 513 | + * @hook ep_facet_selected_filters | |
| 514 | + * @since 5.1.4 | |
| 515 | + * @param {array} $filters Current filters | |
| 516 | + * @return {array} New filters | |
| 517 | + */ | |
| 518 | + return apply_filters( 'ep_facet_selected_filters', $filters ); | |
| 429 | 519 | } |
| 430 | 520 | |
| 431 | 521 | /** |
| 432 | 522 | * Build query url |
| @@ -435,31 +525,29 @@ | ||
| 435 | 525 | * @param array $filters Facet filters |
| 436 | 526 | * @return string |
| 437 | 527 | */ |
| 438 | 528 | public function build_query_url( $filters ) { |
| 439 | - $query_param = array(); | |
| 529 | + $query_params = array(); | |
| 440 | 530 | |
| 441 | - if ( ! empty( $filters['taxonomies'] ) ) { | |
| 442 | - $tax_filters = $filters['taxonomies']; | |
| 443 | - | |
| 444 | - foreach ( $tax_filters as $taxonomy => $filter ) { | |
| 445 | - if ( ! empty( $filter['terms'] ) ) { | |
| 446 | - $query_param[ $this->get_filter_name() . $taxonomy ] = implode( ',', array_keys( $filter['terms'] ) ); | |
| 447 | - } | |
| 531 | + foreach ( $this->types as $type_obj ) { | |
| 532 | + if ( empty( $filters[ $type_obj->get_filter_type() ] ) ) { | |
| 533 | + continue; | |
| 448 | 534 | } |
| 535 | + $query_params = $type_obj->add_query_params( $query_params, $filters ); | |
| 449 | 536 | } |
| 450 | 537 | |
| 451 | - $allowed_args = $this->get_allowed_query_args(); | |
| 538 | + $feature = Features::factory()->get_registered_feature( 'facets' ); | |
| 539 | + $allowed_args = $feature->get_allowed_query_args(); | |
| 452 | 540 | |
| 453 | 541 | if ( ! empty( $filters ) ) { |
| 454 | 542 | foreach ( $filters as $filter => $value ) { |
| 455 | - if ( ! empty( $value ) && in_array( $filter, $allowed_args, true ) ) { | |
| 456 | - $query_param[ $filter ] = $value; | |
| 543 | + if ( in_array( $filter, $allowed_args, true ) ) { | |
| 544 | + $query_params[ $filter ] = $value; | |
| 457 | 545 | } |
| 458 | 546 | } |
| 459 | 547 | } |
| 460 | 548 | |
| 461 | - $query_string = http_build_query( $query_param ); | |
| 549 | + $query_string = build_query( $query_params ); | |
| 462 | 550 | |
| 463 | 551 | /** |
| 464 | 552 | * Filter facet query string |
| 465 | 553 | * |
| @@ -464,14 +552,14 @@ | ||
| 464 | 552 | * Filter facet query string |
| 465 | 553 | * |
| 466 | 554 | * @hook ep_facet_query_string |
| 467 | 555 | * @param {string} $query_string Current query string |
| 468 | - * @param {array} $query_param Query parameters | |
| 556 | + * @param {array} $query_params Query parameters | |
| 469 | 557 | * @return {string} New query string |
| 470 | 558 | */ |
| 471 | - $query_string = apply_filters( 'ep_facet_query_string', $query_string, $query_param ); | |
| 559 | + $query_string = apply_filters( 'ep_facet_query_string', $query_string, $query_params ); | |
| 472 | 560 | |
| 473 | - $url = $_SERVER['REQUEST_URI']; | |
| 561 | + $url = isset( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : ''; | |
| 474 | 562 | $pagination = strpos( $url, '/page' ); |
| 475 | 563 | if ( false !== $pagination ) { |
| 476 | 564 | $url = substr( $url, 0, $pagination ); |
| 477 | 565 | } |
| @@ -481,28 +569,31 @@ | ||
| 481 | 569 | |
| 482 | 570 | /** |
| 483 | 571 | * Register facet widget(s) |
| 484 | 572 | * |
| 485 | - * @since 2.5 | |
| 573 | + * @since 2.5, deprecated in 4.3.0 | |
| 486 | 574 | */ |
| 487 | 575 | public function register_widgets() { |
| 488 | - register_widget( __NAMESPACE__ . '\Widget' ); | |
| 576 | + _deprecated_function( __METHOD__, '4.3.0', "\ElasticPress\Features::factory()->get_registered_feature( 'facets' )->types[ \$type ]->register_widgets()" ); | |
| 489 | 577 | } |
| 490 | 578 | |
| 491 | 579 | /** |
| 492 | - * Output feature box long | |
| 580 | + * Hide the legacy widget. | |
| 493 | 581 | * |
| 494 | - * @since 2.5 | |
| 582 | + * Hides the legacy widget in favor of the Block when the block editor | |
| 583 | + * is in use and the legacy widget has not been used. | |
| 584 | + * | |
| 585 | + * @since 4.3 | |
| 586 | + * @param array $widgets An array of excluded widget-type IDs. | |
| 587 | + * @return array array of excluded widget-type IDs to hide. | |
| 495 | 588 | */ |
| 496 | - public function output_feature_box_long() { | |
| 497 | - ?> | |
| 498 | - <p> | |
| 499 | - <?php | |
| 500 | - // translators: URL | |
| 501 | - echo wp_kses_post( sprintf( __( "Adds a <a href='%s'>Facet widget</a> that administrators can add to the website's sidebars (widgetized areas), so that visitors can filter applicable content and search results by one or more taxonomy terms.", 'elasticpress' ), esc_url( admin_url( 'widgets.php' ) ) ) ); | |
| 502 | - ?> | |
| 503 | - </p> | |
| 504 | - <?php | |
| 589 | + public function hide_legacy_widget( $widgets ) { | |
| 590 | + $widgets[] = 'ep-facet'; | |
| 591 | + $widgets[] = 'ep-facet-date'; | |
| 592 | + $widgets[] = 'ep-facet-meta'; | |
| 593 | + $widgets[] = 'ep-facet-meta-range'; | |
| 594 | + | |
| 595 | + return $widgets; | |
| 505 | 596 | } |
| 506 | 597 | |
| 507 | 598 | /** |
| 508 | 599 | * Returns allowed query args for facets |
| @@ -510,11 +601,26 @@ | ||
| 510 | 601 | * @return mixed|void |
| 511 | 602 | * @since 3.6.0 |
| 512 | 603 | */ |
| 513 | 604 | public function get_allowed_query_args() { |
| 514 | - $args = array( 's', 'post_type' ); | |
| 605 | + $args = array( 's', 'post_type', 'orderby' ); | |
| 515 | 606 | |
| 607 | + // Retrieve all registered query variables for public taxonomies | |
| 608 | + $taxonomies = get_taxonomies( [ 'public' => true ], 'objects' ); | |
| 609 | + foreach ( $taxonomies as $taxonomy ) { | |
| 610 | + if ( $taxonomy->query_var ) { | |
| 611 | + $args[] = $taxonomy->query_var; | |
| 612 | + } | |
| 613 | + } | |
| 516 | 614 | /** |
| 615 | + * To keep backward compatibility, WordPress uses `'cat'` for default categories. | |
| 616 | + * It also allows access using the `?taxonomy=<tax>&term=<term>` format. | |
| 617 | + * | |
| 618 | + * @see get_term_link() | |
| 619 | + */ | |
| 620 | + $args = array_merge( $args, [ 'cat', 'taxonomy', 'term' ] ); | |
| 621 | + | |
| 622 | + /** | |
| 517 | 623 | * Filter allowed query args |
| 518 | 624 | * |
| 519 | 625 | * @hook ep_facet_allowed_query_args |
| 520 | 626 | * @since 3.6.0 |
| @@ -529,38 +635,124 @@ | ||
| 529 | 635 | * |
| 530 | 636 | * @return string The filter name. |
| 531 | 637 | */ |
| 532 | 638 | protected function get_filter_name() { |
| 639 | + _deprecated_function( __METHOD__, '4.3.0', "\ElasticPress\Features::factory()->get_registered_feature( 'facets' )->types['taxonomy']->get_filter_name()" ); | |
| 640 | + | |
| 641 | + return $this->types['taxonomy']->get_filter_name(); | |
| 642 | + } | |
| 643 | + | |
| 644 | + /** | |
| 645 | + * Get all taxonomies that could be selected for a facet. | |
| 646 | + * | |
| 647 | + * @since 4.2.0, deprecated in 4.3.0 | |
| 648 | + * @return array | |
| 649 | + */ | |
| 650 | + public function get_facetable_taxonomies() { | |
| 651 | + _deprecated_function( __METHOD__, '4.3.0', "\ElasticPress\Features::factory()->get_registered_feature( 'facets' )->types['taxonomy']->get_facetable_taxonomies()" ); | |
| 652 | + | |
| 653 | + return $this->types['taxonomy']->get_filter_name(); | |
| 654 | + } | |
| 655 | + | |
| 656 | + /** | |
| 657 | + * Add a new filter to the ES query with selected facets | |
| 658 | + * | |
| 659 | + * @since 4.4.0 | |
| 660 | + * @param array $filters Current filters | |
| 661 | + * @param array $args WP Query args | |
| 662 | + * @param WP_Query $query WP Query object | |
| 663 | + * @return array | |
| 664 | + */ | |
| 665 | + public function apply_facets_filters( $filters, $args, $query ) { | |
| 666 | + if ( ! $this->is_facetable( $query ) ) { | |
| 667 | + return $filters; | |
| 668 | + } | |
| 669 | + | |
| 533 | 670 | /** |
| 534 | - * Filter the facet filter name that's added to the URL | |
| 671 | + * Filter facet selection filters to be applied to the ES query | |
| 535 | 672 | * |
| 536 | - * @hook ep_facet_filter_name | |
| 537 | - * @since 4.0.0 | |
| 538 | - * @param {string} Facet filter name | |
| 539 | - * @return {string} New facet filter name | |
| 673 | + * @hook ep_facet_query_filters | |
| 674 | + * @since 4.4.0 | |
| 675 | + * @param {array} $filters Current filters | |
| 676 | + * @param {array} $args WP Query args | |
| 677 | + * @param {WP_Query} $query WP Query object | |
| 678 | + * @return {array} New filters | |
| 540 | 679 | */ |
| 541 | - return apply_filters( 'ep_facet_filter_name', 'ep_filter_' ); | |
| 680 | + $facets_filters = apply_filters( 'ep_facet_query_filters', [], $args, $query ); | |
| 681 | + | |
| 682 | + if ( empty( $facets_filters ) ) { | |
| 683 | + return $filters; | |
| 684 | + } | |
| 685 | + | |
| 686 | + $es_operator = ( 'any' === $this->get_match_type() ) ? 'should' : 'must'; | |
| 687 | + | |
| 688 | + $filters['facets'] = [ | |
| 689 | + 'bool' => [ | |
| 690 | + $es_operator => $facets_filters, | |
| 691 | + ], | |
| 692 | + ]; | |
| 693 | + | |
| 694 | + return $filters; | |
| 542 | 695 | } |
| 543 | 696 | |
| 544 | 697 | /** |
| 545 | - * Get all taxonomies that could be selected for a facet. | |
| 698 | + * Utility function to retrieve the match type selected by the user. | |
| 546 | 699 | * |
| 547 | - * @since 4.2.0 | |
| 548 | - * @return array | |
| 700 | + * @since 4.4.0 | |
| 701 | + * @return string | |
| 549 | 702 | */ |
| 550 | - public function get_facetable_taxonomies() { | |
| 551 | - $taxonomies = get_taxonomies( array( 'public' => true ), 'object' ); | |
| 703 | + public function get_match_type() { | |
| 704 | + $settings = $this->get_settings(); | |
| 705 | + | |
| 552 | 706 | /** |
| 553 | - * Filter taxonomies made available for faceting | |
| 707 | + * Filter the match type of all facets. Can be 'all' or 'any'. | |
| 554 | 708 | * |
| 555 | - * @hook ep_facet_include_taxonomies | |
| 556 | - * @param {array} $taxonomies Taxonomies | |
| 557 | - * @return {array} New taxonomies | |
| 709 | + * @hook ep_facet_match_type | |
| 710 | + * @since 4.4.0 | |
| 711 | + * @param {string} $match_type Current selection | |
| 712 | + * @return {string} New selection | |
| 558 | 713 | */ |
| 559 | - return apply_filters( 'ep_facet_include_taxonomies', $taxonomies ); | |
| 714 | + return apply_filters( 'ep_facet_match_type', $settings['match_type'] ); | |
| 560 | 715 | } |
| 561 | 716 | |
| 562 | 717 | /** |
| 718 | + * Given an array of filters, remove the facets filter. | |
| 719 | + * | |
| 720 | + * This is used when the user wants posts matching ANY criteria, so aggregations should not restrict their results. | |
| 721 | + * | |
| 722 | + * @since 4.4.0 | |
| 723 | + * @param array $filters Filters to be applied to the ES query | |
| 724 | + * @return array | |
| 725 | + */ | |
| 726 | + public function remove_facets_filter( $filters ) { | |
| 727 | + unset( $filters['facets'] ); | |
| 728 | + return $filters; | |
| 729 | + } | |
| 730 | + | |
| 731 | + /** | |
| 732 | + * Set the `settings_schema` attribute | |
| 733 | + * | |
| 734 | + * @since 5.0.0 | |
| 735 | + */ | |
| 736 | + protected function set_settings_schema() { | |
| 737 | + $this->settings_schema[] = [ | |
| 738 | + 'key' => 'match_type', | |
| 739 | + 'label' => __( 'Filter matching', 'elasticpress' ), | |
| 740 | + 'options' => [ | |
| 741 | + [ | |
| 742 | + 'label' => __( 'Show results that match <strong>all</strong> selected filters', 'elasticpress' ), | |
| 743 | + 'value' => 'all', | |
| 744 | + ], | |
| 745 | + [ | |
| 746 | + 'label' => __( 'Show results that match <strong>any</strong> selected filter', 'elasticpress' ), | |
| 747 | + 'value' => 'any', | |
| 748 | + ], | |
| 749 | + ], | |
| 750 | + 'type' => 'radio', | |
| 751 | + ]; | |
| 752 | + } | |
| 753 | + | |
| 754 | + /** | |
| 563 | 755 | * Figure out if Facet widget can display on page. |
| 564 | 756 | * |
| 565 | 757 | * @param WP_Query $query WP Query |
| 566 | 758 | * @since 4.2.1 |
| @@ -567,6 +759,22 @@ | ||
| 567 | 759 | * @return bool |
| 568 | 760 | */ |
| 569 | 761 | protected function is_facetable_page( $query ) { |
| 570 | 762 | return $query->is_home() || $query->is_search() || $query->is_tax() || $query->is_tag() || $query->is_category() || $query->is_post_type_archive(); |
| 763 | + } | |
| 764 | + | |
| 765 | + /** | |
| 766 | + * Setup REST endpoints | |
| 767 | + * | |
| 768 | + * @since 5.0.0 | |
| 769 | + */ | |
| 770 | + public function setup_endpoints() { | |
| 771 | + $meta_keys = new REST\MetaKeys(); | |
| 772 | + $meta_keys->register_routes(); | |
| 773 | + | |
| 774 | + $meta_range = new REST\MetaRange(); | |
| 775 | + $meta_range->register_routes(); | |
| 776 | + | |
| 777 | + $taxonomies = new REST\Taxonomies(); | |
| 778 | + $taxonomies->register_routes(); | |
| 571 | 779 | } |
| 572 | 780 | } |