PluginProbe
ElasticPress / 5.3.5
ElasticPress v5.3.5
5.3.5 5.3.4 3.6.5 3.6.6 4.0.0 4.0.1 4.1.0 4.2.0 4.2.1 4.2.2 4.3.0 4.3.1 4.4.0 4.4.1 4.5.0 4.5.1 4.5.2 4.6.0 4.6.1 4.7.0 4.7.1 4.7.2 5.0.0 5.0.1 5.0.2 All 108 releases
← All changes | includes/classes/Feature/WooCommerce/WooCommerce.php +320 -1049 4.5.05.3.5 View file →
@@ -9,10 +9,8 @@
9 9 namespace ElasticPress\Feature\WooCommerce;
10 10
11 11 use ElasticPress\Feature;
12 12 use ElasticPress\FeatureRequirementsStatus;
13 -use ElasticPress\Indexables;
14 -use ElasticPress\IndexHelper;
15 13 use ElasticPress\Utils;
16 14
17 15 if ( ! defined( 'ABSPATH' ) ) {
18 16 exit; // Exit if accessed directly.
@@ -22,10 +20,26 @@
22 20 * WooCommerce feature class
23 21 */
24 22 class WooCommerce extends Feature {
25 23 /**
26 - * If enabled, receive the Orders object instance
24 + * If enabled, receive the OrdersAutosuggest object instance
27 25 *
26 + * @since 4.7.0
27 + * @var null|OrdersAutosuggest
28 + */
29 + public $orders_autosuggest = null;
30 +
31 + /**
32 + * Receive the Products object instance
33 + *
34 + * @since 4.7.0
35 + * @var null|Products
36 + */
37 + public $products = null;
38 +
39 + /**
40 + * Receive the Orders object instance
41 + *
28 42 * @since 4.5.0
29 43 * @var null|Orders
30 44 */
31 45 public $orders = null;
@@ -37,14 +51,10 @@
37 51 */
38 52 public function __construct() {
39 53 $this->slug = 'woocommerce';
40 54
41 - $this->title = esc_html__( 'WooCommerce', 'elasticpress' );
55 + $this->group = 'woocommerce';
42 56
43 - $this->summary = __( '“I want a cotton, woman’s t-shirt, for under $15 that’s in stock.” Faceted product browsing strains servers and increases load times. Your buyers can find the perfect product quickly, and buy it quickly.', 'elasticpress' );
44 -
45 - $this->docs_url = __( 'https://elasticpress.zendesk.com/hc/en-us/articles/360050447492-Configuring-ElasticPress-via-the-Plugin-Dashboard#woocommerce', 'elasticpress' );
46 -
47 57 $this->requires_install_reindex = true;
48 58
49 59 $this->setting_requires_install_reindex = 'orders';
50 60
@@ -53,638 +63,364 @@
53 63 $this->default_settings = [
54 64 'orders' => '0',
55 65 ];
56 66
57 - $this->orders = new Orders();
67 + $this->orders = new Orders( $this );
68 + $this->products = new Products( $this );
69 + $this->orders_autosuggest = new OrdersAutosuggest( $this );
58 70
59 71 parent::__construct();
60 72 }
61 73
62 74 /**
63 - * Index Woocommerce meta
75 + * Sets i18n strings.
64 76 *
65 - * @param array $meta Existing post meta.
66 - * @param array $post Post arguments array.
67 - * @since 2.1
68 - * @return array
77 + * @return void
78 + * @since 5.2.0
69 79 */
70 - public function whitelist_meta_keys( $meta, $post ) {
71 - return array_unique(
72 - array_merge(
73 - $meta,
74 - array(
75 - '_thumbnail_id',
76 - '_product_attributes',
77 - '_wpb_vc_js_status',
78 - '_swatch_type',
79 - 'total_sales',
80 - '_downloadable',
81 - '_virtual',
82 - '_regular_price',
83 - '_sale_price',
84 - '_tax_status',
85 - '_tax_class',
86 - '_purchase_note',
87 - '_featured',
88 - '_weight',
89 - '_length',
90 - '_width',
91 - '_height',
92 - '_visibility',
93 - '_sku',
94 - '_sale_price_dates_from',
95 - '_sale_price_dates_to',
96 - '_price',
97 - '_sold_individually',
98 - '_manage_stock',
99 - '_backorders',
100 - '_stock',
101 - '_upsell_ids',
102 - '_crosssell_ids',
103 - '_stock_status',
104 - '_product_version',
105 - '_product_tabs',
106 - '_override_tab_layout',
107 - '_suggested_price',
108 - '_min_price',
109 - '_customer_user',
110 - '_variable_billing',
111 - '_wc_average_rating',
112 - '_product_image_gallery',
113 - '_bj_lazy_load_skip_post',
114 - '_min_variation_price',
115 - '_max_variation_price',
116 - '_min_price_variation_id',
117 - '_max_price_variation_id',
118 - '_min_variation_regular_price',
119 - '_max_variation_regular_price',
120 - '_min_regular_price_variation_id',
121 - '_max_regular_price_variation_id',
122 - '_min_variation_sale_price',
123 - '_max_variation_sale_price',
124 - '_min_sale_price_variation_id',
125 - '_max_sale_price_variation_id',
126 - '_default_attributes',
127 - '_swatch_type_options',
128 - '_order_key',
129 - '_billing_company',
130 - '_billing_address_1',
131 - '_billing_address_2',
132 - '_billing_city',
133 - '_billing_postcode',
134 - '_billing_country',
135 - '_billing_state',
136 - '_billing_email',
137 - '_billing_phone',
138 - '_shipping_address_1',
139 - '_shipping_address_2',
140 - '_shipping_city',
141 - '_shipping_postcode',
142 - '_shipping_country',
143 - '_shipping_state',
144 - '_billing_last_name',
145 - '_billing_first_name',
146 - '_shipping_first_name',
147 - '_shipping_last_name',
148 - '_variations_skus',
149 - )
150 - )
151 - );
80 + public function set_i18n_strings(): void {
81 + $this->title = esc_html__( 'WooCommerce', 'elasticpress' );
82 +
83 + $this->summary = '<p>' . __( 'Most caching and performance tools can’t keep up with the nearly infinite ways your visitors might filter or navigate your products. No matter how many products, filters, or customers you have, ElasticPress will keep your online store performing quickly. If used in combination with the Protected Content feature, ElasticPress will also accelerate order searches and back end product management.', 'elasticpress' ) . '</p>';
84 +
85 + $this->docs_url = __( 'https://www.elasticpress.io/resources/articles/configuring-elasticpress-via-the-plugin-dashboard/#woocommerce', 'elasticpress' );
152 86 }
153 87
154 88 /**
155 - * Make sure all loop shop post ins are IDS. We have to pass post objects here since we override
156 - * the fields=>id query for the layered filter nav query
89 + * Setup all feature filters
157 90 *
158 - * @param array $posts Post object array.
159 - * @since 2.1
160 - * @return array
91 + * @since 2.1
161 92 */
162 - public function convert_post_object_to_id( $posts ) {
163 - _doing_it_wrong( __METHOD__, 'This filter was removed from WooCommerce and will be removed from ElasticPress in a future release.', '4.5.0' );
164 - return $posts;
93 + public function setup() {
94 + if ( ! function_exists( 'WC' ) ) {
95 + return;
96 + }
97 +
98 + add_action( 'switch_blog', [ $this, 'setup_or_tear_down' ] );
99 +
100 + add_filter( 'ep_integrate_search_queries', [ $this, 'disallow_coupons' ], 10, 2 );
101 +
102 + $this->products->setup();
103 + $this->orders->setup();
104 + $this->orders_autosuggest->setup();
165 105 }
166 106
167 107 /**
168 - * Index Woocommerce taxonomies
108 + * Setup or tear down the functionality depending on the plugin being active for the current site.
169 109 *
170 - * @param array $taxonomies Index taxonomies array.
171 - * @param array $post Post properties array.
172 - * @since 2.1
173 - * @return array
110 + * If the site wasn't initialized yet (it does not have its database tables created) we skip it.
111 + *
112 + * @since 5.0.0
113 + * @param int $blog_id Blog ID
114 + * @return void
174 115 */
175 - public function whitelist_taxonomies( $taxonomies, $post ) {
176 - $woo_taxonomies = [];
177 -
178 - $product_type = get_taxonomy( 'product_type' );
179 - if ( false !== $product_type ) {
180 - $woo_taxonomies[] = $product_type;
116 + public function setup_or_tear_down( $blog_id ) {
117 + include_once ABSPATH . 'wp-admin/includes/plugin.php';
118 + if ( wp_is_site_initialized( $blog_id ) && \is_plugin_active( 'woocommerce/woocommerce.php' ) ) {
119 + $this->setup();
120 + } else {
121 + $this->tear_down();
181 122 }
123 + }
182 124
183 - $product_visibility = get_taxonomy( 'product_visibility' );
184 - if ( false !== $product_visibility ) {
185 - $woo_taxonomies[] = $product_visibility;
186 - }
125 + /**
126 + * Un-setup all feature filters
127 + *
128 + * @since 5.0.0
129 + */
130 + public function tear_down() {
131 + remove_filter( 'ep_integrate_search_queries', [ $this, 'disallow_coupons' ] );
187 132
188 - /**
189 - * Note product_shipping_class, product_cat, and product_tag are already public. Make
190 - * sure to index non-attribute taxonomies.
191 - */
192 - $attribute_taxonomies = wc_get_attribute_taxonomies();
193 -
194 - if ( ! empty( $attribute_taxonomies ) ) {
195 - foreach ( $attribute_taxonomies as $tax ) {
196 - $name = wc_attribute_taxonomy_name( $tax->attribute_name );
197 -
198 - if ( ! empty( $name ) ) {
199 - if ( empty( $tax->attribute_ ) ) {
200 - $woo_taxonomies[] = get_taxonomy( $name );
201 - }
202 - }
203 - }
204 - }
205 -
206 - return array_merge( $taxonomies, $woo_taxonomies );
133 + $this->products->tear_down();
134 + $this->orders->tear_down();
135 + $this->orders_autosuggest->tear_down();
207 136 }
208 137
209 138 /**
210 - * Disallow duplicated ES queries on Orders page.
139 + * Given a WP_Query object, return its search term (if any)
211 140 *
212 - * @since 2.4
141 + * This method also accounts for the `'search'` parameter used by
142 + * WooCommerce, in addition to the regular `'s'` parameter.
213 143 *
214 - * @param array $value Original filter values.
215 - * @param WP_Query $query WP_Query
216 - *
217 - * @return array
144 + * @param \WP_Query $query The WP_Query object
145 + * @return string
218 146 */
219 - public function disallow_duplicated_query( $value, $query ) {
220 - _doing_it_wrong( __METHOD__, 'This filter was removed from WooCommerce and will be removed from ElasticPress in a future release.', '4.5.0' );
221 -
222 - return $value;
147 + public function get_search_term( \WP_Query $query ): string {
148 + $search = $query->get( 'search' );
149 + return ( ! empty( $search ) ) ? $search : $query->get( 's', '' );
223 150 }
224 151
225 152 /**
226 - * Translate args to ElasticPress compat format. This is the meat of what the feature does
153 + * Make search coupons don't go through ES
227 154 *
155 + * @param bool $enabled Coupons enabled or not
228 156 * @param WP_Query $query WP Query
229 - * @since 2.1
157 + * @since 4.7.0
158 + * @return bool
230 159 */
231 - public function translate_args( $query ) {
232 - if ( ! $this->should_integrate_with_query( $query ) ) {
233 - return;
160 + public function disallow_coupons( $enabled, $query ) {
161 + if ( is_admin() ) {
162 + return $enabled;
234 163 }
235 164
236 - // Flag to check and make sure we are in a WooCommerce specific query
237 - $integrate = false;
165 + if ( 'shop_coupon' === $query->get( 'post_type' ) && empty( $query->query_vars['ep_integrate'] ) ) {
166 + return false;
167 + }
238 168
239 - /**
240 - * Force ElasticPress if we are querying WC taxonomy
241 - */
242 - $tax_query = $query->get( 'tax_query', [] );
169 + return $enabled;
170 + }
243 171
244 - $supported_taxonomies = array(
245 - 'product_cat',
246 - 'product_tag',
247 - 'product_type',
248 - 'product_visibility',
249 - 'product_shipping_class',
250 - );
172 + /**
173 + * Determine WC feature reqs status
174 + *
175 + * @since 2.2
176 + * @return EP_Feature_Requirements_Status
177 + */
178 + public function requirements_status() {
179 + $status = new FeatureRequirementsStatus( 0, null, $this );
251 180
252 - // Add in any attribute taxonomies that exist
253 - $attribute_taxonomies = wc_get_attribute_taxonomy_names();
181 + if ( ! class_exists( 'WooCommerce' ) ) {
182 + $status->code = 2;
183 + $status->message = esc_html__( 'WooCommerce not installed.', 'elasticpress' );
184 + }
254 185
255 - $supported_taxonomies = array_merge( $supported_taxonomies, $attribute_taxonomies );
186 + return $status;
187 + }
256 188
257 - /**
258 - * Filter supported custom taxonomies for WooCommerce integration
259 - *
260 - * @param {array} $supported_taxonomies An array of default taxonomies.
261 - * @hook ep_woocommerce_supported_taxonomies
262 - * @since 2.3.0
263 - * @return {array} New taxonomies
264 - */
265 - $supported_taxonomies = apply_filters( 'ep_woocommerce_supported_taxonomies', $supported_taxonomies );
266 -
267 - if ( ! empty( $tax_query ) ) {
268 -
269 - /**
270 - * First check if already set taxonomies are supported WC taxes
271 - */
272 - foreach ( $tax_query as $taxonomy_array ) {
273 - if ( isset( $taxonomy_array['taxonomy'] ) && in_array( $taxonomy_array['taxonomy'], $supported_taxonomies, true ) ) {
274 - $integrate = true;
275 - }
276 - }
189 + /**
190 + * Determines whether or not ES should be integrating with the provided query
191 + *
192 + * @param \WP_Query $query Query we might integrate with
193 + *
194 + * @return bool
195 + */
196 + public function should_integrate_with_query( $query ) {
197 + // Lets make sure this doesn't interfere with the CLI
198 + if ( defined( 'WP_CLI' ) && WP_CLI ) {
199 + return false;
277 200 }
278 201
279 - /**
280 - * Next check if any taxonomies are in the root of query vars (shorthand form)
281 - */
282 - foreach ( $supported_taxonomies as $taxonomy ) {
283 - $term = $query->get( $taxonomy, false );
284 -
285 - if ( ! empty( $term ) ) {
286 - $integrate = true;
287 -
288 - $tax_query[] = array(
289 - 'taxonomy' => $taxonomy,
290 - 'field' => 'slug',
291 - 'terms' => (array) $term,
292 - );
293 - }
202 + if ( defined( 'WC_API_REQUEST' ) && WC_API_REQUEST ) {
203 + return false;
294 204 }
295 205
296 - /**
297 - * Force ElasticPress if product post type query
298 - */
299 - $post_type = $query->get( 'post_type', false );
300 -
301 - // Act only on a defined subset of all indexable post types here
302 - $post_types = array(
303 - 'shop_order',
304 - 'shop_order_refund',
305 - 'product_variation',
306 - );
307 -
308 - $is_main_post_type_archive = $query->is_main_query() && $query->is_post_type_archive( 'product' );
309 - $has_ep_integrate_set_true = isset( $query->query_vars['ep_integrate'] ) && filter_var( $query->query_vars['ep_integrate'], FILTER_VALIDATE_BOOLEAN );
310 - if ( $is_main_post_type_archive || $has_ep_integrate_set_true ) {
311 - $post_types[] = 'product';
206 + if ( isset( $query->query_vars['ep_integrate'] ) && ! filter_var( $query->query_vars['ep_integrate'], FILTER_VALIDATE_BOOLEAN ) ) {
207 + return false;
312 208 }
313 209
314 210 /**
315 - * Expands or contracts the post_types eligible for indexing.
211 + * Filter to skip WP Query integration
316 212 *
317 - * @hook ep_woocommerce_default_supported_post_types
318 - * @since 4.4.0
319 - * @param {array} $post_types Post types
320 - * @return {array} New post types
213 + * @hook ep_skip_query_integration
214 + * @param {bool} $skip True to skip
215 + * @param {WP_Query} $query WP Query to evaluate
216 + * @return {bool} New skip value
321 217 */
322 - $supported_post_types = apply_filters( 'ep_woocommerce_default_supported_post_types', $post_types );
218 + if ( apply_filters( 'ep_skip_query_integration', false, $query ) ) {
219 + return false;
220 + }
323 221
324 - $supported_post_types = array_intersect(
325 - $supported_post_types,
326 - Indexables::factory()->get( 'post' )->get_indexable_post_types()
327 - );
328 -
329 - // For orders it queries an array of shop_order and shop_order_refund post types, hence an array_diff
330 - if ( ! empty( $post_type ) && ( in_array( $post_type, $supported_post_types, true ) || ( is_array( $post_type ) && ! array_diff( $post_type, $supported_post_types ) ) ) ) {
331 - $integrate = true;
222 + if ( ! Utils\is_integrated_request( $this->slug ) ) {
223 + return false;
332 224 }
333 225
334 226 /**
335 - * If we have a WooCommerce specific query, lets hook it to ElasticPress and make the query ElasticSearch friendly
227 + * Do nothing for single product queries
336 228 */
337 - if ( ! $integrate ) {
338 - return;
229 + $product_name = $query->get( 'product', false );
230 + if ( ! empty( $product_name ) || $query->is_single() ) {
231 + return false;
339 232 }
340 233
341 - // Set tax_query again since we may have added things
342 - $query->set( 'tax_query', $tax_query );
343 -
344 - // Default to product if no post type is set
345 - if ( empty( $post_type ) ) {
346 - $post_type = 'product';
347 - $query->set( 'post_type', 'product' );
348 - }
349 -
350 - // Handles the WC Top Rated Widget
351 - if ( has_filter( 'posts_clauses', array( WC()->query, 'order_by_rating_post_clauses' ) ) ) {
352 - remove_filter( 'posts_clauses', array( WC()->query, 'order_by_rating_post_clauses' ) );
353 - $query->set( 'orderby', 'meta_value_num' );
354 - $query->set( 'meta_key', '_wc_average_rating' );
355 - }
356 -
357 234 /**
358 - * WordPress have to be version 4.6 or newer to have "fields" support
359 - * since it requires the "posts_pre_query" filter.
360 - *
361 - * @see WP_Query::get_posts
235 + * ElasticPress does not yet support post_parent queries
362 236 */
363 - $fields = $query->get( 'fields', false );
364 - if ( ! version_compare( get_bloginfo( 'version' ), '4.6', '>=' ) && ( 'ids' === $fields || 'id=>parent' === $fields ) ) {
365 - $query->set( 'fields', 'default' );
237 + $post_parent = $query->get( 'post_parent', false );
238 + if ( ! empty( $post_parent ) ) {
239 + return false;
366 240 }
367 241
368 242 /**
369 - * Handle meta queries
243 + * If this is just a preview, let's not use Elasticsearch.
370 244 */
371 - $meta_query = $query->get( 'meta_query', [] );
372 - $meta_key = $query->get( 'meta_key', false );
373 - $meta_value = $query->get( 'meta_value', false );
245 + if ( $query->get( 'preview', false ) ) {
246 + return false;
247 + }
374 248
375 - if ( ! empty( $meta_key ) && ! empty( $meta_value ) ) {
376 - $meta_query[] = array(
377 - 'key' => $meta_key,
378 - 'value' => $meta_value,
379 - );
249 + return true;
250 + }
380 251
381 - $query->set( 'meta_query', $meta_query );
382 - }
383 -
252 + /**
253 + * Set the `settings_schema` attribute
254 + *
255 + * @since 5.0.0
256 + */
257 + protected function set_settings_schema() {
384 258 /**
385 - * Make sure filters are suppressed
259 + * Filters the WooCommerce Settings schema.
260 + *
261 + * @since 5.1.0
262 + * @hook ep_woocommerce_settings_schema
263 + * @param {array} $settings_schema WooCommerce feature settings schema
264 + * @return {array} $settings_schema
386 265 */
387 - $query->query['suppress_filters'] = false;
388 - $query->set( 'suppress_filters', false );
266 + $this->settings_schema = apply_filters( 'ep_woocommerce_settings_schema', $this->settings_schema );
267 + }
389 268
390 - // Integrate with WooCommerce custom searches as well
391 - $search = $query->get( 'search' );
392 - if ( ! empty( $search ) ) {
393 - $s = $search;
394 - $query->set( 's', $s );
395 - } else {
396 - $s = $query->get( 's' );
397 - }
269 + /**
270 + * DEPRECATED. Whether orders autosuggest is available or not
271 + *
272 + * @since 4.5.0
273 + * @deprecated 5.1.0
274 + * @return boolean
275 + */
276 + public function is_orders_autosuggest_available(): bool {
277 + _deprecated_function( __METHOD__, '5.1.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->is_available()" );
278 + return $this->orders_autosuggest->is_available();
279 + }
398 280
399 - $query->query_vars['ep_integrate'] = true;
400 - $query->query['ep_integrate'] = true;
281 + /**
282 + * DEPRECATED. Whether orders autosuggest is enabled or not
283 + *
284 + * @since 4.5.0
285 + * @deprecated 5.1.0
286 + * @return boolean
287 + */
288 + public function is_orders_autosuggest_enabled(): bool {
289 + _deprecated_function( __METHOD__, '5.1.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders_autosuggest->is_enabled()" );
290 + return $this->orders_autosuggest->is_enabled();
291 + }
401 292
402 - if ( ! empty( $s ) ) {
403 -
404 - $searchable_post_types = $this->get_admin_searchable_post_types();
405 -
406 - if ( in_array( $post_type, $searchable_post_types, true ) ) {
407 - $default_search_fields = array( 'post_title', 'post_content', 'post_excerpt' );
408 - if ( ctype_digit( $s ) ) {
409 - $default_search_fields[] = 'ID';
410 - }
411 - $search_fields = $query->get( 'search_fields', $default_search_fields );
412 -
413 - $search_fields['meta'] = array_map(
414 - 'wc_clean',
415 - /**
416 - * Filter shop order meta fields to search for WooCommerce
417 - *
418 - * @hook shop_order_search_fields
419 - * @param {array} $fields Shop order fields
420 - * @return {array} New fields
421 - */
422 - apply_filters(
423 - 'shop_order_search_fields',
424 - array(
425 - '_order_key',
426 - '_billing_company',
427 - '_billing_address_1',
428 - '_billing_address_2',
429 - '_billing_city',
430 - '_billing_postcode',
431 - '_billing_country',
432 - '_billing_state',
433 - '_billing_email',
434 - '_billing_phone',
435 - '_shipping_address_1',
436 - '_shipping_address_2',
437 - '_shipping_city',
438 - '_shipping_postcode',
439 - '_shipping_country',
440 - '_shipping_state',
441 - '_billing_last_name',
442 - '_billing_first_name',
443 - '_shipping_first_name',
444 - '_shipping_last_name',
445 - '_items',
446 - )
447 - )
448 - );
449 -
450 - $query->set(
451 - 'search_fields',
452 - /**
453 - * Filter all the shop order fields to search for WooCommerce
454 - *
455 - * @hook ep_woocommerce_shop_order_search_fields
456 - * @since 4.0.0
457 - * @param {array} $fields Shop order fields
458 - * @param {WP_Query} $query WP Query
459 - * @return {array} New fields
460 - */
461 - apply_filters( 'ep_woocommerce_shop_order_search_fields', $search_fields, $query )
462 - );
463 - } elseif ( 'product' === $post_type && defined( 'EP_IS_NETWORK' ) && EP_IS_NETWORK ) {
464 - $search_fields = $query->get( 'search_fields', array( 'post_title', 'post_content', 'post_excerpt' ) );
465 -
466 - // Remove author_name from this search.
467 - $search_fields = $this->remove_author( $search_fields );
468 -
469 - foreach ( $search_fields as $field_key => $field ) {
470 - if ( 'author_name' === $field ) {
471 - unset( $search_fields[ $field_key ] );
472 - }
473 - }
474 -
475 - $search_fields['meta'] = ( ! empty( $search_fields['meta'] ) ) ? $search_fields['meta'] : [];
476 - $search_fields['taxonomies'] = ( ! empty( $search_fields['taxonomies'] ) ) ? $search_fields['taxonomies'] : [];
477 -
478 - $search_fields['meta'] = array_merge( $search_fields['meta'], array( '_sku' ) );
479 - $search_fields['taxonomies'] = array_merge( $search_fields['taxonomies'], array( 'category', 'post_tag', 'product_tag', 'product_cat' ) );
480 -
481 - $query->set( 'search_fields', $search_fields );
482 - }
483 - } else {
484 - /**
485 - * For default sorting by popularity (total_sales) and rating
486 - * Woocommerce doesn't set the orderby correctly.
487 - * These lines will check the meta_key and correct the orderby based on that.
488 - * And this won't run in search result and only run in main query
489 - */
490 - $meta_key = $query->get( 'meta_key', false );
491 - if ( $meta_key && $query->is_main_query() ) {
492 - switch ( $meta_key ) {
493 - case 'total_sales':
494 - $query->set( 'orderby', $this->get_orderby_meta_mapping( 'total_sales' ) );
495 - $query->set( 'order', 'DESC' );
496 - break;
497 - case '_wc_average_rating':
498 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_wc_average_rating' ) );
499 - $query->set( 'order', 'DESC' );
500 - break;
501 - }
502 - }
503 - }
504 -
505 - /**
506 - * Set orderby and order for price/popularity when GET param not set
507 - */
508 - if ( isset( $query->query_vars['orderby'], $query->query_vars['order'] ) && $query->is_main_query() ) {
509 - switch ( $query->query_vars['orderby'] ) {
510 - case 'price':
511 - $query->set( 'order', $query->query_vars['order'] );
512 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_price' ) );
513 - break;
514 - case 'popularity':
515 - $query->set( 'orderby', $this->get_orderby_meta_mapping( 'total_sales' ) );
516 - $query->set( 'order', 'DESC' );
517 - break;
518 - }
519 - }
520 -
521 - /**
522 - * Set orderby from GET param
523 - * Also make sure the orderby param affects only the main query
524 - */
525 - if ( ! empty( $_GET['orderby'] ) && $query->is_main_query() ) { // phpcs:ignore WordPress.Security.NonceVerification
526 - $orderby = sanitize_text_field( $_GET['orderby'] ); // phpcs:ignore WordPress.Security.NonceVerification
527 - switch ( $orderby ) { // phpcs:ignore WordPress.Security.NonceVerification
528 - case 'popularity':
529 - $query->set( 'orderby', $this->get_orderby_meta_mapping( 'total_sales' ) );
530 - $query->set( 'order', 'DESC' );
531 - break;
532 - case 'price':
533 - $query->set( 'order', $query->get( 'order', 'ASC' ) );
534 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_price' ) );
535 - break;
536 - case 'price-desc':
537 - $query->set( 'order', 'DESC' );
538 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_price' ) );
539 - break;
540 - case 'rating':
541 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_wc_average_rating' ) );
542 - $query->set( 'order', 'DESC' );
543 - break;
544 - case 'date':
545 - case 'title':
546 - case 'ID':
547 - $query->set( 'orderby', $this->get_orderby_meta_mapping( $orderby ) );
548 - break;
549 - case 'sku':
550 - $query->set( 'orderby', $this->get_orderby_meta_mapping( '_sku' ) );
551 - break;
552 - default:
553 - $query->set( 'orderby', $this->get_orderby_meta_mapping( 'menu_order' ) ); // Order by menu and title.
554 - }
555 - }
293 + /**
294 + * DEPRECATED. Translate args to ElasticPress compat format. This is the meat of what the feature does
295 + *
296 + * @param \WP_Query $query WP Query
297 + * @since 2.1
298 + * @deprecated 4.7.0
299 + */
300 + public function translate_args( $query ) {
301 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->translate_args() OR \ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->translate_args()" );
302 + $this->products->translate_args( $query );
303 + $this->orders->translate_args( $query );
556 304 }
557 305
558 306 /**
559 - * Fetch the ES related meta mapping for orderby
307 + * DEPRECATED. Fetch the ES related meta mapping for orderby
560 308 *
561 309 * @param array $meta_key The meta key to get the mapping for.
562 310 * @since 2.1
311 + * @deprecated 4.7.0
563 312 * @return string The mapped meta key.
564 313 */
565 314 public function get_orderby_meta_mapping( $meta_key ) {
566 - /**
567 - * Filter WooCommerce to Elasticsearch meta mapping
568 - *
569 - * @hook orderby_meta_mapping
570 - * @param {array} $mapping Meta mapping
571 - * @return {array} New mapping
572 - */
573 - $mapping = apply_filters(
574 - 'orderby_meta_mapping',
575 - array(
576 - 'ID' => 'ID',
577 - 'title' => 'title date',
578 - 'menu_order' => 'menu_order title date',
579 - 'menu_order title' => 'menu_order title date',
580 - 'total_sales' => 'meta.total_sales.double date',
581 - '_wc_average_rating' => 'meta._wc_average_rating.double date',
582 - '_price' => 'meta._price.double date',
583 - '_sku' => 'meta._sku.value.sortable date',
315 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->get_orderby_meta_mapping()" );
316 + return $this->products->get_orderby_meta_mapping( $meta_key );
317 + }
318 +
319 + /**
320 + * DEPRECATED. Remove the author_name from search fields.
321 + *
322 + * @param array $search_fields Array of search fields.
323 + * @since 3.0
324 + * @deprecated 4.7.0
325 + * @return array
326 + */
327 + public function remove_author( $search_fields ) {
328 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->remove_author()" );
329 + return $this->products->remove_author( $search_fields );
330 + }
331 +
332 + /**
333 + * DEPRECATED. Index WooCommerce meta
334 + *
335 + * @param array $meta Existing post meta.
336 + * @param array $post Post arguments array.
337 + * @deprecated 4.7.0
338 + * @since 2.1
339 + * @return array
340 + */
341 + public function whitelist_meta_keys( $meta, $post ) {
342 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->allow_meta_keys() AND/OR \ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->allow_meta_keys()" );
343 + return array_unique(
344 + array_merge(
345 + $this->products->allow_meta_keys( $meta ),
346 + $this->orders->allow_meta_keys( $meta )
584 347 )
585 348 );
349 + }
586 350
587 - if ( isset( $mapping[ $meta_key ] ) ) {
588 - return $mapping[ $meta_key ];
589 - }
590 -
591 - return 'date';
351 + /**
352 + * DEPRECATED. Index WooCommerce taxonomies
353 + *
354 + * @param array $taxonomies Index taxonomies array.
355 + * @param array $post Post properties array.
356 + * @deprecated 4.7.0
357 + * @since 2.1
358 + * @return array
359 + */
360 + public function whitelist_taxonomies( $taxonomies, $post ) {
361 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->sync_taxonomies()" );
362 + return $this->products->sync_taxonomies( $taxonomies );
592 363 }
593 364
594 -
595 365 /**
596 - * Returns the WooCommerce-oriented post types in admin that EP will search
366 + * DEPRECATED. Returns the WooCommerce-oriented post types in admin that EP will search
597 367 *
598 368 * @since 4.4.0
369 + * @deprecated 4.7.0
599 370 * @return mixed|void
600 371 */
601 372 public function get_admin_searchable_post_types() {
602 - $searchable_post_types = array( 'shop_order' );
603 -
604 - /**
605 - * Filter admin searchable WooCommerce post types
606 - *
607 - * @hook ep_woocommerce_admin_searchable_post_types
608 - * @since 4.4.0
609 - * @param {array} $post_types Post types
610 - * @return {array} New post types
611 - */
612 - return apply_filters( 'ep_woocommerce_admin_searchable_post_types', $searchable_post_types );
373 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->get_admin_searchable_post_types()" );
374 + return $this->orders->get_admin_searchable_post_types();
613 375 }
614 376
615 377 /**
616 - * Make search coupons don't go through ES
378 + * DEPRECATED. Make search coupons don't go through ES
617 379 *
618 380 * @param bool $enabled Coupons enabled or not
619 381 * @param WP_Query $query WP Query
620 382 * @since 2.1
383 + * @deprecated 4.7.0
621 384 * @return bool
622 385 */
623 386 public function blacklist_coupons( $enabled, $query ) {
624 - if ( is_admin() ) {
625 - return $enabled;
626 - }
627 -
628 - if ( 'shop_coupon' === $query->get( 'post_type' ) && empty( $query->query_vars['ep_integrate'] ) ) {
629 - return false;
630 - }
631 -
632 - return $enabled;
387 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->disallow_coupons()" );
388 + return $this->disallow_coupons( $enabled, $query );
633 389 }
634 390
635 391 /**
636 - * Allow order creations on the front end to get synced
392 + * DEPRECATED. Allow order creations on the front end to get synced
637 393 *
638 394 * @since 2.1
639 395 * @param bool $override Original order perms check value
396 + * @deprecated 4.7.0
640 397 * @param int $post_id Post ID
641 398 * @return bool
642 399 */
643 400 public function bypass_order_permissions_check( $override, $post_id ) {
644 - $searchable_post_types = $this->get_admin_searchable_post_types();
645 -
646 - if ( in_array( get_post_type( $post_id ), $searchable_post_types, true ) ) {
647 - return true;
648 - }
649 -
650 - return $override;
401 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->price_filter()" );
402 + return $this->orders->bypass_order_permissions_check( $override, $post_id );
651 403 }
652 404
653 405 /**
654 - * Sets woocommerce meta search fields to an empty array if we are integrating the main query with ElasticSearch
406 + * DEPRECATED. Sets WooCommerce meta search fields to an empty array if we are integrating the main query with ElasticSearch
655 407 *
656 - * Woocommerce calls this action as part of its own callback on parse_query. We add this filter only if the query
408 + * WooCommerce calls this action as part of its own callback on parse_query. We add this filter only if the query
657 409 * is integrated with ElasticSearch.
658 410 * If we were to always return array() on this filter, we'd break admin searches when WooCommerce module is activated
659 411 * without the Protected Content Module
660 412 *
413 + * @deprecated 4.7.0
661 414 * @param \WP_Query $query Current query
662 415 */
663 416 public function maybe_hook_woocommerce_search_fields( $query ) {
664 - global $pagenow, $wp, $wc_list_table, $wp_filter;
665 -
666 - if ( ! $this->should_integrate_with_query( $query ) ) {
667 - return;
668 - }
669 -
670 - /**
671 - * Determines actions to be applied, or removed, if doing a WooCommerce serarch
672 - *
673 - * @hook ep_woocommerce_hook_search_fields
674 - * @since 4.4.0
675 - */
676 - do_action( 'ep_woocommerce_hook_search_fields' );
677 -
678 - if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
679 - return;
680 - }
681 -
682 - remove_action( 'parse_query', [ $wc_list_table, 'search_custom_fields' ] );
417 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->maybe_hook_woocommerce_search_fields()" );
418 + return $this->orders->maybe_hook_woocommerce_search_fields( $query );
683 419 }
684 420
685 421 /**
686 - * Enhance WooCommerce search order by order id, email, phone number, name, etc..
422 + * DEPRECATED. Enhance WooCommerce search order by order id, email, phone number, name, etc..
687 423 * What this function does:
688 424 * 1. Reverse the woocommerce shop_order_search_custom_fields query
689 425 * 2. If the search key is integer and it is an Order Id, just query with post__in
690 426 * 3. If the search key is integer but not an order id ( might be phone number ), use ES to find it
@@ -689,31 +425,18 @@
689 425 * 2. If the search key is integer and it is an Order Id, just query with post__in
690 426 * 3. If the search key is integer but not an order id ( might be phone number ), use ES to find it
691 427 *
692 428 * @param WP_Query $wp WP Query
429 + * @deprecated 4.7.0
693 430 * @since 2.3
694 431 */
695 432 public function search_order( $wp ) {
696 - if ( ! $this->should_integrate_with_query( $wp ) ) {
697 - return;
698 - }
699 -
700 - global $pagenow;
701 -
702 - $searchable_post_types = $this->get_admin_searchable_post_types();
703 -
704 - if ( 'edit.php' !== $pagenow || empty( $wp->query_vars['post_type'] ) || ! in_array( $wp->query_vars['post_type'], $searchable_post_types, true ) ||
705 - ( empty( $wp->query_vars['s'] ) && empty( $wp->query_vars['shop_order_search'] ) ) ) {
706 - return;
707 - }
708 -
709 - $search_key_safe = str_replace( array( 'Order #', '#' ), '', wc_clean( $_GET['s'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
710 - unset( $wp->query_vars['post__in'] );
711 - $wp->query_vars['s'] = $search_key_safe;
433 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->search_order()" );
434 + return $this->orders->search_order( $wp );
712 435 }
713 436
714 437 /**
715 - * Add order items as a searchable string.
438 + * DEPRECATED. Add order items as a searchable string.
716 439 *
717 440 * This mimics how WooCommerce currently does in the order_itemmeta
718 441 * table. They combine the titles of the products and put them in a
719 442 * meta field called "Items".
@@ -721,321 +444,86 @@
721 444 * @since 2.4
722 445 *
723 446 * @param array $post_args Post arguments
724 447 * @param string|int $post_id Post id
725 - *
448 + * @deprecated 4.7.0
726 449 * @return array
727 450 */
728 451 public function add_order_items_search( $post_args, $post_id ) {
729 - $searchable_post_types = $this->get_admin_searchable_post_types();
730 -
731 - // Make sure it is only WooCommerce orders we touch.
732 - if ( ! in_array( $post_args['post_type'], $searchable_post_types, true ) ) {
733 - return $post_args;
734 - }
735 -
736 - $post_indexable = Indexables::factory()->get( 'post' );
737 -
738 - // Get order items.
739 - $order = wc_get_order( $post_id );
740 - $item_meta = [];
741 - foreach ( $order->get_items() as $delta => $product_item ) {
742 - // WooCommerce 3.x uses WC_Order_Item_Product instance while 2.x an array
743 - if ( is_object( $product_item ) && method_exists( $product_item, 'get_name' ) ) {
744 - $item_meta['_items'][] = $product_item->get_name( 'edit' );
745 - } elseif ( is_array( $product_item ) && isset( $product_item['name'] ) ) {
746 - $item_meta['_items'][] = $product_item['name'];
747 - }
748 - }
749 -
750 - // Prepare order items.
751 - $item_meta['_items'] = empty( $item_meta['_items'] ) ? '' : implode( '|', $item_meta['_items'] );
752 - $post_args['meta'] = array_merge( $post_args['meta'], $post_indexable->prepare_meta_types( $item_meta ) );
753 -
754 - return $post_args;
452 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->add_order_items_search()" );
453 + return $this->orders->add_order_items_search( $post_args, $post_id );
755 454 }
756 455
757 456 /**
758 - * Add WooCommerce Product Attributes to EP Facets.
457 + * DEPRECATED. Add WooCommerce Product Attributes to EP Facets.
759 458 *
760 459 * @param array $taxonomies Taxonomies array
460 + * @deprecated 4.7.0
761 461 * @return array
762 462 */
763 463 public function add_product_attributes( $taxonomies = [] ) {
764 - $attribute_names = wc_get_attribute_taxonomy_names();
765 -
766 - foreach ( $attribute_names as $name ) {
767 - if ( ! taxonomy_exists( $name ) ) {
768 - continue;
769 - }
770 - $taxonomies[ $name ] = get_taxonomy( $name );
771 - }
772 -
773 - return $taxonomies;
464 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->add_product_attributes()" );
465 + return $this->products->add_product_attributes( $taxonomies );
774 466 }
775 467
776 468 /**
777 - * Add WooCommerce Fields to the Weighting Dashboard.
469 + * DEPRECATED. Add WooCommerce Fields to the Weighting Dashboard.
778 470 *
779 471 * @since 3.x
780 - *
472 + * @deprecated 4.7.0
781 473 * @param array $fields Current weighting fields.
782 474 * @param string $post_type Current post type.
783 475 * @return array New fields.
784 476 */
785 477 public function add_product_attributes_to_weighting( $fields, $post_type ) {
786 - if ( 'product' === $post_type ) {
787 - if ( ! empty( $fields['attributes']['children']['author_name'] ) ) {
788 - unset( $fields['attributes']['children']['author_name'] );
789 - }
790 -
791 - $sku_key = 'meta._sku.value';
792 -
793 - $fields['attributes']['children'][ $sku_key ] = array(
794 - 'key' => $sku_key,
795 - 'label' => __( 'SKU', 'elasticpress' ),
796 - );
797 -
798 - $variations_skus_key = 'meta._variations_skus.value';
799 -
800 - $fields['attributes']['children'][ $variations_skus_key ] = array(
801 - 'key' => $variations_skus_key,
802 - 'label' => __( 'Variations SKUs', 'elasticpress' ),
803 - );
804 - }
805 - return $fields;
478 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->add_product_attributes_to_weighting()" );
479 + return $this->products->add_product_attributes_to_weighting( $fields, $post_type );
806 480 }
807 481
808 482 /**
809 - * Add WooCommerce Fields to the default values of the Weighting Dashboard.
483 + * DEPRECATED. Add WooCommerce Fields to the default values of the Weighting Dashboard.
810 484 *
811 485 * @since 3.x
812 - *
486 + * @deprecated 4.7.0
813 487 * @param array $defaults Default values for the post type.
814 488 * @param string $post_type Current post type.
815 489 * @return array
816 490 */
817 491 public function add_product_default_post_type_weights( $defaults, $post_type ) {
818 - if ( 'product' === $post_type ) {
819 - if ( ! empty( $defaults['author_name'] ) ) {
820 - unset( $defaults['author_name'] );
821 - }
822 -
823 - $defaults['meta._sku.value'] = array(
824 - 'enabled' => true,
825 - 'weight' => 1,
826 - );
827 -
828 - $defaults['meta._variations_skus.value'] = array(
829 - 'enabled' => true,
830 - 'weight' => 1,
831 - );
832 - }
833 - return $defaults;
492 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->add_product_default_post_type_weights()" );
493 + return $this->products->add_product_default_post_type_weights( $defaults, $post_type );
834 494 }
835 495
836 496 /**
837 - * Add WC post type to autosuggest
497 + * DEPRECATED. Add WC post type to autosuggest
838 498 *
839 499 * @param array $post_types Array of post types (e.g. post, page).
840 500 * @since 2.6
501 + * @deprecated 4.7.0
841 502 * @return array
842 503 */
843 504 public function suggest_wc_add_post_type( $post_types ) {
844 - if ( ! in_array( 'product', $post_types, true ) ) {
845 - $post_types[] = 'product';
846 - }
847 -
848 - return $post_types;
505 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->suggest_wc_add_post_type()" );
506 + return $this->products->suggest_wc_add_post_type( $post_types );
849 507 }
850 508
851 509 /**
852 - * Setup all feature filters
510 + * DEPRECATED. Modifies main query to allow filtering by price with WooCommerce "Filter by price" widget.
853 511 *
854 - * @since 2.1
855 - */
856 - public function setup() {
857 - if ( ! function_exists( 'WC' ) ) {
858 - return;
859 - }
860 -
861 - add_action( 'ep_formatted_args', [ $this, 'price_filter' ], 10, 3 );
862 - add_filter( 'ep_sync_insert_permissions_bypass', [ $this, 'bypass_order_permissions_check' ], 10, 2 );
863 - add_filter( 'ep_integrate_search_queries', [ $this, 'blacklist_coupons' ], 10, 2 );
864 - add_filter( 'ep_prepare_meta_allowed_protected_keys', [ $this, 'whitelist_meta_keys' ], 10, 2 );
865 - add_filter( 'woocommerce_layered_nav_query_post_ids', [ $this, 'convert_post_object_to_id' ], 10, 4 );
866 - add_filter( 'woocommerce_unfiltered_product_ids', [ $this, 'convert_post_object_to_id' ], 10, 4 );
867 - add_filter( 'ep_sync_taxonomies', [ $this, 'whitelist_taxonomies' ], 10, 2 );
868 - add_filter( 'ep_post_sync_args_post_prepare_meta', [ $this, 'add_order_items_search' ], 20, 2 );
869 - add_filter( 'ep_pc_skip_post_content_cleanup', [ $this, 'keep_order_fields' ], 20, 2 );
870 - add_action( 'pre_get_posts', [ $this, 'translate_args' ], 11, 1 );
871 - add_action( 'ep_wp_query_search_cached_posts', [ $this, 'disallow_duplicated_query' ], 10, 2 );
872 - add_action( 'parse_query', [ $this, 'maybe_hook_woocommerce_search_fields' ], 1 );
873 - add_action( 'parse_query', [ $this, 'search_order' ], 11 );
874 - add_filter( 'ep_term_suggest_post_type', [ $this, 'suggest_wc_add_post_type' ] );
875 - add_filter( 'ep_facet_include_taxonomies', [ $this, 'add_product_attributes' ] );
876 - add_filter( 'ep_weighting_fields_for_post_type', [ $this, 'add_product_attributes_to_weighting' ], 10, 2 );
877 - add_filter( 'ep_weighting_default_post_type_weights', [ $this, 'add_product_default_post_type_weights' ], 10, 2 );
878 - add_filter( 'ep_prepare_meta_data', [ $this, 'add_variations_skus_meta' ], 10, 2 );
879 - add_filter( 'request', [ $this, 'admin_product_list_request_query' ], 9 );
880 -
881 - // Custom product ordering
882 - add_action( 'ep_admin_notices', [ $this, 'maybe_display_notice_about_product_ordering' ] );
883 - add_action( 'woocommerce_after_product_ordering', [ $this, 'action_sync_on_woocommerce_sort_single' ], 10, 2 );
884 -
885 - // Orders Autosuggest feature.
886 - if ( $this->is_orders_autosuggest_enabled() ) {
887 - $this->orders->setup();
888 - }
889 - }
890 -
891 - /**
892 - * Output feature box long
893 - *
894 - * @since 2.1
895 - */
896 - public function output_feature_box_long() {
897 - ?>
898 - <p><?php esc_html_e( 'Most caching and performance tools can’t keep up with the nearly infinite ways your visitors might filter or navigate your products. No matter how many products, filters, or customers you have, ElasticPress will keep your online store performing quickly. If used in combination with the Protected Content feature, ElasticPress will also accelerate order searches and back end product management.', 'elasticpress' ); ?></p>
899 - <?php
900 - }
901 -
902 - /**
903 - * Dashboard WooCommerce settings
904 - *
905 - * @since 4.5.0
906 - */
907 - public function output_feature_box_settings() {
908 - $available = $this->is_orders_autosuggest_available();
909 - $enabled = $this->is_orders_autosuggest_enabled();
910 - ?>
911 - <div class="field">
912 - <div class="field-name status"><?php esc_html_e( 'Orders Autosuggest', 'elasticpress' ); ?></div>
913 - <div class="input-wrap">
914 - <label><input name="settings[orders]" type="radio" <?php checked( $enabled ); ?> <?php disabled( $available, false, true ); ?> value="1"><?php echo wp_kses_post( __( 'Enabled', 'elasticpress' ) ); ?></label><br>
915 - <label><input name="settings[orders]" type="radio" <?php checked( ! $enabled ); ?> <?php disabled( $available, false, true ); ?> value="0"><?php echo wp_kses_post( __( 'Disabled', 'elasticpress' ) ); ?></label>
916 - <p class="field-description">
917 - <?php
918 - $epio_autosuggest_kb_link = 'https://elasticpress.zendesk.com/hc/en-us/articles/13374461690381-Configuring-ElasticPress-io-Order-Autosuggest';
919 -
920 - $message = ( $available ) ?
921 - /* translators: 1: <a> tag (ElasticPress.io); 2. </a>; 3: <a> tag (KB article); 4. </a>; */
922 - __( 'You are directly connected to %1$sElasticPress.io%2$s! Enable Orders Autosuggest to enhance Dashboard results and quickly find WooCommerce Orders. %3$sLearn More%4$s.', 'elasticpress' ) :
923 - /* translators: 1: <a> tag (ElasticPress.io); 2. </a>; 3: <a> tag (KB article); 4. </a>; */
924 - __( 'Due to the sensitive nature of orders, this autosuggest feature is available only to %1$sElasticPress.io%2$s customers. %3$sLearn More%4$s.', 'elasticpress' );
925 -
926 - printf(
927 - wp_kses( $message, 'ep-html' ),
928 - '<a href="https://elasticpress.io/" target="_blank">',
929 - '</a>',
930 - '<a href="' . esc_url( $epio_autosuggest_kb_link ) . '" target="_blank">',
931 - '</a>'
932 - );
933 - ?>
934 - </p>
935 - </div>
936 - </div>
937 - <?php
938 - }
939 -
940 - /**
941 - * Remove the author_name from search fields.
942 - *
943 - * @param array $search_fields Array of search fields.
944 - * @since 3.0
945 - * @return array
946 - */
947 - public function remove_author( $search_fields ) {
948 - foreach ( $search_fields as $field_key => $field ) {
949 - if ( 'author_name' === $field ) {
950 - unset( $search_fields[ $field_key ] );
951 - }
952 - }
953 -
954 - return $search_fields;
955 - }
956 -
957 - /**
958 - * Determine WC feature reqs status
959 - *
960 - * @since 2.2
961 - * @return EP_Feature_Requirements_Status
962 - */
963 - public function requirements_status() {
964 - $status = new FeatureRequirementsStatus( 0 );
965 -
966 - if ( ! class_exists( 'WooCommerce' ) ) {
967 - $status->code = 2;
968 - $status->message = esc_html__( 'WooCommerce not installed.', 'elasticpress' );
969 - }
970 -
971 - return $status;
972 - }
973 -
974 - /**
975 - * Modifies main query to allow filtering by price with WooCommerce "Filter by price" widget.
976 - *
977 512 * @param array $args ES args
978 513 * @param array $query_args WP_Query args
979 514 * @param WP_Query $query WP_Query object
980 515 * @since 3.2
516 + * @deprecated 4.7.0
981 517 * @return array
982 518 */
983 519 public function price_filter( $args, $query_args, $query ) {
984 - // Only can use widget on main query
985 - if ( ! $query->is_main_query() ) {
986 - return $args;
987 - }
988 -
989 - // Only can use widget on shop, product taxonomy, or search
990 - if ( ! is_shop() && ! is_product_taxonomy() && ! is_search() ) {
991 - return $args;
992 - }
993 -
994 - // phpcs:disable WordPress.Security.NonceVerification
995 - if ( empty( $_GET['min_price'] ) && empty( $_GET['max_price'] ) ) {
996 - return $args;
997 - }
998 -
999 - if ( $query->is_search() ) {
1000 - /**
1001 - * This logic is iffy but the WC price filter widget is not intended for use with search anyway
1002 - */
1003 - $old_query = $args['query']['bool'];
1004 - unset( $args['query']['bool']['should'] );
1005 -
1006 - if ( ! empty( $_GET['min_price'] ) ) {
1007 - $args['query']['bool']['must'][0]['range']['meta._price.long']['gte'] = $_GET['min_price'];
1008 - }
1009 -
1010 - if ( ! empty( $_GET['max_price'] ) ) {
1011 - $args['query']['bool']['must'][0]['range']['meta._price.long']['lte'] = $_GET['max_price'];
1012 - }
1013 -
1014 - $args['query']['bool']['must'][0]['range']['meta._price.long']['boost'] = 2.0;
1015 - $args['query']['bool']['must'][1]['bool'] = $old_query;
1016 - } else {
1017 - unset( $args['query']['match_all'] );
1018 -
1019 - $args['query']['range']['meta._price.long']['gte'] = ! empty( $_GET['min_price'] ) ? $_GET['min_price'] : 0;
1020 -
1021 - if ( ! empty( $_GET['min_price'] ) ) {
1022 - $args['query']['range']['meta._price.long']['gte'] = $_GET['min_price'];
1023 - }
1024 -
1025 - if ( ! empty( $_GET['max_price'] ) ) {
1026 - $args['query']['range']['meta._price.long']['lte'] = $_GET['max_price'];
1027 - }
1028 -
1029 - $args['query']['range']['meta._price.long']['boost'] = 2.0;
1030 - }
1031 - // phpcs:enable WordPress.Security.NonceVerification
1032 -
1033 - return $args;
520 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->price_filter()" );
521 + return $this->products->price_filter( $args, $query_args, $query );
1034 522 }
1035 523
1036 524 /**
1037 - * Prevent order fields from being removed.
525 + * DEPRECATED. Prevent order fields from being removed.
1038 526 *
1039 527 * When Protected Content is enabled, all posts with password have their content removed.
1040 528 * This can't happen for orders, as the order key is added in that field.
1041 529 *
@@ -1041,64 +529,34 @@
1041 529 *
1042 530 * @see https://github.com/10up/ElasticPress/issues/2726
1043 531 *
1044 532 * @since 4.2.0
533 + * @deprecated 4.7.0
1045 534 * @param bool $skip Whether the password protected content should have their content, and meta removed
1046 535 * @param array $post_args Post arguments
1047 536 * @return bool
1048 537 */
1049 538 public function keep_order_fields( $skip, $post_args ) {
1050 - $searchable_post_types = $this->get_admin_searchable_post_types();
1051 -
1052 - if ( in_array( $post_args['post_type'], $searchable_post_types, true ) ) {
1053 - return true;
1054 - }
1055 -
1056 - return $skip;
539 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->orders->keep_order_fields()" );
540 + return $this->orders->keep_order_fields( $skip, $post_args );
1057 541 }
1058 542
1059 543 /**
1060 - * Add a new `_variations_skus` meta field to the product to be indexed in Elasticsearch.
544 + * DEPRECATED. Add a new `_variations_skus` meta field to the product to be indexed in Elasticsearch.
1061 545 *
1062 546 * @since 4.2.0
547 + * @deprecated 4.7.0
1063 548 * @param array $post_meta Post meta
1064 549 * @param WP_Post $post Post object
1065 550 * @return array
1066 551 */
1067 552 public function add_variations_skus_meta( $post_meta, $post ) {
1068 - if ( 'product' !== $post->post_type ) {
1069 - return $post_meta;
1070 - }
1071 -
1072 - $product = wc_get_product( $post );
1073 - if ( ! $product ) {
1074 - return $post_meta;
1075 - }
1076 -
1077 - $variations_ids = $product->get_children();
1078 -
1079 - $post_meta['_variations_skus'] = array_reduce(
1080 - $variations_ids,
1081 - function ( $variations_skus, $current_id ) {
1082 - $variation = wc_get_product( $current_id );
1083 - if ( ! $variation || ! $variation->exists() ) {
1084 - return $variations_skus;
1085 - }
1086 - $variation_sku = $variation->get_sku();
1087 - if ( ! $variation_sku ) {
1088 - return $variations_skus;
1089 - }
1090 - $variations_skus[] = $variation_sku;
1091 - return $variations_skus;
1092 - },
1093 - []
1094 - );
1095 -
1096 - return $post_meta;
553 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->add_variations_skus_meta()" );
554 + return $this->products->add_variations_skus_meta( $post_meta, $post );
1097 555 }
1098 556
1099 557 /**
1100 - * Integrate ElasticPress with the WooCommerce Admin Product List.
558 + * DEPRECATED. Integrate ElasticPress with the WooCommerce Admin Product List.
1101 559 *
1102 560 * WooCommerce uses its `WC_Admin_List_Table_Products` class to control that screen. This
1103 561 * function adds all necessary hooks to bypass the default behavior and integrate with ElasticPress.
1104 562 * By default, WC runs a SQL query to get the Product IDs that match the list criteria and passes
@@ -1105,264 +563,77 @@
1105 563 * that list of IDs to the main WP_Query. This integration changes that process to a single query, run
1106 564 * by ElasticPress.
1107 565 *
1108 566 * @since 4.2.0
567 + * @deprecated 4.7.0
1109 568 * @param array $query_vars Query vars.
1110 569 * @return array
1111 570 */
1112 571 public function admin_product_list_request_query( $query_vars ) {
1113 - global $typenow, $wc_list_table;
1114 -
1115 - // Return if not in the correct screen.
1116 - if ( ! is_a( $wc_list_table, 'WC_Admin_List_Table_Products' ) || 'product' !== $typenow ) {
1117 - return $query_vars;
1118 - }
1119 -
1120 - // Return if admin WP_Query integration is not turned on, i.e., Protect Content is not enabled.
1121 - if ( ! has_filter( 'ep_admin_wp_query_integration', '__return_true' ) ) {
1122 - return $query_vars;
1123 - }
1124 -
1125 - /**
1126 - * Filter to skip integration with WooCommerce Admin Product List.
1127 - *
1128 - * @hook ep_woocommerce_integrate_admin_products_list
1129 - * @since 4.2.0
1130 - * @param {bool} $integrate True to integrate, false to preserve original behavior. Defaults to true.
1131 - * @param {array} $query_vars Query vars.
1132 - * @return {bool} New integrate value
1133 - */
1134 - if ( ! apply_filters( 'ep_woocommerce_integrate_admin_products_list', true, $query_vars ) ) {
1135 - return $query_vars;
1136 - }
1137 -
1138 - add_action( 'pre_get_posts', [ $this, 'translate_args_admin_products_list' ], 12 );
1139 -
1140 - // This short-circuits WooCommerce search for product IDs.
1141 - add_filter( 'woocommerce_product_pre_search_products', '__return_empty_array' );
1142 -
1143 - return $query_vars;
572 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->admin_product_list_request_query()" );
573 + return $this->products->admin_product_list_request_query( $query_vars );
1144 574 }
1145 575
1146 576 /**
1147 - * Apply the necessary changes to WP_Query in WooCommerce Admin Product List.
577 + * DEPRECATED. Apply the necessary changes to WP_Query in WooCommerce Admin Product List.
1148 578 *
1149 579 * @param WP_Query $query The WP Query being executed.
580 + * @deprecated 4.7.0
1150 581 */
1151 582 public function translate_args_admin_products_list( $query ) {
1152 - // The `translate_args()` method sets it to `true` if we should integrate it.
1153 - if ( ! $query->get( 'ep_integrate', false ) ) {
1154 - return;
1155 - }
1156 -
1157 - // WooCommerce unsets the search term right after using it to fetch product IDs. Here we add it back.
1158 - $search_term = ! empty( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1159 - if ( ! empty( $search_term ) ) {
1160 - $query->set( 's', sanitize_text_field( $search_term ) ); // phpcs:ignore WordPress.Security.NonceVerification
1161 -
1162 - /**
1163 - * Filter the fields used in WooCommerce Admin Product Search.
1164 - *
1165 - * ```
1166 - * add_filter(
1167 - * 'ep_woocommerce_admin_products_list_search_fields',
1168 - * function ( $wc_admin_search_fields ) {
1169 - * $wc_admin_search_fields['meta'][] = 'custom_field';
1170 - * return $wc_admin_search_fields;
1171 - * }
1172 - * );
1173 - * ```
1174 - *
1175 - * @hook ep_woocommerce_admin_products_list_search_fields
1176 - * @since 4.2.0
1177 - * @param {array} $wc_admin_search_fields Fields to be used in the WooCommerce Admin Product Search
1178 - * @return {array} New fields
1179 - */
1180 - $search_fields = apply_filters(
1181 - 'ep_woocommerce_admin_products_list_search_fields',
1182 - [
1183 - 'post_title',
1184 - 'post_content',
1185 - 'post_excerpt',
1186 - 'meta' => [
1187 - '_sku',
1188 - '_variations_skus',
1189 - ],
1190 - ]
1191 - );
1192 -
1193 - $query->set( 'search_fields', $search_fields );
1194 - }
1195 -
1196 - // Sets the meta query for `product_type` if needed. Also removed from the WP_Query by WC in `WC_Admin_List_Table_Products::query_filters()`.
1197 - $product_type_query = $query->get( 'product_type', '' );
1198 - $product_type_url = ! empty( $_GET['product_type'] ) ? sanitize_text_field( $_GET['product_type'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1199 - $allowed_prod_types = [ 'virtual', 'downloadable' ];
1200 - if ( empty( $product_type_query ) && ! empty( $product_type_url ) && in_array( $product_type_url, $allowed_prod_types, true ) ) {
1201 - $meta_query = $query->get( 'meta_query', [] );
1202 - $meta_query[] = [
1203 - 'key' => "_{$product_type_url}",
1204 - 'value' => 'yes',
1205 - ];
1206 - $query->set( 'meta_query', $meta_query );
1207 - }
1208 -
1209 - // Sets the meta query for `stock_status` if needed.
1210 - $stock_status_query = $query->get( 'stock_status', '' );
1211 - $stock_status_url = ! empty( $_GET['stock_status'] ) ? sanitize_text_field( $_GET['stock_status'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
1212 - $allowed_stock_status = [ 'instock', 'outofstock', 'onbackorder' ];
1213 - if ( empty( $stock_status_query ) && ! empty( $stock_status_url ) && in_array( $stock_status_url, $allowed_stock_status, true ) ) {
1214 - $meta_query = $query->get( 'meta_query', [] );
1215 - $meta_query[] = [
1216 - 'key' => '_stock_status',
1217 - 'value' => $stock_status_url,
1218 - ];
1219 - $query->set( 'meta_query', $meta_query );
1220 - }
583 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->price_filter()" );
584 + $this->products->translate_args_admin_products_list( $query );
1221 585 }
1222 586
1223 587 /**
1224 - * Determines whether or not ES should be integrating with the provided query
588 + * DEPRECATED. Depending on the number of products display an admin notice in the custom sort screen for WooCommerce Products
1225 589 *
1226 - * @param \WP_Query $query Query we might integrate with
1227 - *
1228 - * @return bool
1229 - */
1230 - protected function should_integrate_with_query( $query ) {
1231 - // Lets make sure this doesn't interfere with the CLI
1232 - if ( defined( 'WP_CLI' ) && WP_CLI ) {
1233 - return false;
1234 - }
1235 -
1236 - if ( defined( 'WC_API_REQUEST' ) && WC_API_REQUEST ) {
1237 - return false;
1238 - }
1239 -
1240 - if ( isset( $query->query_vars['ep_integrate'] ) && ! filter_var( $query->query_vars['ep_integrate'], FILTER_VALIDATE_BOOLEAN ) ) {
1241 - return false;
1242 - }
1243 -
1244 - /**
1245 - * Filter to skip WP Query integration
1246 - *
1247 - * @hook ep_skip_query_integration
1248 - * @param {bool} $skip True to skip
1249 - * @param {WP_Query} $query WP Query to evaluate
1250 - * @return {bool} New skip value
1251 - */
1252 - if ( apply_filters( 'ep_skip_query_integration', false, $query ) ) {
1253 - return false;
1254 - }
1255 -
1256 - if ( ! Utils\is_integrated_request( $this->slug ) ) {
1257 - return false;
1258 - }
1259 -
1260 - /**
1261 - * Do nothing for single product queries
1262 - */
1263 - $product_name = $query->get( 'product', false );
1264 - if ( ! empty( $product_name ) || $query->is_single() ) {
1265 - return false;
1266 - }
1267 -
1268 - /**
1269 - * ElasticPress does not yet support post_parent queries
1270 - */
1271 - $post_parent = $query->get( 'post_parent', false );
1272 - if ( ! empty( $post_parent ) ) {
1273 - return false;
1274 - }
1275 -
1276 - /**
1277 - * If this is just a preview, let's not use Elasticsearch.
1278 - */
1279 - if ( $query->get( 'preview', false ) ) {
1280 - return false;
1281 - }
1282 -
1283 - return true;
1284 - }
1285 -
1286 - /**
1287 - * Depending on the number of products display an admin notice in the custom sort screen for WooCommerce Products
1288 - *
1289 590 * @since 4.4.0
591 + * @deprecated 4.7.0
1290 592 * @param array $notices Current ElasticPress admin notices
1291 593 * @return array
1292 594 */
1293 595 public function maybe_display_notice_about_product_ordering( $notices ) {
1294 - global $pagenow, $wp_query;
1295 -
1296 - /**
1297 - * Make sure we're on edit.php in admin dashboard.
1298 - */
1299 - if ( ! is_admin() || 'edit.php' !== $pagenow || empty( $wp_query->query['orderby'] ) || 'menu_order title' !== $wp_query->query['orderby'] ) {
1300 - return $notices;
1301 - }
1302 -
1303 - $documents_per_page_sync = IndexHelper::factory()->get_index_default_per_page();
1304 - if ( $documents_per_page_sync >= $wp_query->found_posts ) {
1305 - return $notices;
1306 - }
1307 -
1308 - $notices['woocommerce_custom_sort'] = [
1309 - 'html' => sprintf(
1310 - /* translators: Sync Page URL */
1311 - __( 'Due to the number of products in the site, you will need to <a href="%s">resync</a> after applying a custom sort order.', 'elasticpress' ),
1312 - Utils\get_sync_url()
1313 - ),
1314 - 'type' => 'warning',
1315 - 'dismiss' => true,
1316 - ];
1317 -
1318 - return $notices;
596 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->maybe_display_notice_about_product_ordering()" );
597 + return $this->products->maybe_display_notice_about_product_ordering( $notices );
1319 598 }
1320 599
1321 600 /**
1322 - * Conditionally resync products after applying a custom order.
601 + * DEPRECATED. Conditionally resync products after applying a custom order.
1323 602 *
1324 603 * @since 4.4.0
604 + * @deprecated 4.7.0
1325 605 * @param int $sorting_id ID of post dragged and dropped
1326 606 * @param array $menu_orders Post IDs and their new menu_order value
1327 607 */
1328 608 public function action_sync_on_woocommerce_sort_single( $sorting_id, $menu_orders ) {
1329 -
1330 - $documents_per_page_sync = IndexHelper::factory()->get_index_default_per_page();
1331 - if ( $documents_per_page_sync < count( $menu_orders ) ) {
1332 - return;
1333 - }
1334 -
1335 - $sync_manager = Indexables::factory()->get( 'post' )->sync_manager;
1336 - foreach ( $menu_orders as $post_id => $order ) {
1337 - $sync_manager->add_to_queue( $post_id );
1338 - }
609 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->action_sync_on_woocommerce_sort_single()" );
610 + return $this->products->action_sync_on_woocommerce_sort_single( $sorting_id, $menu_orders );
1339 611 }
1340 612
1341 613 /**
1342 - * Whether orders autosuggest is available or not
614 + * DEPRECATED. Add weight by date settings related to WooCommerce
1343 615 *
1344 - * @since 4.5.0
1345 - * @return boolean
616 + * @since 4.6.0
617 + * @deprecated 4.7.0
618 + * @param array $settings Current settings.
1346 619 */
1347 - public function is_orders_autosuggest_available() : bool {
1348 - /**
1349 - * Whether the autosuggest feature is available for non
1350 - * ElasticPress.io customers.
1351 - *
1352 - * @since 4.5.0
1353 - * @hook ep_woocommerce_orders_autosuggest_available
1354 - * @param {boolean} $available Whether the feature is available.
1355 - */
1356 - return apply_filters( 'ep_woocommerce_orders_autosuggest_available', Utils\is_epio() );
620 + public function add_weight_settings_search( $settings ) {
621 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->add_weight_settings_search()" );
622 + $this->products->add_weight_settings_search( $settings );
1357 623 }
1358 624
1359 625 /**
1360 - * Whether orders autosuggest is enabled or not
626 + * DEPRECATED. Conditionally disable decaying by date based on WooCommerce Decay settings.
1361 627 *
1362 - * @since 4.5.0
1363 - * @return boolean
628 + * @since 4.6.0
629 + * @deprecated 4.7.0
630 + * @param bool $is_decaying_enabled Whether decay by date is enabled or not
631 + * @param array $settings Settings
632 + * @param array $args WP_Query args
633 + * @return bool
1364 634 */
1365 - public function is_orders_autosuggest_enabled() : bool {
1366 - return $this->is_orders_autosuggest_available() && '1' === $this->get_setting( 'orders' );
635 + public function maybe_disable_decaying( $is_decaying_enabled, $settings, $args ) {
636 + _deprecated_function( __METHOD__, '4.7.0', "\ElasticPress\Features::factory()->get_registered_feature( 'woocommerce' )->products->maybe_disable_decaying()" );
637 + return $this->products->maybe_disable_decaying( $is_decaying_enabled, $settings, $args );
1367 638 }
1368 639 }