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